From: vsr Date: Fri, 12 Nov 2010 14:22:21 +0000 (+0000) Subject: Merge from V5_1_5_BR branch 12/11/2010 X-Git-Tag: tag_Before_ViscLayers_PrototypeVersion~23 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=30be868bcd0dd1bea604af475f08f9107db292d2;p=modules%2Fsmesh.git Merge from V5_1_5_BR branch 12/11/2010 --- diff --git a/configure.ac b/configure.ac index 6551e4b4f..c388519f2 100644 --- a/configure.ac +++ b/configure.ac @@ -24,7 +24,7 @@ # Modified by : Alexander BORODIN (OCN) - autotools usage # Created from configure.in.base # -AC_INIT([Salome2 Project SMESH module], [5.1.4], [webmaster.salome@opencascade.com], [SalomeSMESH]) +AC_INIT([Salome2 Project SMESH module], [5.1.5], [webmaster.salome@opencascade.com], [SalomeSMESH]) AC_CONFIG_AUX_DIR(adm_local/unix/config_files) AC_CANONICAL_HOST AC_CANONICAL_TARGET @@ -434,6 +434,19 @@ echo # chmod +x ./bin/salome/*; \ #]) +AC_CONFIG_COMMANDS([hack_libtool],[ +sed -i "s%^CC=\"\(.*\)\"%hack_libtool (){ \n\ + if test \"\$(echo \$[@] | grep -E '\\\-L/usr/lib(/../lib)?(64)? ')\" == \"\" \n\ + then\n\ + cmd=\"\1 \$[@]\"\n\ + else\n\ + cmd=\"\1 \"\`echo \$[@] | sed -r -e 's|(.*)-L/usr/lib(/../lib)?(64)? (.*)|\\\1\\\4 -L/usr/lib\\\3|g'\`\n\ + fi\n\ + \$cmd\n\ +}\n\ +CC=\"hack_libtool\"%g" libtool +],[]) + # This list is initiated using autoscan and must be updated manually # when adding a new file .in to manage. When you execute # autoscan, the Makefile list is generated in the output file configure.scan. @@ -485,5 +498,3 @@ AC_OUTPUT([ \ idl/Makefile \ Makefile ]) - -AC_HACK_LIBTOOL diff --git a/doc/docutils/Makefile.am b/doc/docutils/Makefile.am index e1698bb9e..a757dd6f7 100644 --- a/doc/docutils/Makefile.am +++ b/doc/docutils/Makefile.am @@ -39,7 +39,7 @@ SPHINXBUILD = sphinx-build PAPEROPT_a4 = -D latex_paper_size=a4 ALLSPHINXOPTS = -d doctrees $(PAPEROPT_a4) $(SPHINXOPTS) $(SOURCEDIR) -SPHINX_PYTHONPATH = $(prefix)/lib/python$(PYTHON_VERSION)/site-packages/salome:$(KERNEL_ROOT_DIR)/bin/salome:$(KERNEL_ROOT_DIR)/lib/python$(PYTHON_VERSION)/site-packages/salome:$(OMNIORB_ROOT)/lib/python$(PYTHON_VERSION)/site-packages +SPHINX_PYTHONPATH = $(prefix)/lib/python$(PYTHON_VERSION)/site-packages/salome:$(prefix)/lib64/python$(PYTHON_VERSION)/site-packages/salome:$(KERNEL_ROOT_DIR)/bin/salome:$(KERNEL_ROOT_DIR)/lib/python$(PYTHON_VERSION)/site-packages/salome:$(KERNEL_ROOT_DIR)/lib64/python$(PYTHON_VERSION)/site-packages/salome:$(OMNIORB_ROOT)/lib/python$(PYTHON_VERSION)/site-packages:$(OMNIORB_ROOT)/lib64/python$(PYTHON_VERSION)/site-packages SPHINX_LD_LIBRARY_PATH = $(KERNEL_ROOT_DIR)/lib/salome:$(OMNIORB_ROOT)/lib diff --git a/doc/salome/gui/SMESH/Makefile.am b/doc/salome/gui/SMESH/Makefile.am index 40503e04e..1bb1e9bee 100755 --- a/doc/salome/gui/SMESH/Makefile.am +++ b/doc/salome/gui/SMESH/Makefile.am @@ -31,23 +31,21 @@ guidoc_DATA = images/head.png usr_docs: doxyfile_py doxyfile - echo "===========================================" ; \ - echo "Generating Python interface documentation"; \ - echo "===========================================" ; \ - $(DOXYGEN) doxyfile_py ; \ - echo "===========================================" ; \ - echo "Replacing smeshDC by smesh" ; \ - echo "===========================================" ; \ - files=`find smeshpy_doc -type f` ; \ - for filen in $${files} ; do \ - sed -e "s/\/smesh/g" -e "s/smesh\.smesh/smesh/g" \ - -e "s/smesh::smesh/smesh/g" $${filen} > $${filen}_ ; \ - mv -f $${filen}_ $${filen} ; \ - done ; \ - echo "===========================================" ; \ - echo "Generating GUI documentation" ; \ - echo "===========================================" ; \ - $(DOXYGEN) doxyfile ; + echo "===========================================" ; \ + echo "Replacing smeshDC by smesh" ; \ + echo "===========================================" ; \ + sed -e "/class smeshDC/d" -e "s/^ *#/#/g" -e "s/^ *def /def /g" \ + -e "s/smeshDC/smesh/g" $(top_srcdir)/src/SMESH_SWIG/smeshDC.py > \ + $(top_builddir)/src/SMESH_SWIG/smesh.py ; \ + echo "===========================================" ; \ + echo "Generating Python interface documentation"; \ + echo "===========================================" ; \ + $(DOXYGEN) doxyfile_py ; \ + echo "===========================================" ; \ + echo "Generating GUI documentation" ; \ + echo "===========================================" ; \ + $(DOXYGEN) doxyfile ; \ + rm -f $(top_builddir)/src/SMESH_SWIG/smesh.py docs: usr_docs diff --git a/doc/salome/gui/SMESH/doxyfile_py.in b/doc/salome/gui/SMESH/doxyfile_py.in index b381d0819..6053cdfd0 100755 --- a/doc/salome/gui/SMESH/doxyfile_py.in +++ b/doc/salome/gui/SMESH/doxyfile_py.in @@ -98,8 +98,8 @@ EXAMPLE_RECURSIVE = NO #--------------------------------------------------------------------------- #Input related options #--------------------------------------------------------------------------- -INPUT = @top_srcdir@/src/SMESH_SWIG -FILE_PATTERNS = smeshDC.py +INPUT = @top_builddir@/src/SMESH_SWIG +FILE_PATTERNS = smesh.py IMAGE_PATH = @srcdir@/images RECURSIVE = NO EXAMPLE_PATH = @top_srcdir@/src/SMESH_SWIG diff --git a/doc/salome/gui/SMESH/images/2d_from_3d_dlg.png b/doc/salome/gui/SMESH/images/2d_from_3d_dlg.png new file mode 100644 index 000000000..a03530978 Binary files /dev/null and b/doc/salome/gui/SMESH/images/2d_from_3d_dlg.png differ diff --git a/doc/salome/gui/SMESH/images/2d_from_3d_ico.png b/doc/salome/gui/SMESH/images/2d_from_3d_ico.png new file mode 100644 index 000000000..b0842d3e7 Binary files /dev/null and b/doc/salome/gui/SMESH/images/2d_from_3d_ico.png differ diff --git a/doc/salome/gui/SMESH/images/2d_from_3d_menu.png b/doc/salome/gui/SMESH/images/2d_from_3d_menu.png index ec5117214..acb7b349e 100644 Binary files a/doc/salome/gui/SMESH/images/2d_from_3d_menu.png and b/doc/salome/gui/SMESH/images/2d_from_3d_menu.png differ diff --git a/doc/salome/gui/SMESH/images/a-averagelength.png b/doc/salome/gui/SMESH/images/a-averagelength.png index 70e2afd26..c8ca5ac77 100755 Binary files a/doc/salome/gui/SMESH/images/a-averagelength.png and b/doc/salome/gui/SMESH/images/a-averagelength.png differ diff --git a/doc/salome/gui/SMESH/images/hypo_quad_params_dialog.png b/doc/salome/gui/SMESH/images/hypo_quad_params_dialog.png new file mode 100644 index 000000000..3cd442a8d Binary files /dev/null and b/doc/salome/gui/SMESH/images/hypo_quad_params_dialog.png differ diff --git a/doc/salome/gui/SMESH/images/netgen3d_simple.png b/doc/salome/gui/SMESH/images/netgen3d_simple.png index 959ec02c8..e2fca5cd9 100644 Binary files a/doc/salome/gui/SMESH/images/netgen3d_simple.png and b/doc/salome/gui/SMESH/images/netgen3d_simple.png differ diff --git a/doc/salome/gui/SMESH/input/1d_meshing_hypo.doc b/doc/salome/gui/SMESH/input/1d_meshing_hypo.doc index aba2b6598..367a0d0b5 100644 --- a/doc/salome/gui/SMESH/input/1d_meshing_hypo.doc +++ b/doc/salome/gui/SMESH/input/1d_meshing_hypo.doc @@ -5,7 +5,7 @@
  • \ref arithmetic_1d_anchor "Arithmetic 1D"
  • -
  • \ref average_length_anchor "Average Length"
  • +
  • \ref average_length_anchor "Local Length"
  • \ref max_length_anchor "Max Size"
  • \ref deflection_1d_anchor "Deflection 1D"
  • \ref number_of_segments_anchor "Number of segments"
  • @@ -57,9 +57,9 @@ locations and 1D mesh elements are constructed on segments.
    \anchor average_length_anchor -

    Average Length hypothesis

    +

    Local Length hypothesis

    -Average Length hypothesis can be applied for meshing of edges +Local Length hypothesis can be applied for meshing of edges composing your geometrical object. Definition of this hypothesis consists of setting the \b length of segments, which will split these edges, and the \b precision of rounding. The points on the edges @@ -79,10 +79,10 @@ integer. Default value is 1e-07. \image html a-averagelength.png -\image html b-erage_length.png "Average length hypothesis - all 1D mesh elements are roughly equal" +\image html b-erage_length.png "Local Length hypothesis - all 1D mesh elements are roughly equal" See Also a sample TUI Script of a -\ref tui_average_length "Defining Average Length" hypothesis +\ref tui_average_length "Defining Local Length" hypothesis operation.
    \anchor max_length_anchor @@ -157,7 +157,7 @@ operation. Start and End Length hypothesis allows to divide a geometrical edge into segments so that the first and the last segments have a specified -length. The length medium segments changes with automatically chosen +length. The length of medium segments changes with automatically chosen geometric progression. Then mesh nodes are constructed at segment ends location and 1D mesh elements are constructed on them. diff --git a/doc/salome/gui/SMESH/input/2d_meshing_hypo.doc b/doc/salome/gui/SMESH/input/2d_meshing_hypo.doc index 892cc9f74..d72e4d504 100644 --- a/doc/salome/gui/SMESH/input/2d_meshing_hypo.doc +++ b/doc/salome/gui/SMESH/input/2d_meshing_hypo.doc @@ -43,27 +43,58 @@ length calculated as an average edge length for a given wire. \anchor hypo_quad_params_anchor

    Quadrangle parameters

    -Quadrangle parameters is a hypothesis for -Quadrangle (Mapping), which allows using this algorithm for meshing of -triangular faces.In this case it is necessary to select the Base vertex -used as a degenerated edge. +\image html hypo_quad_params_dialog.png "Quadrangle parameters creation/edition dialog" + +Quadrangle parameters is a hypothesis for Quadrangle (Mapping). + +Base vertex parameter allows using Quadrangle (Mapping) +algorithm for meshing of triangular faces. In this case it is +necessary to select the vertex, which will be used as the fourth edge +(degenerated). \image html hypo_quad_params_1.png "A face built from 3 edges" \image html hypo_quad_params_res.png "The resulting mesh" -This hypothesis can be also used to mesh a segment of a circular face. -Please, consider that there is a limitation on the selectiion of the degenerated +This parameter can be also used to mesh a segment of a circular face. +Please, consider that there is a limitation on the selection of the vertex for the faces built with the angle > 180 degrees (see the picture). \image html hypo_quad_params_2.png "3/4 of a circular face" -In this case, selection of a wrong vertex for the Quadrangle parameters -hypothesis will generate a wrong mesh. The picture below +In this case, selection of a wrong vertex for the Base vertex +parameter will generate a wrong mesh. The picture below shows the good (left) and the bad (right) results of meshing. \image html hypo_quad_params_res_2.png "The resulting meshes" +Type parameter is used on faces with a different number of +segments on opposite sides to define the algorithm of transition +between them. The following types are available: + +
      +
    • Standard is the default case, when both triangles and quadrangles + are possible in the transition area along the finer meshed sides.
    • +
    • Triangle preference forces building only triangles in the + transition area along the finer meshed sides. + This type corresponds to Triangle Preference additional + hypothesis, which is obsolete now.
    • +
    • Quadrangle preference forces building only quadrangles in the + transition area along the finer meshed sides. This hypothesis has a + restriction: the total quantity of segments on all + four sides of the face must be even (divisible by 2).
    • + This type corresponds to Quadrangle Preference + additional hypothesis, which is obsolete now. +
    • Quadrangle preference (reversed) works in the same way and +with the same restriction as Quadrangle preference, but + the transition area is located along the coarser meshed sides.
    • +
    • Reduced type forces building only quadrangles and the transition + between the sides is made gradually, layer by layer. This type has + a limitation on the number of segments: one pair of opposite sides must have + the same number of segments, the other pair must have an even difference + between the numbers of segments on the sides.
    • +
    + See Also a sample TUI Script of a \ref tui_quadrangle_parameters "Quadrangle Parameters" hypothesis. diff --git a/doc/salome/gui/SMESH/input/about_filters.doc b/doc/salome/gui/SMESH/input/about_filters.doc index 98c74c424..22d88635f 100644 --- a/doc/salome/gui/SMESH/input/about_filters.doc +++ b/doc/salome/gui/SMESH/input/about_filters.doc @@ -2,8 +2,8 @@ \page filters_page About filters -\b Filters allows to pick only those mesh elements which satisfy to -specific condition or set of conditions. Filters can be used to create +\b Filters allow picking only the mesh elements satisfying to a +specific condition or a set of conditions. Filters can be used to create or edit mesh groups, remove elements from the mesh object, control mesh quality by different parameters, etc. @@ -18,15 +18,14 @@ The functinality of mesh filters is available in both GUI and TUI modes: - In GUI, filters are available in some dialog boxes via an additional -"Set Filters" button, clicking on which opens specific dialog box +"Set Filters" button, clicking on which opens the dialog box allowing to specify the list of filter criterions to be applied to the -current selection. Follow to the \subpage selection_filter_library_page page to learn more +current selection. See \subpage selection_filter_library_page page to learn more about selection filters and their usage in GUI. -- In Python scripts, filters can be used to choose only some of mesh - entities (nodes and/or elements) for the operations which require - list of the entities as input parameter (create/modify group, remove +- In Python scripts, filters can be used to choose only some mesh + entities (nodes and/or elements) for the operations, which require the + list of entities as input parameter (create/modify group, remove nodes/elements, etc). The page \ref tui_filters_page provides - examples of the filters usage in the Python scripts. - + examples of the filters usage in Python scripts. */ diff --git a/doc/salome/gui/SMESH/input/about_hypo.doc b/doc/salome/gui/SMESH/input/about_hypo.doc index bbce53d2c..5f989ec3d 100644 --- a/doc/salome/gui/SMESH/input/about_hypo.doc +++ b/doc/salome/gui/SMESH/input/about_hypo.doc @@ -17,7 +17,7 @@ them, you operate numerical values): edges):
    • \ref arithmetic_1d_anchor "Arithmetic 1D"
    • -
    • \ref average_length_anchor "Average Length"
    • +
    • \ref average_length_anchor "Local Length"
    • \ref max_length_anchor "Max Size"
    • \ref deflection_1d_anchor "Deflection 1D"
    • \ref number_of_segments_anchor "Number of segments"
    • diff --git a/doc/salome/gui/SMESH/input/adding_nodes_and_elements.doc b/doc/salome/gui/SMESH/input/adding_nodes_and_elements.doc index 5c99e8e79..c0168994b 100644 --- a/doc/salome/gui/SMESH/input/adding_nodes_and_elements.doc +++ b/doc/salome/gui/SMESH/input/adding_nodes_and_elements.doc @@ -27,23 +27,23 @@ following associated submenu will appear: From this submenu select the type of element which you would like to add to your mesh. -\note All dialogs for adding new node or element to the mesh (except for -the dialog for 0D elements) provide a possibility to add it -automatically to the specified group or to create it anew using -Add to group box, that allows to choose an existing group for -the created node or element or to give the name to a new group. By -default, the Add to group check box is switched off. If user +\note All dialogs for new node or element adding to the mesh (except for +the dialog for 0D elements) provide the possibility to automatically add +a node or element to the specified group or to create the anew using +Add to group box, that allows choosing an existing group for +the created node or element or giving the name to a new group. By +default, the Add to group check box is switched off. If the user swiches this check box on, the combo box listing all currently existing groups of the corresponding type becomes available. By -default, no any group is selected. In such a case, when user presses +default, no group is selected. In this case, when the user presses Apply or Apply & Close button, the warning message box -informing the user about the necessity to input new group name is -shown. The combo box lists both \ref standalone_group "standalone groups" -and \ref group_on_geom "groups on geometry". If the user has -chosen the group on geometry, he is warned and proposed to -\ref convert_to_standalone "convert this group to the standalone". -If user refuses converting operation, an operation is cancelled and -new node/element is not created! +informs the user about the necessity to input new group name. The +combo box lists both \ref standalone_group "standalone groups" +and \ref group_on_geom "groups on geometry". If the user chooses a +group on geometry, he is warned and proposed to +\ref convert_to_standalone "convert this group to standalone". +If the user rejects conversion operation, it is cancelled and +a new node/element is not created! diff --git a/doc/salome/gui/SMESH/input/adding_quadratic_elements.doc b/doc/salome/gui/SMESH/input/adding_quadratic_elements.doc index 83736c85d..921948630 100644 --- a/doc/salome/gui/SMESH/input/adding_quadratic_elements.doc +++ b/doc/salome/gui/SMESH/input/adding_quadratic_elements.doc @@ -18,23 +18,23 @@ one of the following: \image html image152.png -\note All dialogs for adding quadratic element to the mesh -provide a possibility to add new element -automatically to the specified group or to create it anew using -Add to group box, that allows to choose an existing group for -the created node or element or to give the name to a new group. By -default, the Add to group check box is switched off. If user +\note All dialogs for quadratic element adding to the mesh +provide the possibility to automatically add an element +to the specified group or to create the group anew using +Add to group box, that allows choosing an existing group for +the created node or element or giving the name to a new group. By +default, the Add to group check box is switched off. If the user swiches this check box on, the combo box listing all currently existing groups of the corresponding type becomes available. By -default, no any group is selected. In such a case, when user presses +default, no group is selected. In this case, when the user presses Apply or Apply & Close button, the warning message box -informing the user about the necessity to input new group name is -shown. The combo box lists both \ref standalone_group "standalone groups" -and \ref group_on_geom "groups on geometry". If the user has -chosen the group on geometry, he is warned and proposed to -\ref convert_to_standalone "convert this group to the standalone". -If user refuses converting operation, an operation is cancelled and -new node/element is not created! +informs the user about the necessity to input a new group name. The +combo box lists both \ref standalone_group "standalone groups" +and \ref group_on_geom "groups on geometry". If the user chooses a +group on geometry, he is warned and proposed to +\ref convert_to_standalone "convert this group to standalone". +If the user rejects conversion operation, it is cancelled and +a new quadratic element is not created. To create any Quadratic Element specify the nodes which will form your diff --git a/doc/salome/gui/SMESH/input/additional_hypo.doc b/doc/salome/gui/SMESH/input/additional_hypo.doc index 1205e19b0..81eab0be8 100644 --- a/doc/salome/gui/SMESH/input/additional_hypo.doc +++ b/doc/salome/gui/SMESH/input/additional_hypo.doc @@ -41,17 +41,20 @@ It allows Netgen 2D to build quadrangular meshes at any conditions. It allows Quadrangle (Mapping) to build quadrangular meshes even if the number of nodes at the opposite edges of a meshed face is not equal, -otherwise this mesh will contain some triangular elements. +otherwise this mesh will contain some triangular elements. This use +case is obsolete now. Use Quadrangle Parameters hypothesis with +type Quadrangle Preference set instead.
      This hypothesis has one restriction on its work: the total quantity of segments on all four sides of the face must be even (divisible by 2). -

      Triangle Preference

      +

      Triangle Preference (obsolete)

      This additional hypothesis can be used only together with Quadrangle (Mapping) algorithm. It allows to build triangular mesh faces in the refinement area if the number of nodes at the opposite edges of a meshed face is not equal, otherwise refinement area will contain some quadrangular elements. - +This hypothesis is obsolete now. Use Quadrangle Parameters +hypothesis with type Triangle Preference set instead. */ diff --git a/doc/salome/gui/SMESH/input/creating_groups.doc b/doc/salome/gui/SMESH/input/creating_groups.doc index 1b00a6174..85d633a22 100644 --- a/doc/salome/gui/SMESH/input/creating_groups.doc +++ b/doc/salome/gui/SMESH/input/creating_groups.doc @@ -26,7 +26,7 @@ SALOME Platform distinguishes between the two Group types: \anchor standalone_group

      "Standalone Group"

      Standalone Group consists of mesh elements, which you can define in -the next possible ways: +the following ways:
      • Choosing them manually with the mouse in the 3D Viewer. You can click on an element in the 3D viewer and it will be highlighted. After @@ -37,9 +37,8 @@ definite filter to selection of the elements of your group. See more about filters on the \ref selection_filter_library_page "Selection filter library" page.
      • By adding all existing entities of the chosen type to the -group. For this purpose, it is necessary to turn on the Select -All check box. In this mode, all controls which allow selection of -the entities manually or by filters, are disabled.
      • +group. For this turn on the Select All check box. In this +mode all controls, which allow selecting the entities manually or by filters, are disabled.
      To remove a selected element or elements from the list click the \b Remove button. The Sort List button allows to sort the list of IDs of diff --git a/doc/salome/gui/SMESH/input/double_nodes_page.doc b/doc/salome/gui/SMESH/input/double_nodes_page.doc index eb41ee747..063bcba5e 100644 --- a/doc/salome/gui/SMESH/input/double_nodes_page.doc +++ b/doc/salome/gui/SMESH/input/double_nodes_page.doc @@ -1,8 +1,11 @@ /*! -\page double_nodes_page Duplicating Nodes +\page double_nodes_page Duplicate Nodes \n This operation allows to duplicate nodes of your mesh. +Duplication consists in replacement of an existing mesh element by another one. +Lower level elements of the duplicated ones are cloned +automatically. To duplicate nodes:
        @@ -34,13 +37,13 @@ In this mode the dialog looks like: \image html duplicate01.png Parameters to be defined in this mode: -
          +
          • Group of nodes to duplicate (mandatory): these nodes will be duplicated.
          • Group of elements to replace nodes with new ones (optional): the duplicated nodes will be associated with these elements.
          • Construct group with newly created nodes option (checked by default): - if checked - the group with just created nodes will be builded.
          • -
        + if checked - the group with just created nodes will be built. +

    \anchor mode_with_elem_anchor @@ -51,15 +54,15 @@ In this mode the dialog looks like: \image html duplicate02.png Parameters to be defined in this mode: -
      +
      • Group of elements to duplicate (mandatory): these elements will be duplicated.
      • Group of nodes at not to duplicate (optional): group of nodes at crack bottom which will not be duplicated.
      • Group of elements to replace nodes with new ones (mandatory): the duplicated nodes will be associated with these elements.
      • Construct group with newly created elements option (checked by default): - if checked - the group with just created elements will be builded.
      • -
    + if checked - the group with just created elements will be built. +

See Also a sample TUI Script of a \ref tui_duplicate_nodes "Duplicate nodes" operation. diff --git a/doc/salome/gui/SMESH/input/index.doc b/doc/salome/gui/SMESH/input/index.doc index af0f76f16..0975842ae 100644 --- a/doc/salome/gui/SMESH/input/index.doc +++ b/doc/salome/gui/SMESH/input/index.doc @@ -25,6 +25,10 @@ array of dedicated operations. Almost all mesh module functionalities are accessible via \subpage smeshpy_interface_page "Mesh module Python interface". +Also it can be useful to have a look at the +\subpage smeshpypkg_page "documentation on SMESH python package". + + \image html image7.jpg "Example of MESH module usage for engineering tasks" */ diff --git a/doc/salome/gui/SMESH/input/make_2dmesh_from_3d.doc b/doc/salome/gui/SMESH/input/make_2dmesh_from_3d.doc index f4b5b2ba5..e52078629 100644 --- a/doc/salome/gui/SMESH/input/make_2dmesh_from_3d.doc +++ b/doc/salome/gui/SMESH/input/make_2dmesh_from_3d.doc @@ -1,22 +1,58 @@ /*! -\page make_2dmesh_from_3d_page Generate the skin elements (2D) of a mesh having 3D elements +\page make_2dmesh_from_3d_page Generate boundary elements -\n This functionality allows to generate 2D mesh elements as a skin -on the existing 3D mesh elements. +\n This functionality allows to generate mesh elements on the borders of +elements of a higher dimension. -To generate 2D mesh: +To generate border elements:
    -
  1. From the Modification menu choose "Create 2D mesh from 3D" -item, or choose from the popup menu. +
  2. From the Modification menu choose "Create boundary elements" +item, or click "Create boundary elements" button in the toolbar -\image html 2d_from_3d_menu.png +\image html 2d_from_3d_ico.png "Create boundary elements icon" -The algorithm detects boundary volume faces without connections to -other volumes and creates 2D mesh elements on face nodes. If the mesh -already contains 2D elements on the detected nodes, new elements are not -created. The the resulting dialog shows mesh information statistics -about the newly created 2D mesh elements. +The following dialog box will appear: +\image html 2d_from_3d_dlg.png "Create boundary elements dialog box". +
  3. +
  4. Check in the dialog box one of three radio buttons corresponding to +the type of operation you would like to perform.
  5. +
  6. Fill the other fields available in the dialog box.
  7. +
  8. Click the \b Apply or Apply and Close button to perform the operation.
+\n "Create boundary elements" dialog allows creation of boundary elements +of three types. +
    +
  • 2D from 3D creates mesh faces on free facets of volume elements
  • +
  • 1D from 2D creates mesh edges on free edges of mesh faces
  • +
  • 1D from 3D creates mesh edges on all borders of free facets of volume elements
  • +
+Here a free facet means a facet shared by only one volume, a free edge +means an edge shared by only one mesh face. + +In this dialog: +
    +
  • specify the Mesh, submesh or group, the boundary which of +will be analyzed.
  • +
  • specify the Target mesh, where the boundary elements will + be created. +
      +
    • This mesh adds elements in the selected mesh or the mesh + the selected submesh or group belongs to.
    • +
    • New mesh adds elements to a new mesh. The new mesh appears + in the Object Browser with the name that you can change in the adjacent box.
    • +
  • +
  • activate Copy source mesh checkbox to copy 2D or 3D + elements (depending on the operation type), which belong to the analyzed +Mesh, submesh or group field, to the new mesh.
  • +
  • deactivate Copy missing elements only checkbox to copy + boundary elements already present in the analyzed mesh to the + new mesh.
  • +
  • activate Create group checkbox to create a group to which the + missing boundary elements are added. The new group appears + in the Object Browser with the name that you can change in the adjacent box.
  • +
+
See Also a sample TUI Script of a \ref tui_make_2dmesh_from_3d "Create boundary elements" operation. + */ diff --git a/doc/salome/gui/SMESH/input/modifying_meshes.doc b/doc/salome/gui/SMESH/input/modifying_meshes.doc index 8d5875a9c..45e746da4 100644 --- a/doc/salome/gui/SMESH/input/modifying_meshes.doc +++ b/doc/salome/gui/SMESH/input/modifying_meshes.doc @@ -18,7 +18,9 @@ elements of the mesh. its elements.
  • \subpage rotation_page "Rotate" by the indicated axis and angle the mesh or some of its elements.
  • -
  • \subpage scale_page "Scale Transform" the mesh or some of its elements.
  • +
  • \subpage scale_page "Scale Transform" the mesh or some of its +elements.
  • +
  • \subpage double_nodes_page "Duplicate nodes".
  • Create a \subpage symmetry_page "symmetrical copy" of the mesh through a point or a vector of symmetry.
  • Unite meshes by \subpage sewing_meshes_page "sewing" free borders, @@ -45,8 +47,7 @@ of the selected node or edge.
  • Apply \subpage pattern_mapping_page "pattern mapping".
  • \subpage convert_to_from_quadratic_mesh_page "Convert regular mesh to quadratic", or vice versa.
  • -
  • Create \subpage double_nodes_page "double nodes".
  • -
  • \subpage make_2dmesh_from_3d_page "Create 2D mesh from 3D".
  • +
  • \subpage make_2dmesh_from_3d_page "Generate boundary elements".
  • diff --git a/doc/salome/gui/SMESH/input/netgen_2d_3d_hypo.doc b/doc/salome/gui/SMESH/input/netgen_2d_3d_hypo.doc index bbb7c59ff..7fd71550a 100644 --- a/doc/salome/gui/SMESH/input/netgen_2d_3d_hypo.doc +++ b/doc/salome/gui/SMESH/input/netgen_2d_3d_hypo.doc @@ -42,8 +42,8 @@ dimension. - Number of Segments has the same sense as \ref number_of_segments_anchor "Number of segments" hypothesis with equidistant distribution. -- Average Length has the same sense as \ref -average_length_anchor "Average Length" hypothesis. +- Local Length has the same sense as \ref +average_length_anchor "Local Length" hypothesis. \b 2D group allows defining the size of 2D elements - Length from edges if checked in, acts like \ref diff --git a/doc/salome/gui/SMESH/input/pattern_mapping.doc b/doc/salome/gui/SMESH/input/pattern_mapping.doc index 1a48a4644..ef7f8ba66 100644 --- a/doc/salome/gui/SMESH/input/pattern_mapping.doc +++ b/doc/salome/gui/SMESH/input/pattern_mapping.doc @@ -5,33 +5,31 @@

    About patterns

    The pattern describes a mesh to generate: positions of nodes within a -geometrical domain and nodal connectivity of elements. As well, a -pattern specifies the so-called key-points, i.e. nodes that will be -located at geometrical vertices. Pattern description is stored in +geometrical domain and nodal connectivity of elements. A +pattern also specifies the so-called key-points, i.e. the nodes that will be +located at geometrical vertices. The pattern description is stored in \.smp file. The smp file contains 4 sections: --# The first line holds the total number of the pattern nodes (N). --# The next N lines describe nodes coordinates. Each line holds 2 -coordinates of a node for 2D pattern or 3 cordinates for 3D pattern. -Note, that for 3D pattern only relateive values in range [0;1] are -valid for coordinates of the nodes. --# A key-points line: indices of nodes to be mapped on geometrical -vertices (for 2D pattern only). An index n refers to a node described -on an n-th line of section 2. The first node index is zero. For 3D -pattern key points are not specified. --# The rest lines describe nodal connectivity of elements, one line -for an element. A line holds indices of nodes forming an element. An -index n refers to a node described on an n-th line of the section -2. The first node index is zero. There must be 3 or 4 indices on a -line for 2D pattern (only 2d elements are allowed) and 4, 5, 6 or 8 -indices for 3D pattern (only 3d elements are allowed). - -The 2D pattern must contain at least one element and at least one -key-point. All key-points must lay on boundaries. - -The 3D pattern must contain at least one element. +-# The first line indicates the total number of pattern nodes (N). +-# The next N lines describe nodes coordinates. Each line contains 2 +node coordinates for a 2D pattern or 3 node cordinates for a 3D pattern. +Note, that node coordinates of a 3D pattern can be defined only by relative values in range [0;1]. +-# The key-points line contains the indices of the nodes to be mapped on geometrical +vertices (for a 2D pattern only). Index n refers to the node described +on the n-th line of section 2. The index of the first node zero. For a 3D pattern the key points are not specified. +-# The remaining lines describe nodal connectivity of elements, one line +for each element. Each line holds indices of nodes forming an element. +Index n refers to the node described on the n-th line of section 2. +The first node index is zero. There must be 3 or 4 indices on each +line for a 2D pattern (only 2d elements are allowed) and 4, 5, 6 or 8 +indices for a 3D pattern (only 3d elements are allowed). + +A 2D pattern must contain at least one element and at least one +key-point. All key-points must lie on boundaries. + +A 3D pattern must contain at least one element. An example of a simple 2D pattern smp file: @@ -60,7 +58,7 @@ An example of a simple 2D pattern smp file: 8 1 2 \endcode -The image below provides a preview of above described pattern: +The image below provides a preview of the above pattern: \image html pattern2d.png @@ -99,91 +97,120 @@ From the \b Modification menu choose the Pattern Mapping item or click \image html image98.png
    "Pattern mapping" button
    -The following dialog box shall appear: +The following dialog box will appear: + +\n For a 2D pattern \image html patternmapping1.png -
    2D Pattern Mapping dialog box
    +In this dialog you should specify: + +
      +
    • \b Pattern, which can be loaded from .smp pattern file previously +created manually or generated automatically from an existing mesh or submesh.
    • +
    • \b Face with the number of vertices equal to the number of + key-points in the pattern; the number of key-points on internal + boundaries of the pattern must also be equal to the number of vertices + on internal boundaries of the face;
    • +
    • \b Vertex to which the first key-point should be mapped;
    • +Alternatively, it is possible to select Refine selected mesh elements +checkbox and apply the pattern to +
    • Mesh Face instead of a geometric Face
    • +
    • and select \b Node instead of vertex.
    • + +Additionally it is possible to: +
    • Reverse the order of key-points By default, the vertices of + a face are ordered counterclockwise.
    • +
    • Enable to Create polygons near boundary
    • +
    • and Create polyhedrons near boundary
    • +
    + +\n For a 3D pattern \image html patternmapping2.png -
    3D Pattern Mapping dialog box
    +In this dialog you should specify: +
      +
    • \b Pattern, which can be loaded from .smp pattern file previously +created manually or generated automatically from an existing mesh or submesh.
    • +
    • A 3D block (Solid) object;
    • +
    • Two vertices that specify the order of nodes in the resulting mesh.
    • +Alternatively, it is possible to select Refine selected mesh elements +checkbox and apply the pattern to +
    • One or several Mesh volumes instead of a geometric 3D +object
    • +
    • and select two /b Nodes instead of vertices.
    • +Additionally it is possible to: +
    • Enable to Create polygons near boundary
    • +
    • and Create polyhedrons near boundary
    • +
    + +\n Automatic Generation + +To generate a pattern automatically from an existing mesh or submesh, +click \b New button. + +The following dialog box will appear: -To apply a pattern to a geometrical object, you should specify: +\image html a-patterntype1.png --# For 2D pattern - - A face having the number of vertices equal to the number of - key-points in the pattern; the number of key-points on internal - boundaries of a pattern must also be equal to the number of vertices - on internal boundaries of a face; - - A vertex to which the first key-point should be mapped; - - Reverse or not the order of key-points. (The order of vertices of - a face is counterclockwise looking from outside). --# For 3D pattern - - 3D block (Solid) object; - - Two vertices that specify the order of nodes in the resulting - mesh. - -Then you either load a .smp pattern file previously created manually -by clicking on the "Load pattern" button, or click on the \b -New button for automatic generation of the pattern. - -For an automatic generation you just specify a geometrical face (for -2D) or solid (for 3d) having a mesh built on it. Mesh nodes lying on -face vertices become key-points of 2D pattern. Additionally, for 2D -pattern you may choose the way of getting nodes coordinates by -projecting nodes on the face instead of using -"positions on face" generated by mesher (if there is any). Faces -having a seam edge can't be used for automatic pattern creation. - -When creating a pattern from an existing mesh, there are two possible -cases: - -- A sub-mesh on face/solid is selected. A pattern is created from the 2d/3d -elements bound to a face/solid by mesher. For 2D pattern, node coordinates are either -"positions on face" computed by mesher, or coordinates got by node -projection on a geometrical surface, according to the user choice. For -3D pattern, nodes coordinates correspond to the nodes computed by mesher. -- A mesh where the main shape is a face/solid, is selected. A pattern is -created from all the 2d/3d elements in a mesh. In addition, for 2D -pattern, if all mesh elements are build by mesher, the user can select -the way of getting nodes coordinates, else all nodes are projected on -a face surface. +In this dialog you should specify: -\image html a-patterntype.png +
      +
    • Mesh or Submesh, which is a meshed geometrical face (for a +2D pattern) or a meshed solid (for a 3D pattern). Mesh nodes lying on +the face vertices become key-points of the pattern.
    • +
    • A custom Pattern Name
    • +
    • Additionally, for a 2D pattern you may choose to +Project nodes on the face to get node coordinates instead of using +"positions on face" generated by the mesher (if there is any). The faces +having a seam edge cannot be used for automatic pattern creation.
    • +
    -
    2D Pattern Creation dialog box
    +When a pattern is created from an existing mesh, two cases are possible: -\image html a-patterntype1.png +- A sub-mesh on a face/solid is selected. The pattern is created from the 2d/3d +elements bound to the face/solid by the mesher. For a 2D pattern, the node coordinates are either +"positions on face" computed by the mesher, or coordinates got by node +projection on a geometrical surface, according to the user choice. For +a 3D pattern, the node coordinates correspond to the nodes computed by +the mesher. +- A mesh, where the main shape is a face/solid, is selected. The pattern is +created from all 2d/3d elements in a mesh. In addition, if all mesh +elements of a 2D pattern are built by the mesher, the user can select +how to get node coordinates, otherwise all nodes are projected on +a face surface. -
    3D Pattern Creation dialog box

    Mapping algorithm

    -The mapping algorithm for 2D case is as follows: - -- Key-points are set in the order that they are encountered when - walking along a pattern boundary so that elements are on the left. The - first key-point is preserved. -- Find geometrical vertices corresponding to key-points by vertices - order in a face boundary; here, "Reverse order of key-points" flag is - taken into account. \image html image95.gif -- Boundary nodes of a pattern are mapped onto edges of a face: a - node located between certain key-points on a pattern boundary is - mapped on a geometrical edge limited by corresponding geometrical - vertices. Node position on an edge reflects its distance from two - key-points. \image html image96.gif -- Coordinates of a non-boundary node in a parametric space of a face - are defined as following. In a parametric space of a pattern, a node - lays at the intersection of two iso-lines, each of which intersects a - pattern boundary at least at two points. Knowing mapped positions of - boundary nodes, we find where isoline-boundary intersection points are - mapped to, and hence we can find mapped isolines direction and then, - two node positions on two mapped isolines. The eventual mapped - position of a node is found as an average of positions on mapped - isolines. \image html image97.gif - -For 3D case the algorithm is similar. +The mapping algorithm for a 2D case is as follows: + +- The key-points are set counterclockwise in the order corresponding + to their location on the pattern boundary. The first key-point is preserved. +- The geometrical vertices corresponding to the key-points are found + on face boundary. Here, "Reverse order of key-points" flag is set. +\image html image95.gif +- The boundary nodes of the pattern are mapped onto the edges of the face: a + node located between two key-points on the pattern boundary is + mapped on the geometrical edge limited by the corresponding geometrical + vertices. The node position on the edge depends on its distance from the + key-points. +\image html image96.gif +- The cordinates of a non-boundary node in the parametric space of the face + are defined in the following way. In the parametric space of the + pattern, the node lies at the intersection of two iso-lines. Both + of them intersect the pattern boundary at two + points at least. If the mapped positions of boundary nodes are known, it is + possible to find, where the points at the intersection of isolines + and boundaries are mapped. Then it is possible to find + the direction of mapped isolinesection and, filally, the poitions of + two nodes on two mapped isolines. The eventual mapped + position of the node is found as an average of the positions on mapped + isolines. +\image html image97.gif + +The 3D algorithm is similar. See Also a sample TUI Script of a \ref tui_pattern_mapping "Pattern Mapping" operation. diff --git a/doc/salome/gui/SMESH/input/removing_nodes_and_elements.doc b/doc/salome/gui/SMESH/input/removing_nodes_and_elements.doc index aef20c8ad..0a48ee65e 100644 --- a/doc/salome/gui/SMESH/input/removing_nodes_and_elements.doc +++ b/doc/salome/gui/SMESH/input/removing_nodes_and_elements.doc @@ -51,14 +51,14 @@ node of your mesh all adjacent elements will be also deleted. \anchor removing_orphan_nodes_anchor

    Removing orphan nodes

    -There is a quick way to remove all the orphan (free) nodes. +There is a quick way to remove all orphan (free) nodes. -To remove the orphan nodes: +To remove orphan nodes:
    1. Select your mesh in the Object Browser or in the 3D viewer.
    2. From the Modification menu choose Remove and from the associated -submenu select the Orphan Nodes, or just click "Remove orphan nodes" +submenu select Orphan Nodes, or just click "Remove orphan nodes" button in the toolbar. \image html remove_orphan_nodes_icon.png @@ -68,7 +68,7 @@ The following Warning message box will appear: \image html removeorphannodes.png -Confirm removing nodes by pressing "Yes" button. +Confirm nodes removal by pressing "Yes" button.

    diff --git a/doc/salome/gui/SMESH/input/selection_filter_library.doc b/doc/salome/gui/SMESH/input/selection_filter_library.doc index 94dd3844c..c01dc0a54 100644 --- a/doc/salome/gui/SMESH/input/selection_filter_library.doc +++ b/doc/salome/gui/SMESH/input/selection_filter_library.doc @@ -156,6 +156,12 @@ See also a length, which is more, less or equal (within a given Tolerance) to the predefined Threshold Value. See also a \ref length_2d_page "Length 2D quality control". +
  • +Coplanar faces selects mesh faces neighboring the one selected +by ID in Threshold Value field, if the angle between the +normal to the neighboring face and the normal to the selected face is less then the +angular tolerance (defined in degrees). Selection continues among all neighbor faces of already +selected ones.
  • diff --git a/doc/salome/gui/SMESH/input/tui_defining_hypotheses.doc b/doc/salome/gui/SMESH/input/tui_defining_hypotheses.doc index 1aa91d9d5..9932991f8 100644 --- a/doc/salome/gui/SMESH/input/tui_defining_hypotheses.doc +++ b/doc/salome/gui/SMESH/input/tui_defining_hypotheses.doc @@ -128,7 +128,7 @@ hexa.Compute()
    \anchor tui_average_length -

    Average Length

    +

    Local Length

    \code from geompy import * @@ -549,7 +549,7 @@ mesh.Compute() \endcode \anchor tui_quadrangle_parameters -

    Quadrangle Parameters example

    +

    Quadrangle Parameters example 1 (meshing a face with 3 edges)

    \code import geompy import smesh @@ -570,7 +570,7 @@ Mesh_1 = smesh.Mesh(Common_1) Quadrangle_Parameters_1 = smesh.CreateHypothesis('QuadrangleParams') Quadrangle_Parameters_1.SetTriaVertex( 8 ) -# Define 1D hypothesis and cmpute the mesh +# Define 1D hypothesis and compute the mesh Regular_1D = Mesh_1.Segment() Nb_Segments_1 = Regular_1D.NumberOfSegments(10) Nb_Segments_1.SetDistrType( 0 ) @@ -579,6 +579,56 @@ Quadrangle_2D = Mesh_1.Quadrangle() Mesh_1.Compute() \endcode +

    Quadrangle Parameters example 2 (using different types)

    +\code +import geompy +import smesh +import StdMeshers + +# Make quadrangle face and explode it on edges. +Vertex_1 = geompy.MakeVertex(0, 0, 0) +Vertex_2 = geompy.MakeVertex(40, 0, 0) +Vertex_3 = geompy.MakeVertex(40, 30, 0) +Vertex_4 = geompy.MakeVertex(0, 30, 0) +Quadrangle_Face_1 = geompy.MakeQuad4Vertices(Vertex_1, Vertex_4, Vertex_3, Vertex_2) +[Edge_1,Edge_2,Edge_3,Edge_4] = geompy.SubShapeAllSorted(Quadrangle_Face_1, geompy.ShapeType["EDGE"]) +geompy.addToStudy( Vertex_1, "Vertex_1" ) +geompy.addToStudy( Vertex_2, "Vertex_2" ) +geompy.addToStudy( Vertex_3, "Vertex_3" ) +geompy.addToStudy( Vertex_4, "Vertex_4" ) +geompy.addToStudy( Quadrangle_Face_1, "Quadrangle Face_1" ) +geompy.addToStudyInFather( Quadrangle_Face_1, Edge_2, "Edge_2" ) + +# Set the Geometry for meshing +Mesh_1 = smesh.Mesh(Quadrangle_Face_1) + +# Create Quadrangle parameters and +# define the Type as Quadrangle Preference +Quadrangle_Parameters_1 = smesh.CreateHypothesis('QuadrangleParams') +Quadrangle_Parameters_1.SetQuadType( StdMeshers.QUAD_QUADRANGLE_PREF ) + +# Define other hypotheses and algorithms +Regular_1D = Mesh_1.Segment() +Nb_Segments_1 = Regular_1D.NumberOfSegments(4) +Nb_Segments_1.SetDistrType( 0 ) +status = Mesh_1.AddHypothesis(Quadrangle_Parameters_1) +Quadrangle_2D = Mesh_1.Quadrangle() + +# Define submesh on one edge to provide different number of segments +Regular_1D_1 = Mesh_1.Segment(geom=Edge_2) +Nb_Segments_2 = Regular_1D_1.NumberOfSegments(10) +Nb_Segments_2.SetDistrType( 0 ) +SubMesh_1 = Regular_1D_1.GetSubMesh() + +# Compute mesh (with Quadrangle Preference type) +isDone = Mesh_1.Compute() + +# Change type to Reduced and compute again +Quadrangle_Parameters_1.SetQuadType( StdMeshers.QUAD_REDUCED ) +isDone = Mesh_1.Compute() +\endcode + + \n Other meshing algorithms:
      diff --git a/doc/salome/gui/SMESH/input/tui_filters.doc b/doc/salome/gui/SMESH/input/tui_filters.doc index ad6dd5929..0a4fccd3b 100755 --- a/doc/salome/gui/SMESH/input/tui_filters.doc +++ b/doc/salome/gui/SMESH/input/tui_filters.doc @@ -2,8 +2,8 @@ \page tui_filters_page Filters usage -Filters allows to pick only those mesh elements which satisfy to -specific condition or set of conditions. Filters can be used to create +Filters allow picking only the mesh elements satisfying to a +specific condition or a set of conditions. Filters can be used to create or edit mesh groups, remove elements from the mesh object, control mesh quality by different parameters, etc. @@ -12,10 +12,10 @@ AND and \a OR. In addition, applied filter criterion can be reverted using logical operator \a NOT. Mesh filters use the functionality of mesh quality controls to filter -mesh nodes / elements by specific characteristic (Area, Length, etc). +mesh nodes / elements by a specific characteristic (Area, Length, etc). This page provides a short description of the existing mesh filters, -describing required parameters and gives simple examples of usage in +describes required parameters and gives simple examples of usage in Python scripts. \sa \ref tui_quality_controls_page diff --git a/doc/salome/gui/SMESH/input/tui_transforming_meshes.doc b/doc/salome/gui/SMESH/input/tui_transforming_meshes.doc index e50fcda36..22f11886f 100644 --- a/doc/salome/gui/SMESH/input/tui_transforming_meshes.doc +++ b/doc/salome/gui/SMESH/input/tui_transforming_meshes.doc @@ -421,4 +421,167 @@ if salome.sg.hasDesktop(): salome.sg.updateObjBrowser(0) \endcode +
      +\anchor tui_make_2dmesh_from_3d +

      Create boundary elements

      + +\code +# The objective of these samples is to illustrate the following use cases: +# 1) The mesh MESH1 with 3D cells has no or only a part of its skin (2D cells): +# 1.1) Add the 2D skin (missing 2D cells) to MESH1 (what is done now by the algorithm). +# 1.2) Create a new 3D Mesh MESH2 that consists of MESH1 and added 2D skin cells. +# 1.3) Create a new 2D Mesh MESH3 that consists only of 2D skin cells. +# 2) The mesh MESH1 with 3D cells has all its skin (2D cells): +# Create a new 2D Mesh MESH3 that consists only of 2D skin cells. +# +# In all cases an option to create a group containing these 2D skin cells is available. + +from smesh import * + +box = geompy.MakeBoxDXDYDZ(1,1,1) +geompy.addToStudy(box,"box") +boxFace = geompy.SubShapeAll(box, geompy.ShapeType["FACE"])[0] +geompy.addToStudyInFather(box,boxFace,"boxFace") + +MESH1 = Mesh(box,"MESH1") +MESH1.AutomaticHexahedralization() + +init_nb_edges = MESH1.NbEdges() +init_nb_faces = MESH1.NbFaces() +init_nb_volumes = MESH1.NbVolumes() + +# ========================================================================================= +# 1) The mesh MESH1 with 3D cells has no or only a part of its skin (2D cells) +# ========================================================================================= +# remove some faces +all_faces = MESH1.GetElementsByType(SMESH.FACE) +rm_faces = all_faces[:init_nb_faces/5] + all_faces[4*init_nb_faces/5:] +MESH1.RemoveElements(rm_faces) +assert(MESH1.NbFaces() == init_nb_faces-len(rm_faces)) + +# 1.1) Add the 2D skin (missing 2D cells) to MESH1 +# ------------------------------------------------- +# add missing faces +# 1.1.1) to the whole mesh +m,g = MESH1.MakeBoundaryMesh(MESH1) +assert(init_nb_faces == MESH1.NbFaces()) +assert(init_nb_edges == MESH1.NbEdges()) +assert(m) +assert(not g) + +# 1.1.2) to some elements +MESH1.RemoveElements(rm_faces) +MESH1.MakeBoundaryMesh([]) +assert(init_nb_faces != MESH1.NbFaces()) +volumes = MESH1.GetElementsByType(SMESH.VOLUME) +for v in volumes: + MESH1.MakeBoundaryMesh([v]) +assert(init_nb_faces == MESH1.NbFaces()) +assert(init_nb_edges == MESH1.NbEdges()) + +# 1.1.3) to a group of elements +volGroup1 = MESH1.CreateEmptyGroup(SMESH.VOLUME, "volGroup1") +volGroup1.Add( volumes[: init_nb_volumes/2]) +volGroup2 = MESH1.CreateEmptyGroup(SMESH.VOLUME, "volGroup2") +volGroup1.Add( volumes[init_nb_volumes/2:]) +MESH1.RemoveElements(rm_faces) +MESH1.MakeBoundaryMesh(volGroup1) +MESH1.MakeBoundaryMesh(volGroup2) +assert(init_nb_faces == MESH1.NbFaces()) +assert(init_nb_edges == MESH1.NbEdges()) + +# 1.1.4) to a submesh. +# The submesh has no volumes, so it is required to check if it passes without crash and does not create +# missing faces +faceSubmesh = MESH1.GetSubMesh( boxFace, "boxFace" ) +MESH1.RemoveElements(rm_faces) +MESH1.MakeBoundaryMesh(faceSubmesh) +assert(init_nb_faces != MESH1.NbFaces()) + +# check group creation +MESH1.RemoveElements(rm_faces) +groupName = "added to mesh" +m,group = MESH1.MakeBoundaryMesh(MESH1,groupName=groupName) +assert(group) +assert(group.GetName() == groupName) +assert(group.Size() == len(rm_faces)) + + +# 1.2) Create a new 3D Mesh MESH2 that consists of MESH1 and added 2D skin cells. +# ------------------------------------------------------------------------------ +MESH1.RemoveElements(rm_faces) +meshName = "MESH2" +MESH2,group = MESH1.MakeBoundaryMesh(MESH1,meshName=meshName,toCopyElements=True) +assert(MESH2) +assert(MESH2.GetName() == meshName) +assert(MESH2.NbVolumes() == MESH1.NbVolumes()) +assert(MESH2.NbFaces() == len(rm_faces)) + +# check group creation +MESH1.RemoveElements(rm_faces) +MESH2,group = MESH1.MakeBoundaryMesh(MESH1,meshName="MESH2_0", + groupName=groupName,toCopyElements=True) +assert(group) +assert(group.GetName() == groupName) +assert(group.Size() == len(rm_faces)) +assert(group.GetMesh()._is_equivalent(MESH2.GetMesh())) + +# 1.3) Create a new 2D Mesh MESH3 that consists only of 2D skin cells. +# ----------------------------------------------------------------------- +MESH1.RemoveElements(rm_faces) +meshName = "MESH3" +MESH3,group = MESH1.MakeBoundaryMesh(MESH1,meshName=meshName,toCopyExistingBondary=True) +assert(MESH3) +assert(not group) +assert(MESH3.GetName() == meshName) +assert(MESH3.NbVolumes() == 0) +assert(MESH3.NbFaces() == init_nb_faces) + +# check group creation +MESH1.RemoveElements(rm_faces) +MESH3,group = MESH1.MakeBoundaryMesh(MESH1,meshName=meshName, + groupName=groupName, toCopyExistingBondary=True) +assert(group) +assert(group.GetName() == groupName) +assert(group.Size() == len(rm_faces)) +assert(group.GetMesh()._is_equivalent(MESH3.GetMesh())) +assert(MESH3.NbFaces() == init_nb_faces) + +# ================================================================== +# 2) The mesh MESH1 with 3D cells has all its skin (2D cells) +# Create a new 2D Mesh MESH3 that consists only of 2D skin cells. +# ================================================================== +MESH1.MakeBoundaryMesh(MESH1) +MESH3,group = MESH1.MakeBoundaryMesh(MESH1,meshName=meshName,toCopyExistingBondary=True) +assert(MESH3) +assert(not group) +assert(MESH3.NbVolumes() == 0) +assert(MESH3.NbFaces() == init_nb_faces) + +# check group creation +MESH3,group = MESH1.MakeBoundaryMesh(MESH1,meshName=meshName, + groupName=groupName, toCopyExistingBondary=True) +assert(group) +assert(group.GetName() == groupName) +assert(group.Size() == 0) +assert(group.GetMesh()._is_equivalent(MESH3.GetMesh())) +assert(MESH3.NbFaces() == init_nb_faces) + +# ================ +# Make 1D from 2D +# ================ + +MESH1.Clear() +MESH1.Compute() +MESH1.RemoveElements( MESH1.GetElementsByType(SMESH.EDGE)) + +rm_faces = faceSubmesh.GetIDs()[:2] # to remove few adjacent faces +nb_missing_edges = 2 + 2*len(rm_faces) + +MESH1.RemoveElements(rm_faces) +mesh,group = MESH1.MakeBoundaryMesh(MESH1, BND_1DFROM2D) +assert( MESH1.NbEdges() == nb_missing_edges ) + + +\endcode */ diff --git a/idl/SMESH_BasicHypothesis.idl b/idl/SMESH_BasicHypothesis.idl index 871f07714..a5ecbcabf 100644 --- a/idl/SMESH_BasicHypothesis.idl +++ b/idl/SMESH_BasicHypothesis.idl @@ -753,6 +753,16 @@ module StdMeshers /*! * StdMeshers_QuadrangleParams: interface of "Quadrangle Params" hypothesis */ + enum QuadType + { + QUAD_STANDARD, + QUAD_TRIANGLE_PREF, + QUAD_QUADRANGLE_PREF, + QUAD_QUADRANGLE_PREF_REVERSED, + QUAD_REDUCED, + QUAD_NB_TYPES /* this is not a type of quadrangulation */ + }; + interface StdMeshers_QuadrangleParams : SMESH::SMESH_Hypothesis { /*! @@ -774,6 +784,16 @@ module StdMeshers * Get the entry of the main object */ string GetObjectEntry(); + + /*! + * Set the type of quadrangulation + */ + void SetQuadType( in QuadType type ); + + /*! + * Get the type of quadrangulation + */ + QuadType GetQuadType(); }; /*! diff --git a/idl/SMESH_Filter.idl b/idl/SMESH_Filter.idl index 56f2cdce2..3b478fec0 100644 --- a/idl/SMESH_Filter.idl +++ b/idl/SMESH_Filter.idl @@ -65,6 +65,7 @@ module SMESH FT_LinearOrQuadratic, FT_GroupColor, FT_ElemGeomType, + FT_CoplanarFaces, FT_LessThan, FT_MoreThan, FT_EqualTo, @@ -346,6 +347,16 @@ module SMESH void SetGeometryType( in GeometryType theType ); }; + /*! + * Functor "Coplanar faces" + * Returns true if a mesh face is a coplanar neighbour to a given one. It checks + * if normal of a face has angle with the threshold face less than a tolerance. + */ + interface CoplanarFaces : Predicate{ + void SetFace ( in long theFaceID ); + void SetTolerance( in double theToler ); + }; + /*! * Filter */ @@ -360,13 +371,13 @@ module SMESH * BinaryOp - binary logical operation FT_LogicalAND, FT_LogicalOR or * (FT_Undefined must be for the last criterion) * ThresholdStr - Threshold value defined as string. Used for: - * 1. Diaposon of identifiers. Example: "1,2,3,5-10,12,27-29" + * 1. Diapason of identifiers. Example: "1,2,3,5-10,12,27-29" * 2. BelongToGeom predicate for storing name of shape * 3. GroupColor predicate for storing group color "0.2;0;0.5" * ThresholdID - One more threshold value defined as string. Used for: * 1. BelongToGeom predicate for storing id of shape * Tolerance - Tolerance is used for comparators (EqualTo comparision) and for - * "Belong to plane" and "Belong to cylinder" predicates + * "Belong to plane", "Belong to cylinder" etc predicates * TypeOfElement - type of element SMESH::NODE, SMESH::FACE (used by BelongToGeom predicate only) * Precision - Precision of numerical functors */ @@ -477,6 +488,7 @@ module SMESH GroupColor CreateGroupColor(); ElemGeomType CreateElemGeomType(); + CoplanarFaces CreateCoplanarFaces(); /*! * Create comparators ( predicates ) diff --git a/idl/SMESH_MeshEditor.idl b/idl/SMESH_MeshEditor.idl index 387091de3..c010980be 100644 --- a/idl/SMESH_MeshEditor.idl +++ b/idl/SMESH_MeshEditor.idl @@ -29,6 +29,8 @@ module SMESH { + enum Bnd_Dimension { BND_2DFROM3D, BND_1DFROM3D, BND_1DFROM2D }; + /*! * This interface makes modifications on the Mesh - removing elements and nodes etc. */ @@ -921,12 +923,34 @@ module SMESH in GEOM::GEOM_Object theShape ); /*! - * \brief Generated skin mesh (containing 2D cells) from 3D mesh + * \brief Generates skin mesh (containing 2D cells) from 3D mesh * The created 2D mesh elements based on nodes of free faces of boundary volumes * \return TRUE if operation has been completed successfully, FALSE otherwise */ boolean Make2DMeshFrom3D(); + /*! + * \brief Creates missing boundary elements + * \param elements - elements whose boundary is to be checked + * \param dimension - defines type of boundary elements to create + * \param groupName - a name of group to store created boundary elements in, + * "" means not to create the group + * \param meshName - a name of new mesh to store created boundary elements in, + * "" means not to create the new mesh + * \param toCopyElements - if true, the checked elements will be copied into the new mesh + * \param toCopyExistingBondary - if true, not only new but also pre-existing + * boundary elements will be copied into the new mesh + * \param group - returns the create group, if any + * \retval SMESH::SMESH_Mesh - the mesh where elements were added to + */ + SMESH::SMESH_Mesh MakeBoundaryMesh(in SMESH_IDSource elements, + in Bnd_Dimension dimension, + in string groupName, + in string meshName, + in boolean toCopyElements, + in boolean toCopyExistingBondary, + out SMESH_Group group); + }; }; diff --git a/resources/Makefile.am b/resources/Makefile.am index ed3f5aff7..9541a2133 100644 --- a/resources/Makefile.am +++ b/resources/Makefile.am @@ -70,6 +70,11 @@ dist_salomeres_DATA = \ mesh_pyramid.png \ mesh_quad_n.png \ mesh_quad.png \ + mesh_quadrangle_quadpref.png \ + mesh_quadrangle_quadpref_reversed.png \ + mesh_quadrangle_reduced.png \ + mesh_quadrangle_standard.png \ + mesh_quadrangle_triapref.png \ mesh_rem_element.png \ mesh_rem_node.png \ mesh_rem_orphan_nodes.png \ diff --git a/resources/SalomeApp.xml b/resources/SalomeApp.xml index a1806b5cd..b7993a340 100644 --- a/resources/SalomeApp.xml +++ b/resources/SalomeApp.xml @@ -67,6 +67,7 @@ + diff --git a/resources/StdMeshers.xml b/resources/StdMeshers.xml index 37dda8a94..557cd9613 100644 --- a/resources/StdMeshers.xml +++ b/resources/StdMeshers.xml @@ -122,7 +122,7 @@ +#include #include #include @@ -70,6 +71,12 @@ */ namespace{ + + inline gp_XYZ gpXYZ(const SMDS_MeshNode* aNode ) + { + return gp_XYZ(aNode->X(), aNode->Y(), aNode->Z() ); + } + inline double getAngle( const gp_XYZ& P1, const gp_XYZ& P2, const gp_XYZ& P3 ) { gp_Vec v1( P1 - P2 ), v2( P3 - P2 ); @@ -171,6 +178,26 @@ namespace{ return aResult; } + gp_XYZ getNormale( const SMDS_MeshFace* theFace, bool* ok=0 ) + { + int aNbNode = theFace->NbNodes(); + + gp_XYZ q1 = gpXYZ( theFace->GetNode(1)) - gpXYZ( theFace->GetNode(0)); + gp_XYZ q2 = gpXYZ( theFace->GetNode(2)) - gpXYZ( theFace->GetNode(0)); + gp_XYZ n = q1 ^ q2; + if ( aNbNode > 3 ) { + gp_XYZ q3 = gpXYZ( theFace->GetNode(3)) - gpXYZ( theFace->GetNode(0)); + n += q2 ^ q3; + } + double len = n.Modulus(); + bool zeroLen = ( len <= numeric_limits::min()); + if ( !zeroLen ) + n /= len; + + if (ok) *ok = !zeroLen; + + return n; + } } @@ -178,8 +205,8 @@ namespace{ using namespace SMESH::Controls; /* - FUNCTORS -*/ + * FUNCTORS + */ /* Class : NumericalFunctor @@ -2002,13 +2029,71 @@ SMDSAbs_GeometryType ElemGeomType::GetGeomType() const return myGeomType; } +//================================================================================ +/*! + * \brief Class CoplanarFaces + */ +//================================================================================ + +CoplanarFaces::CoplanarFaces() + : myMesh(0), myFaceID(0), myToler(0) +{ +} +bool CoplanarFaces::IsSatisfy( long theElementId ) +{ + if ( myCoplanarIDs.empty() ) + { + // Build a set of coplanar face ids + + if ( !myMesh || !myFaceID || !myToler ) + return false; + + const SMDS_MeshElement* face = myMesh->FindElement( myFaceID ); + if ( !face || face->GetType() != SMDSAbs_Face ) + return false; + + bool normOK; + gp_Vec myNorm = getNormale( static_cast(face), &normOK ); + if (!normOK) + return false; + + const double radianTol = myToler * PI180; + typedef SMDS_StdIterator< const SMDS_MeshElement*, SMDS_ElemIteratorPtr > TFaceIt; + std::set checkedFaces, checkedNodes; + std::list faceQueue( 1, face ); + while ( !faceQueue.empty() ) + { + face = faceQueue.front(); + if ( checkedFaces.insert( face ).second ) + { + gp_Vec norm = getNormale( static_cast(face), &normOK ); + if (!normOK || myNorm.Angle( norm ) <= radianTol) + { + myCoplanarIDs.insert( face->GetID() ); + std::set neighborFaces; + for ( int i = 0; i < face->NbCornerNodes(); ++i ) + { + const SMDS_MeshNode* n = face->GetNode( i ); + if ( checkedNodes.insert( n ).second ) + neighborFaces.insert( TFaceIt( n->GetInverseElementIterator(SMDSAbs_Face)), + TFaceIt()); + } + faceQueue.insert( faceQueue.end(), neighborFaces.begin(), neighborFaces.end() ); + } + } + faceQueue.pop_front(); + } + } + return myCoplanarIDs.count( theElementId ); +} + /* - Class : RangeOfIds - Description : Predicate for Range of Ids. - Range may be specified with two ways. - 1. Using AddToRange method - 2. With SetRangeStr method. Parameter of this method is a string - like as "1,2,3,50-60,63,67,70-" + *Class : RangeOfIds + *Description : Predicate for Range of Ids. + * Range may be specified with two ways. + * 1. Using AddToRange method + * 2. With SetRangeStr method. Parameter of this method is a string + * like as "1,2,3,50-60,63,67,70-" */ //======================================================================= @@ -2638,32 +2723,6 @@ static void getLinks( const SMDS_MeshFace* theFace, } } -static gp_XYZ getNormale( const SMDS_MeshFace* theFace ) -{ - gp_XYZ n; - int aNbNode = theFace->NbNodes(); - TColgp_Array1OfXYZ anArrOfXYZ(1,4); - SMDS_ElemIteratorPtr aNodeItr = theFace->nodesIterator(); - int i = 1; - for ( ; aNodeItr->more() && i <= 4; i++ ) { - SMDS_MeshNode* aNode = (SMDS_MeshNode*)aNodeItr->next(); - anArrOfXYZ.SetValue(i, gp_XYZ( aNode->X(), aNode->Y(), aNode->Z() ) ); - } - - gp_XYZ q1 = anArrOfXYZ.Value(2) - anArrOfXYZ.Value(1); - gp_XYZ q2 = anArrOfXYZ.Value(3) - anArrOfXYZ.Value(1); - n = q1 ^ q2; - if ( aNbNode > 3 ) { - gp_XYZ q3 = anArrOfXYZ.Value(4) - anArrOfXYZ.Value(1); - n += q2 ^ q3; - } - double len = n.Modulus(); - if ( len > 0 ) - n /= len; - - return n; -} - bool ManifoldPart::findConnected ( const ManifoldPart::TDataMapFacePtrInt& theAllFacePtrInt, SMDS_MeshFace* theStartFace, diff --git a/src/Controls/SMESH_ControlsDef.hxx b/src/Controls/SMESH_ControlsDef.hxx index 5849c1f83..1fde3f281 100644 --- a/src/Controls/SMESH_ControlsDef.hxx +++ b/src/Controls/SMESH_ControlsDef.hxx @@ -770,11 +770,11 @@ namespace SMESH{ class SMESHCONTROLS_EXPORT ElemGeomType: public virtual Predicate{ public: ElemGeomType(); - virtual void SetMesh( const SMDS_Mesh* theMesh ); - virtual bool IsSatisfy( long theElementId ); - void SetType( SMDSAbs_ElementType theType ); - virtual SMDSAbs_ElementType GetType() const; - void SetGeomType( SMDSAbs_GeometryType theType ); + virtual void SetMesh( const SMDS_Mesh* theMesh ); + virtual bool IsSatisfy( long theElementId ); + void SetType( SMDSAbs_ElementType theType ); + virtual SMDSAbs_ElementType GetType() const; + void SetGeomType( SMDSAbs_GeometryType theType ); virtual SMDSAbs_GeometryType GetGeomType() const; private: @@ -784,6 +784,31 @@ namespace SMESH{ }; typedef boost::shared_ptr ElemGeomTypePtr; + /* + Class : CoplanarFaces + Description : Predicate to check angle between faces + */ + class SMESHCONTROLS_EXPORT CoplanarFaces: public virtual Predicate + { + public: + CoplanarFaces(); + void SetFace( long theID ) { myFaceID = theID; } + long GetFace() const { return myFaceID; } + void SetTolerance (const double theToler) { myToler = theToler; } + double GetTolerance () const { return myToler; } + virtual void SetMesh( const SMDS_Mesh* theMesh ) { myMesh = theMesh; } + virtual SMDSAbs_ElementType GetType() const { return SMDSAbs_Face; } + + virtual bool IsSatisfy( long theElementId ); + + private: + const SMDS_Mesh* myMesh; + long myFaceID; + double myToler; + std::set< long > myCoplanarIDs; + }; + typedef boost::shared_ptr CoplanarFacesPtr; + /* FILTER */ diff --git a/src/SMESH/SMESH_HypoFilter.cxx b/src/SMESH/SMESH_HypoFilter.cxx index dd99ac11a..f60a122a9 100644 --- a/src/SMESH/SMESH_HypoFilter.cxx +++ b/src/SMESH/SMESH_HypoFilter.cxx @@ -27,7 +27,9 @@ // #include "SMESH_HypoFilter.hxx" +#include "SMESH_Gen.hxx" #include "SMESH_Hypothesis.hxx" +#include "SMESH_MesherHelper.hxx" #include "SMESH_subMesh.hxx" #include @@ -115,7 +117,7 @@ bool SMESH_HypoFilter::InstancePredicate::IsOk(const SMESH_Hypothesis* aHyp, //======================================================================= bool SMESH_HypoFilter::IsAssignedToPredicate::IsOk(const SMESH_Hypothesis* aHyp, - const TopoDS_Shape& aShape) const + const TopoDS_Shape& aShape) const { return ( !_mainShape.IsNull() && !aShape.IsNull() && _mainShape.IsSame( aShape )); } @@ -128,14 +130,19 @@ bool SMESH_HypoFilter::IsAssignedToPredicate::IsOk(const SMESH_Hypothesis* aHyp, bool SMESH_HypoFilter::IsMoreLocalThanPredicate::IsOk(const SMESH_Hypothesis* aHyp, const TopoDS_Shape& aShape) const { - // issue 0020963 - // if aShape is COMPOUND (i.e. most probably a GEOM group) then - // it is more local if it contains shapes of less dimension than _shapeType - if ( aShape.ShapeType() == TopAbs_COMPOUND ) - for ( int moreLocalType = _shapeType+1; moreLocalType < int(TopAbs_SHAPE); ++moreLocalType ) - if ( TopExp_Explorer( aShape, TopAbs_ShapeEnum(moreLocalType)).More()) - return true; - return ( aShape.ShapeType() > _shapeType ); + if ( SMESH_MesherHelper::IsSubShape( aShape, /*mainShape=*/_shape )) + return true; + + if ( aShape.ShapeType() == TopAbs_COMPOUND && + !SMESH_MesherHelper::IsSubShape( _shape, /*mainShape=*/aShape)) // issue 0020963 + { + for ( int type = TopAbs_SOLID; type < TopAbs_SHAPE; ++type ) + if ( aHyp->GetDim() == SMESH_Gen::GetShapeDim( TopAbs_ShapeEnum( type ))) + for ( TopExp_Explorer exp( aShape, TopAbs_ShapeEnum( type )); exp.More(); exp.Next()) + if ( SMESH_MesherHelper::IsSubShape( exp.Current(), /*mainShape=*/_shape )) + return true; + } + return false; } //======================================================================= diff --git a/src/SMESH/SMESH_HypoFilter.hxx b/src/SMESH/SMESH_HypoFilter.hxx index 0fb043e57..c2ad8b753 100644 --- a/src/SMESH/SMESH_HypoFilter.hxx +++ b/src/SMESH/SMESH_HypoFilter.hxx @@ -23,7 +23,6 @@ // SMESH SMESH : implementaion of SMESH idl descriptions // File : SMESH_HypoFilter.hxx // Module : SMESH -// $Header$ // #ifndef SMESH_HypoFilter_HeaderFile #define SMESH_HypoFilter_HeaderFile @@ -168,8 +167,8 @@ class SMESH_EXPORT SMESH_HypoFilter: public SMESH_HypoPredicate }; struct IsMoreLocalThanPredicate : public SMESH_HypoPredicate { - TopAbs_ShapeEnum _shapeType; - IsMoreLocalThanPredicate( const TopoDS_Shape& shape ):_shapeType(shape.ShapeType()){} + TopoDS_Shape _shape; + IsMoreLocalThanPredicate( const TopoDS_Shape& shape ):_shape(shape){} bool IsOk(const SMESH_Hypothesis* aHyp, const TopoDS_Shape& aShape) const; }; diff --git a/src/SMESH/SMESH_MeshEditor.cxx b/src/SMESH/SMESH_MeshEditor.cxx index b802540f0..f26db9a0c 100644 --- a/src/SMESH/SMESH_MeshEditor.cxx +++ b/src/SMESH/SMESH_MeshEditor.cxx @@ -35,6 +35,7 @@ #include "SMDS_SpacePosition.hxx" #include "SMDS_QuadraticFaceOfNodes.hxx" #include "SMDS_MeshGroup.hxx" +#include "SMDS_SetIterator.hxx" #include "SMESHDS_Group.hxx" #include "SMESHDS_Mesh.hxx" @@ -99,6 +100,8 @@ using namespace SMESH::Controls; typedef map > TElemOfNodeListMap; typedef map > TElemOfElemListMap; +typedef SMDS_SetIterator< SMDS_pElement, TIDSortedElemSet::const_iterator> TSetIterator; + //======================================================================= //function : SMESH_MeshEditor //purpose : @@ -219,6 +222,7 @@ SMESH_MeshEditor::AddElement(const vector & node, node[16],node[17],node[18],node[19] ); } } + if ( e ) myLastCreatedElems.Append( e ); return e; } @@ -5531,10 +5535,8 @@ SMESH_MeshEditor::Transform (TIDSortedElemSet & theElems, } } else if ( theCopy ) { - if ( SMDS_MeshElement* copy = AddElement( nodes, elem->GetType(), elem->IsPoly() )) { - myLastCreatedElems.Append( copy ); + if ( AddElement( nodes, elem->GetType(), elem->IsPoly() )) srcElems.Append( elem ); - } } else { // reverse element as it was reversed by transformation @@ -5871,7 +5873,7 @@ namespace // Utils used in SMESH_ElementSearcherImpl::FindElementsByPoint() { public: - ElementBndBoxTree(const SMDS_Mesh& mesh, SMDSAbs_ElementType elemType); + ElementBndBoxTree(const SMDS_Mesh& mesh, SMDSAbs_ElementType elemType, double tolerance = NodeRadius ); void getElementsNearPoint( const gp_Pnt& point, TIDSortedElemSet& foundElems); void getElementsNearLine ( const gp_Ax1& line, TIDSortedElemSet& foundElems); ~ElementBndBoxTree(); @@ -5887,7 +5889,7 @@ namespace // Utils used in SMESH_ElementSearcherImpl::FindElementsByPoint() { const SMDS_MeshElement* _element; int _refCount; // an ElementBox can be included in several tree branches - ElementBox(const SMDS_MeshElement* elem); + ElementBox(const SMDS_MeshElement* elem, double tolerance); }; vector< ElementBox* > _elements; }; @@ -5898,7 +5900,7 @@ namespace // Utils used in SMESH_ElementSearcherImpl::FindElementsByPoint() */ //================================================================================ - ElementBndBoxTree::ElementBndBoxTree(const SMDS_Mesh& mesh, SMDSAbs_ElementType elemType) + ElementBndBoxTree::ElementBndBoxTree(const SMDS_Mesh& mesh, SMDSAbs_ElementType elemType, double tolerance) :SMESH_Octree( new SMESH_Octree::Limit( MaxLevel, /*minSize=*/0. )) { int nbElems = mesh.GetMeshInfo().NbElements( elemType ); @@ -5906,7 +5908,7 @@ namespace // Utils used in SMESH_ElementSearcherImpl::FindElementsByPoint() SMDS_ElemIteratorPtr elemIt = mesh.elementsIterator( elemType ); while ( elemIt->more() ) - _elements.push_back( new ElementBox( elemIt->next() )); + _elements.push_back( new ElementBox( elemIt->next(),tolerance )); if ( _elements.size() > MaxNbElemsInLeaf ) compute(); @@ -6030,14 +6032,14 @@ namespace // Utils used in SMESH_ElementSearcherImpl::FindElementsByPoint() */ //================================================================================ - ElementBndBoxTree::ElementBox::ElementBox(const SMDS_MeshElement* elem) + ElementBndBoxTree::ElementBox::ElementBox(const SMDS_MeshElement* elem, double tolerance) { _element = elem; _refCount = 1; SMDS_ElemIteratorPtr nIt = elem->nodesIterator(); while ( nIt->more() ) Add( SMESH_MeshEditor::TNodeXYZ( cast2Node( nIt->next() ))); - Enlarge( NodeRadius ); + Enlarge( tolerance ); } } // namespace @@ -6157,7 +6159,7 @@ double SMESH_ElementSearcherImpl::getTolerance() elemSize = max( dist, elemSize ); } } - _tolerance = 1e-6 * elemSize; + _tolerance = 1e-4 * elemSize; } } return _tolerance; @@ -6348,7 +6350,7 @@ FindElementsByPoint(const gp_Pnt& point, if ( !_ebbTree || _elementType != type ) { if ( _ebbTree ) delete _ebbTree; - _ebbTree = new ElementBndBoxTree( *_mesh, _elementType = type ); + _ebbTree = new ElementBndBoxTree( *_mesh, _elementType = type, tolerance ); } TIDSortedElemSet suspectElems; _ebbTree->getElementsNearPoint( point, suspectElems ); @@ -9829,7 +9831,7 @@ bool SMESH_MeshEditor::doubleNodes( SMESHDS_Mesh* theMeshDS, continue; if ( theIsDoubleElem ) - myLastCreatedElems.Append( AddElement(newNodes, anElem->GetType(), anElem->IsPoly()) ); + AddElement(newNodes, anElem->GetType(), anElem->IsPoly()); else theMeshDS->ChangeElementNodes( anElem, &newNodes[ 0 ], anElem->NbNodes() ); @@ -10054,7 +10056,7 @@ bool SMESH_MeshEditor::DoubleNodesInRegion( const TIDSortedElemSet& theElems, //================================================================================ /*! - * \brief Generated skin mesh (containing 2D cells) from 3D mesh + * \brief Generates skin mesh (containing 2D cells) from 3D mesh * The created 2D mesh elements based on nodes of free faces of boundary volumes * \return TRUE if operation has been completed successfully, FALSE otherwise */ @@ -10096,9 +10098,195 @@ bool SMESH_MeshEditor::Make2DMeshFrom3D() nbExisted++; continue; // face already exsist } - myLastCreatedElems.Append( AddElement(nodes, SMDSAbs_Face, isPoly && iface == 1) ); + AddElement(nodes, SMDSAbs_Face, isPoly && iface == 1); nbCreated++; } } return ( nbFree==(nbExisted+nbCreated) ); } + +namespace +{ + inline const SMDS_MeshNode* getNodeWithSameID(SMESHDS_Mesh* mesh, const SMDS_MeshNode* node) + { + if ( const SMDS_MeshNode* n = mesh->FindNode( node->GetID() )) + return n; + return mesh->AddNodeWithID( node->X(),node->Y(),node->Z(), node->GetID() ); + } +} +//================================================================================ +/*! + * \brief Creates missing boundary elements + * \param elements - elements whose boundary is to be checked + * \param dimension - defines type of boundary elements to create + * \param group - a group to store created boundary elements in + * \param targetMesh - a mesh to store created boundary elements in + * \param toCopyElements - if true, the checked elements will be copied into the targetMesh + * \param toCopyExistingBondary - if true, not only new but also pre-existing + * boundary elements will be copied into the targetMesh + */ +//================================================================================ + +void SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements, + Bnd_Dimension dimension, + SMESH_Group* group/*=0*/, + SMESH_Mesh* targetMesh/*=0*/, + bool toCopyElements/*=false*/, + bool toCopyExistingBondary/*=false*/) +{ + SMDSAbs_ElementType missType = (dimension == BND_2DFROM3D) ? SMDSAbs_Face : SMDSAbs_Edge; + SMDSAbs_ElementType elemType = (dimension == BND_1DFROM2D) ? SMDSAbs_Face : SMDSAbs_Volume; + // hope that all elements are of the same type, do not check them all + if ( !elements.empty() && (*elements.begin())->GetType() != elemType ) + throw SALOME_Exception(LOCALIZED("wrong element type")); + + if ( !targetMesh ) + toCopyElements = toCopyExistingBondary = false; + + SMESH_MeshEditor tgtEditor( targetMesh ? targetMesh : myMesh ); + SMESHDS_Mesh* aMesh = GetMeshDS(), *tgtMeshDS = tgtEditor.GetMeshDS(); + + SMDS_VolumeTool vTool; + TIDSortedElemSet emptySet, avoidSet; + int inode; + + typedef vector TConnectivity; + + SMDS_ElemIteratorPtr eIt; + if (elements.empty()) + eIt = aMesh->elementsIterator(elemType); + else + eIt = SMDS_ElemIteratorPtr( new TSetIterator( elements.begin(), elements.end() )); + + while (eIt->more()) + { + const SMDS_MeshElement* elem = eIt->next(); + const int iQuad = elem->IsQuadratic(); + + // 1. For an elem, get present bnd elements and connectivities of missing bnd elements + vector presentBndElems; + vector missingBndElems; + TConnectivity nodes; + if ( vTool.Set(elem) ) // elem is a volume ------------------------------------------ + { + vTool.SetExternalNormal(); + for ( int iface = 0, n = vTool.NbFaces(); iface < n; iface++ ) + { + if (!vTool.IsFreeFace(iface)) + continue; + int nbFaceNodes = vTool.NbFaceNodes(iface); + const SMDS_MeshNode** nn = vTool.GetFaceNodes(iface); + if ( missType == SMDSAbs_Edge ) // boundary edges + { + nodes.resize( 2+iQuad ); + for ( int i = 0; i < nbFaceNodes; i += 1+iQuad) + { + for ( int j = 0; j < nodes.size(); ++j ) + nodes[j] =nn[i+j]; + if ( const SMDS_MeshElement* edge = + aMesh->FindElement(nodes,SMDSAbs_Edge,/*noMedium=*/0)) + presentBndElems.push_back( edge ); + else + missingBndElems.push_back( nodes ); + } + } + else // boundary face + { + nodes.clear(); + for ( inode = 0; inode < nbFaceNodes; inode += 1+iQuad) + nodes.push_back( nn[inode] ); + if (iQuad) + for ( inode = 1; inode < nbFaceNodes; inode += 2) + nodes.push_back( nn[inode] ); + + if (const SMDS_MeshFace * f = aMesh->FindFace( nodes ) ) + presentBndElems.push_back( f ); + else + missingBndElems.push_back( nodes ); + } + } + } + else // elem is a face ------------------------------------------ + { + avoidSet.clear(), avoidSet.insert( elem ); + int nbNodes = elem->NbCornerNodes(); + nodes.resize( 2 /*+ iQuad*/); + for ( int i = 0; i < nbNodes; i++ ) + { + nodes[0] = elem->GetNode(i); + nodes[1] = elem->GetNode((i+1)%nbNodes); + if ( FindFaceInSet( nodes[0], nodes[1], emptySet, avoidSet)) + continue; // not free link + + //if ( iQuad ) + //nodes[2] = elem->GetNode( i + nbNodes ); + if ( const SMDS_MeshElement* edge = + aMesh->FindElement(nodes,SMDSAbs_Edge,/*noMedium=*/true)) + presentBndElems.push_back( edge ); + else + missingBndElems.push_back( nodes ); + } + } + + // 2. Add missing boundary elements + if ( targetMesh != myMesh ) + // instead of making a map of nodes in this mesh and targetMesh, + // we create nodes with same IDs. We can renumber them later, if needed + for ( int i = 0; i < missingBndElems.size(); ++i ) + { + TConnectivity& srcNodes = missingBndElems[i]; + TConnectivity nodes( srcNodes.size() ); + for ( inode = 0; inode < nodes.size(); ++inode ) + nodes[inode] = getNodeWithSameID( tgtMeshDS, srcNodes[inode] ); + tgtEditor.AddElement(nodes, missType, elem->IsPoly() && nodes.size()/(iQuad+1)>4); + } + else + for ( int i = 0; i < missingBndElems.size(); ++i ) + { + TConnectivity& nodes = missingBndElems[i]; + tgtEditor.AddElement(nodes, missType, elem->IsPoly() && nodes.size()/(iQuad+1)>4); + } + + // 3. Copy present boundary elements + if ( toCopyExistingBondary ) + for ( int i = 0 ; i < presentBndElems.size(); ++i ) + { + const SMDS_MeshElement* e = presentBndElems[i]; + TConnectivity nodes( e->NbNodes() ); + for ( inode = 0; inode < nodes.size(); ++inode ) + nodes[inode] = getNodeWithSameID( tgtMeshDS, e->GetNode(inode) ); + tgtEditor.AddElement(nodes, missType, e->IsPoly()); + // leave only missing elements in tgtEditor.myLastCreatedElems + tgtEditor.myLastCreatedElems.Remove( tgtEditor.myLastCreatedElems.Size() ); + } + } // loop on given elements + + // 4. Fill group with missing boundary elements + if ( group ) + { + if ( SMESHDS_Group* g = dynamic_cast( group->GetGroupDS() )) + for ( int i = 0; i < tgtEditor.myLastCreatedElems.Size(); ++i ) + g->SMDSGroup().Add( tgtEditor.myLastCreatedElems( i+1 )); + } + tgtEditor.myLastCreatedElems.Clear(); + + // 5. Copy given elements + if ( toCopyElements ) + { + if (elements.empty()) + eIt = aMesh->elementsIterator(elemType); + else + eIt = SMDS_ElemIteratorPtr( new TSetIterator( elements.begin(), elements.end() )); + while (eIt->more()) + { + const SMDS_MeshElement* elem = eIt->next(); + TConnectivity nodes( elem->NbNodes() ); + for ( inode = 0; inode < nodes.size(); ++inode ) + nodes[inode] = getNodeWithSameID( tgtMeshDS, elem->GetNode(inode) ); + tgtEditor.AddElement(nodes, elemType, elem->IsPoly()); + + tgtEditor.myLastCreatedElems.Clear(); + } + } + return; +} diff --git a/src/SMESH/SMESH_MeshEditor.hxx b/src/SMESH/SMESH_MeshEditor.hxx index 80287eea3..dabe3f8db 100644 --- a/src/SMESH/SMESH_MeshEditor.hxx +++ b/src/SMESH/SMESH_MeshEditor.hxx @@ -624,13 +624,17 @@ public: const TIDSortedElemSet& theNodesNot, const TopoDS_Shape& theShape ); - /*! - * \brief Generated skin mesh (containing 2D cells) from 3D mesh - * The created 2D mesh elements based on nodes of free faces of boundary volumes - * \return TRUE if operation has been completed successfully, FALSE otherwise - */ bool Make2DMeshFrom3D(); - + + enum Bnd_Dimension { BND_2DFROM3D, BND_1DFROM3D, BND_1DFROM2D }; + + void MakeBoundaryMesh(const TIDSortedElemSet& elements, + Bnd_Dimension dimension, + SMESH_Group* group = 0, + SMESH_Mesh* targetMesh = 0, + bool toCopyElements = false, + bool toCopyExistingBondary = false); + private: /*! diff --git a/src/SMESH/SMESH_MesherHelper.cxx b/src/SMESH/SMESH_MesherHelper.cxx index 0a3887f70..b695e1276 100644 --- a/src/SMESH/SMESH_MesherHelper.cxx +++ b/src/SMESH/SMESH_MesherHelper.cxx @@ -356,7 +356,7 @@ gp_XY SMESH_MesherHelper::GetNodeUV(const TopoDS_Face& F, static_cast(n->GetPosition().get()); uv.SetCoord(fpos->GetUParameter(),fpos->GetVParameter()); if ( check ) - uvOK = CheckNodeUV( F, n, uv.ChangeCoord(), 2*BRep_Tool::Tolerance( F )); + uvOK = CheckNodeUV( F, n, uv.ChangeCoord(), 10*MaxTolerance( F )); } else if(Pos->GetTypeOfPosition()==SMDS_TOP_EDGE) { @@ -375,7 +375,7 @@ gp_XY SMESH_MesherHelper::GetNodeUV(const TopoDS_Face& F, else uv.SetCoord(0.,0.); if ( check || !validU ) - uvOK = CheckNodeUV( F, n, uv.ChangeCoord(), 2*BRep_Tool::Tolerance( E ),/*force=*/ !validU ); + uvOK = CheckNodeUV( F, n, uv.ChangeCoord(), 10*MaxTolerance( F ),/*force=*/ !validU ); // for a node on a seam edge select one of UVs on 2 pcurves if ( n2 && IsSeamShape( edgeID ) ) @@ -1521,6 +1521,26 @@ bool SMESH_MesherHelper::IsSubShape( const TopoDS_Shape& shape, SMESH_Mesh* aMes shape.ShapeType() == TopAbs_COMPOUND && aMesh->GetMeshDS()->IsGroupOfSubShapes( shape ); } +//================================================================================ +/*! + * \brief Return maximal tolerance of shape + */ +//================================================================================ + +double SMESH_MesherHelper::MaxTolerance( const TopoDS_Shape& shape ) +{ + double tol = Precision::Confusion(); + TopExp_Explorer exp; + for ( exp.Init( shape, TopAbs_FACE ); exp.More(); exp.Next() ) + tol = Max( tol, BRep_Tool::Tolerance( TopoDS::Face( exp.Current()))); + for ( exp.Init( shape, TopAbs_EDGE ); exp.More(); exp.Next() ) + tol = Max( tol, BRep_Tool::Tolerance( TopoDS::Edge( exp.Current()))); + for ( exp.Init( shape, TopAbs_VERTEX ); exp.More(); exp.Next() ) + tol = Max( tol, BRep_Tool::Tolerance( TopoDS::Vertex( exp.Current()))); + + return tol; +} + //======================================================================= //function : IsQuadraticMesh //purpose : Check mesh without geometry for: if all elements on this shape are quadratic, diff --git a/src/SMESH/SMESH_MesherHelper.hxx b/src/SMESH/SMESH_MesherHelper.hxx index 14d9225e6..7af79e5cf 100644 --- a/src/SMESH/SMESH_MesherHelper.hxx +++ b/src/SMESH/SMESH_MesherHelper.hxx @@ -140,6 +140,8 @@ public: static bool IsSubShape( const TopoDS_Shape& shape, SMESH_Mesh* aMesh ); + static double MaxTolerance( const TopoDS_Shape& shape ); + public: // ---------- PUBLIC INSTANCE METHODS ---------- diff --git a/src/SMESHGUI/SMESHGUI.cxx b/src/SMESHGUI/SMESHGUI.cxx index 4867a2ca1..1efc41fd2 100644 --- a/src/SMESHGUI/SMESHGUI.cxx +++ b/src/SMESHGUI/SMESHGUI.cxx @@ -1164,7 +1164,7 @@ SalomeApp_Application* anApp = dynamic_cast( SUIT_Session::session()->activeApplication() ); SUIT_ViewManager* vm = anApp->activeViewManager(); - int nbSf = vm->getViewsCount(); + int nbSf = vm ? vm->getViewsCount() : 0; SALOME_ListIteratorOfListIO It(selected); @@ -1206,7 +1206,7 @@ std::string anEntry = SO->GetID(); /** Erase graphical object **/ - if(SO->FindAttribute(anAttr, "AttributeIOR")){ + if(SO->FindAttribute(anAttr, "AttributeIOR") && vm ){ QVector aViews = vm->getViews(); for(int i = 0; i < nbSf; i++){ SUIT_ViewWindow *sf = aViews[i]; @@ -1330,13 +1330,22 @@ LightApp_SelectionMgr* SMESHGUI::selectionMgr() return 0; } -bool SMESHGUI::automaticUpdate() +//============================================================================= +/*! + * + */ +//============================================================================= +bool SMESHGUI::automaticUpdate(unsigned int requestedSize, bool* limitExceeded) { SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr(); if ( !resMgr ) return false; - return resMgr->booleanValue( "SMESH", "auto_update", false ); + bool autoUpdate = resMgr->booleanValue( "SMESH", "auto_update", false ); + long updateLimit = resMgr->integerValue( "SMESH", "update_limit", 500000 ); + bool exceeded = updateLimit > 0 && requestedSize > updateLimit; + if ( limitExceeded ) *limitExceeded = autoUpdate && exceeded; + return autoUpdate && !exceeded; } //============================================================================= @@ -3821,8 +3830,12 @@ void SMESHGUI::createPreferences() // General tab ------------------------------------------------------------------------ int genTab = addPreference( tr( "PREF_TAB_GENERAL" ) ); - int updateGroup = addPreference( tr( "PREF_GROUP_UPDATE" ), genTab ); - addPreference( tr( "PREF_AUTO_UPDATE" ), updateGroup, LightApp_Preferences::Bool, "SMESH", "auto_update" ); + int autoUpdate = addPreference( tr( "PREF_AUTO_UPDATE" ), genTab, LightApp_Preferences::Auto, "SMESH", "auto_update" ); + int lim = addPreference( tr( "PREF_UPDATE_LIMIT" ), autoUpdate, LightApp_Preferences::IntSpin, "SMESH", "update_limit" ); + setPreferenceProperty( lim, "min", 0 ); + setPreferenceProperty( lim, "max", 100000000 ); + setPreferenceProperty( lim, "step", 1000 ); + setPreferenceProperty( lim, "special", tr( "PREF_UPDATE_LIMIT_NOLIMIT" ) ); int qaGroup = addPreference( tr( "PREF_GROUP_QUALITY" ), genTab ); setPreferenceProperty( qaGroup, "columns", 2 ); diff --git a/src/SMESHGUI/SMESHGUI.h b/src/SMESHGUI/SMESHGUI.h index 4a82e5c1a..bb2b29c04 100644 --- a/src/SMESHGUI/SMESHGUI.h +++ b/src/SMESHGUI/SMESHGUI.h @@ -77,7 +77,7 @@ public : bool isActiveStudyLocked(); - static bool automaticUpdate(); + static bool automaticUpdate(unsigned int requestedSize = 0, bool* limitExceeded = 0); static void Modified( bool = true ); diff --git a/src/SMESHGUI/SMESHGUI_ComputeDlg.cxx b/src/SMESHGUI/SMESHGUI_ComputeDlg.cxx index ccd700190..b31a1b8e9 100644 --- a/src/SMESHGUI/SMESHGUI_ComputeDlg.cxx +++ b/src/SMESHGUI/SMESHGUI_ComputeDlg.cxx @@ -98,6 +98,7 @@ #define COLONIZE(str) (QString(str).contains(":") > 0 ? QString(str) : QString(str) + " :" ) +/* OBSOLETE static void addSeparator( QWidget* parent ) { QGridLayout* l = qobject_cast( parent->layout() ); @@ -109,6 +110,7 @@ static void addSeparator( QWidget* parent ) l->addWidget( hline, row, i ); } } +*/ enum TCol { COL_ALGO = 0, COL_SHAPE, COL_ERROR, COL_SHAPEID, COL_PUBLISHED, COL_BAD_MESH, NB_COLUMNS @@ -734,25 +736,38 @@ void SMESHGUI_BaseComputeOp::computeMesh() // SHOW MESH // NPAL16631: if ( getSMESHGUI()->automaticUpdate() ) - if ( !memoryLack && getSMESHGUI()->automaticUpdate() ) + SUIT_ResourceMgr* resMgr = SMESH::GetResourceMgr( SMESHGUI::GetSMESHGUI() ); + long newSize = myMesh->NbElements(); + long limitSize = resMgr->integerValue( "SMESH", "update_limit", 500000 ); + bool limitExceeded; + if ( !memoryLack ) { - try { + if ( getSMESHGUI()->automaticUpdate( newSize, &limitExceeded ) ) + { + try { #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100 - OCC_CATCH_SIGNALS; + OCC_CATCH_SIGNALS; #endif - SMESH::Update(myIObject, true); - } - catch (...) { + SMESH::Update(myIObject, true); + } + catch (...) { #ifdef _DEBUG_ - MESSAGE ( "Exception thrown during mesh visualization" ); + MESSAGE ( "Exception thrown during mesh visualization" ); #endif - if ( SMDS_Mesh::CheckMemory(true) ) { // has memory to show warning? - SMESH::OnVisuException(); - } - else { - memoryLack = true; - } + if ( SMDS_Mesh::CheckMemory(true) ) { // has memory to show warning? + SMESH::OnVisuException(); + } + else { + memoryLack = true; + } + } } + else if ( limitExceeded ) + { + SUIT_MessageBox::warning( desktop(), + tr( "SMESH_WRN_WARNING" ), + tr( "SMESH_WRN_SIZE_LIMIT_EXCEEDED" ).arg( newSize ).arg( limitSize ) ); + } } LightApp_SelectionMgr *Sel = selectionMgr(); if ( Sel ) @@ -804,7 +819,7 @@ void SMESHGUI_BaseComputeOp::computeMesh() void SMESHGUI_BaseComputeOp::showComputeResult( const bool theMemoryLack, const bool theNoCompError, SMESH::compute_error_array_var& theCompErrors, - const bool theNoHypoError, + const bool theNoHypoError, const QString& theHypErrors ) { bool hasShape = myMesh->HasShapeToMesh(); @@ -1562,6 +1577,7 @@ void SMESHGUI_PrecomputeOp::onPreview() SMESH::MeshPreviewStruct_var previewData = gen->Precompute(myMesh, myMainShape, (SMESH::Dimension)dim, aShapesId); + SMESH::MeshPreviewStruct* previewRes = previewData._retn(); if ( previewRes && previewRes->nodesXYZ.length() > 0 ) { diff --git a/src/SMESHGUI/SMESHGUI_FilterDlg.cxx b/src/SMESHGUI/SMESHGUI_FilterDlg.cxx index 2ae183e74..99da50cf2 100755 --- a/src/SMESHGUI/SMESHGUI_FilterDlg.cxx +++ b/src/SMESHGUI/SMESHGUI_FilterDlg.cxx @@ -33,11 +33,11 @@ #include "SMESHGUI_Filter.h" #include "SMESHGUI_FilterUtils.h" #include "SMESHGUI_FilterLibraryDlg.h" +#include "SMESHGUI_SpinBox.h" #include #include #include -#include // SALOME GEOM includes #include @@ -219,7 +219,7 @@ bool SMESHGUI_FilterTable::AdditionalWidget::IsValid (const bool theMsg) const } if (!valid && theMsg) { SUIT_MessageBox::information(SMESHGUI::desktop(), tr("SMESH_INSUFFICIENT_DATA"), - tr("SMESHGUI_INVALID_PARAMETERS")); + tr("SMESHGUI_INVALID_PARAMETERS")); return false; } } @@ -317,7 +317,7 @@ void SMESHGUI_FilterTable::AdditionalWidget::SetPrecision(const int theId, const if ( qobject_cast( myWidgets[ theId ] ) ) { SMESHGUI_SpinBox* sb = qobject_cast( myWidgets[ theId ] ); double val = sb->GetValue(); - double min = pow(10, -(sb->decimals())); + double min = pow(10.0, -(sb->decimals())); sb->RangeStepAndValidator( 0., 1.e20, 0.1, precision ? precision : "len_tol_precision" ); sb->SetValue( qMax( val, min ) ); } @@ -968,13 +968,16 @@ bool SMESHGUI_FilterTable::IsValid (const bool theMess, const int theEntityType) QtxColorButton* clrBtn = qobject_cast(aTable->cellWidget(i, 2)); if (clrBtn && !clrBtn->color().isValid()) errMsg = tr( "GROUPCOLOR_ERROR" ); - } else if (aCriterion == SMESH::FT_RangeOfIds || - aCriterion == SMESH::FT_BelongToGeom || - aCriterion == SMESH::FT_BelongToPlane || - aCriterion == SMESH::FT_BelongToCylinder || - aCriterion == SMESH::FT_BelongToGenSurface || - aCriterion == SMESH::FT_ElemGeomType || - aCriterion == SMESH::FT_LyingOnGeom) { + } + else if (aCriterion == SMESH::FT_RangeOfIds || + aCriterion == SMESH::FT_BelongToGeom || + aCriterion == SMESH::FT_BelongToPlane || + aCriterion == SMESH::FT_BelongToCylinder || + aCriterion == SMESH::FT_BelongToGenSurface || + aCriterion == SMESH::FT_ElemGeomType || + aCriterion == SMESH::FT_CoplanarFaces || + aCriterion == SMESH::FT_LyingOnGeom) + { if (aTable->text(i, 2).isEmpty()) errMsg = tr( "ERROR" ); } @@ -988,8 +991,8 @@ bool SMESHGUI_FilterTable::IsValid (const bool theMess, const int theEntityType) if (!aRes && aTable->isEditable(i, 2)) errMsg = tr( "ERROR" ); else if (aType == SMESH::EDGE && - GetCriterionType(i, aType) == SMESH::FT_MultiConnection && - aThreshold == 1) + GetCriterionType(i, aType) == SMESH::FT_MultiConnection && + aThreshold == 1) errMsg = tr( "MULTIEDGES_ERROR" ); } @@ -1088,12 +1091,14 @@ void SMESHGUI_FilterTable::GetCriterion (const int theRow, } else if ( aCriterionType == SMESH::FT_ElemGeomType ) theCriterion.Threshold = (double)((ComboItem*)aTable->item(theRow, 2))->value(); + else if ( aCriterionType == SMESH::FT_CoplanarFaces ) + theCriterion.ThresholdID = aTable->text(theRow, 2).toLatin1().constData(); else if ( aCriterionType != SMESH::FT_RangeOfIds && aCriterionType != SMESH::FT_BelongToGeom && aCriterionType != SMESH::FT_BelongToPlane && aCriterionType != SMESH::FT_BelongToCylinder && aCriterionType != SMESH::FT_BelongToGenSurface && - aCriterionType != SMESH::FT_LyingOnGeom) + aCriterionType != SMESH::FT_LyingOnGeom ) { theCriterion.Compare = ((ComboItem*)aTable->item(theRow, 1))->value(); theCriterion.Threshold = aTable->item(theRow, 2)->text().toDouble(); @@ -1159,19 +1164,26 @@ void SMESHGUI_FilterTable::SetCriterion (const int theRow, ComboItem* typeBox = (ComboItem*)aTable->item(theRow, 2); typeBox->setValue( (int)(theCriterion.Threshold + 0.5) ); } + else if (theCriterion.Type == SMESH::FT_CoplanarFaces ) + { + aTable->item( theRow, 2 )->setText( QString( theCriterion.ThresholdID ) ); + } else if (theCriterion.Type != SMESH::FT_RangeOfIds && - theCriterion.Type != SMESH::FT_BelongToGeom && - theCriterion.Type != SMESH::FT_BelongToPlane && - theCriterion.Type != SMESH::FT_BelongToCylinder && - theCriterion.Type != SMESH::FT_BelongToGenSurface && - theCriterion.Type != SMESH::FT_LyingOnGeom && - theCriterion.Type != SMESH::FT_FreeBorders && - theCriterion.Type != SMESH::FT_FreeEdges && - theCriterion.Type != SMESH::FT_FreeNodes && - theCriterion.Type != SMESH::FT_FreeFaces && - theCriterion.Type != SMESH::FT_BadOrientedVolume && - theCriterion.Type != SMESH::FT_LinearOrQuadratic) + theCriterion.Type != SMESH::FT_BelongToGeom && + theCriterion.Type != SMESH::FT_BelongToPlane && + theCriterion.Type != SMESH::FT_BelongToCylinder && + theCriterion.Type != SMESH::FT_BelongToGenSurface && + theCriterion.Type != SMESH::FT_LyingOnGeom && + theCriterion.Type != SMESH::FT_CoplanarFaces && + theCriterion.Type != SMESH::FT_FreeBorders && + theCriterion.Type != SMESH::FT_FreeEdges && + theCriterion.Type != SMESH::FT_FreeNodes && + theCriterion.Type != SMESH::FT_FreeFaces && + theCriterion.Type != SMESH::FT_BadOrientedVolume && + theCriterion.Type != SMESH::FT_LinearOrQuadratic) + { aTable->item( theRow, 2 )->setText(QString("%1").arg(theCriterion.Threshold, 0, 'g', 15)); + } else { aTable->item( theRow, 2 )->setText(QString(theCriterion.ThresholdStr)); @@ -1179,24 +1191,25 @@ void SMESHGUI_FilterTable::SetCriterion (const int theRow, aTable->item( theRow, 5 )->setText( QString( theCriterion.ThresholdID ) ); } - if (theCriterion.Compare == SMESH::FT_EqualTo || - theCriterion.Type == SMESH::FT_BelongToPlane || - theCriterion.Type == SMESH::FT_BelongToCylinder || - theCriterion.Type == SMESH::FT_BelongToGenSurface || - theCriterion.Type == SMESH::FT_BelongToGeom || - theCriterion.Type == SMESH::FT_LyingOnGeom) + if (theCriterion.Compare == SMESH::FT_EqualTo || + theCriterion.Type == SMESH::FT_BelongToPlane || + theCriterion.Type == SMESH::FT_BelongToCylinder || + theCriterion.Type == SMESH::FT_BelongToGenSurface || + theCriterion.Type == SMESH::FT_BelongToGeom || + theCriterion.Type == SMESH::FT_LyingOnGeom || + theCriterion.Type == SMESH::FT_CoplanarFaces) { QTableWidgetItem* anItem = aTable->item(theRow, 0); if (!myAddWidgets.contains(anItem)) { myAddWidgets[ anItem ] = new AdditionalWidget(myWgStack); + myAddWidgets[ anItem ]->SetPrecision( AdditionalWidget::Tolerance, getPrecision( theCriterion.Type ) ); myWgStack->addWidget(myAddWidgets[ anItem ]); } myAddWidgets[ anItem ]->SetDouble(AdditionalWidget::Tolerance, theCriterion.Tolerance); } emit CriterionChanged(theRow, aType); - } //======================================================================= @@ -1324,11 +1337,13 @@ void SMESHGUI_FilterTable::updateAdditionalWidget() ComboItem* anItem = ((ComboItem*)aTable->item(aRow, 0)); int aCriterion = GetCriterionType(aRow); - bool toEnable = ((ComboItem*)aTable->item(aRow, 1))->value() == SMESH::FT_EqualTo && - aCriterion != SMESH::FT_RangeOfIds && - aCriterion != SMESH::FT_FreeEdges && - aCriterion != SMESH::FT_FreeFaces && - aCriterion != SMESH::FT_BadOrientedVolume; + bool toEnable = ((((ComboItem*)aTable->item(aRow, 1))->value() == SMESH::FT_EqualTo && + aCriterion != SMESH::FT_RangeOfIds && + aCriterion != SMESH::FT_FreeEdges && + aCriterion != SMESH::FT_FreeFaces && + aCriterion != SMESH::FT_BadOrientedVolume) + || + aCriterion == SMESH::FT_CoplanarFaces); if (!myAddWidgets.contains(anItem)) { @@ -1352,6 +1367,7 @@ const char* SMESHGUI_FilterTable::getPrecision( const int aType ) case SMESH::FT_Warping: case SMESH::FT_MinimumAngle: case SMESH::FT_Skew: + case SMESH::FT_CoplanarFaces: retval = "angle_precision"; break; case SMESH::FT_Area: retval = "area_precision"; break; @@ -1466,7 +1482,7 @@ void SMESHGUI_FilterTable::onCriterionChanged (const int row, const int col, con bool isComboItem = false; if (aTableItem) { int aTableType = aTable->item(row, 2)->type(); - isComboItem = aTableType == aComboType ? true : false; + isComboItem = ( aTableType == aComboType ); } if ( (aCriterionType != SMESH::FT_GroupColor && clrBtn) || @@ -1500,14 +1516,16 @@ void SMESHGUI_FilterTable::onCriterionChanged (const int row, const int col, con aTable->blockSignals( isSignalsBlocked ); } - if (aType == SMESH::NODE && aCriterionType == SMESH::FT_FreeNodes || - aType == SMESH::EDGE && aCriterionType == SMESH::FT_FreeBorders || - aType == SMESH::FACE && (aCriterionType == SMESH::FT_FreeEdges || - aCriterionType == SMESH::FT_FreeFaces) || - aType == SMESH::VOLUME && aCriterionType == SMESH::FT_BadOrientedVolume || + if ((aType == SMESH::NODE && aCriterionType == SMESH::FT_FreeNodes ) || + (aType == SMESH::EDGE && aCriterionType == SMESH::FT_FreeBorders ) || + (aType == SMESH::FACE && (aCriterionType == SMESH::FT_FreeEdges || + aCriterionType == SMESH::FT_FreeFaces)) || + (aType == SMESH::VOLUME && aCriterionType == SMESH::FT_BadOrientedVolume) || aCriterionType == SMESH::FT_LinearOrQuadratic || aCriterionType == SMESH::FT_GroupColor || - aCriterionType == SMESH::FT_ElemGeomType) + aCriterionType == SMESH::FT_ElemGeomType || + aCriterionType == SMESH::FT_CoplanarFaces + ) { bool isSignalsBlocked = aTable->signalsBlocked(); aTable->blockSignals( true ); @@ -1516,7 +1534,8 @@ void SMESHGUI_FilterTable::onCriterionChanged (const int row, const int col, con aCompareItem->clear(); aTable->setEditable(false, row, 1); aTable->setEditable(aCriterionType == SMESH::FT_GroupColor || - aCriterionType == SMESH::FT_ElemGeomType, row, 2); + aCriterionType == SMESH::FT_ElemGeomType || + aCriterionType == SMESH::FT_CoplanarFaces, row, 2); aTable->blockSignals( isSignalsBlocked ); } else if (aCriterionType == SMESH::FT_RangeOfIds || @@ -1789,6 +1808,7 @@ const QMap& SMESHGUI_FilterTable::getCriteria (const int theType) aCriteria[ SMESH::FT_LinearOrQuadratic ] = tr("LINEAR"); aCriteria[ SMESH::FT_GroupColor ] = tr("GROUP_COLOR"); aCriteria[ SMESH::FT_ElemGeomType ] = tr("GEOM_TYPE"); + aCriteria[ SMESH::FT_CoplanarFaces ] = tr("COPLANAR_FACES"); } return aCriteria; } @@ -2116,8 +2136,8 @@ bool SMESHGUI_FilterTable::GetThreshold (const int theRow, // Purpose : Set text and internal value in cell of ID value //======================================================================= void SMESHGUI_FilterTable::SetID( const int theRow, - const QString& theText, - const int theEntityType ) + const QString& theText, + const int theEntityType ) { Table* aTable = myTables[ theEntityType == -1 ? GetType() : theEntityType ]; aTable->item( theRow, 5 )->setText( theText ); @@ -2638,7 +2658,8 @@ bool SMESHGUI_FilterDlg::isValid() const aType == SMESH::FT_BelongToPlane || aType == SMESH::FT_BelongToCylinder || aType == SMESH::FT_BelongToGenSurface || - aType == SMESH::FT_LyingOnGeom) { + aType == SMESH::FT_LyingOnGeom) + { QString aName; myTable->GetThreshold(i, aName); @@ -2687,6 +2708,29 @@ bool SMESHGUI_FilterDlg::isValid() const } } } + else if (aType == SMESH::FT_CoplanarFaces) + { + QString faceID; + myTable->GetThreshold(i, faceID); + if ( faceID.isEmpty() ) + { + SUIT_MessageBox::information(SMESHGUI::desktop(), tr("SMESH_INSUFFICIENT_DATA"), + tr("FACE_ID_NOT_SELECTED")); + return false; + } + if ( myMesh->_is_nil() ) + { + SUIT_MessageBox::information(SMESHGUI::desktop(), tr("SMESH_INSUFFICIENT_DATA"), + tr("MESH_IS_NOT_SELECTED")); + return false; + } + if ( myMesh->GetElementType( faceID.toLong(), /*iselem=*/true) != SMESH::FACE ) + { + SUIT_MessageBox::information(SMESHGUI::desktop(), tr("SMESH_INSUFFICIENT_DATA"), + tr("NOT_FACE_ID").arg(faceID)); + return false; + } + } } return true; @@ -2705,7 +2749,7 @@ void SMESHGUI_FilterDlg::SetSourceWg (QWidget* theWg, } //======================================================================= -// name : SMESHGUI_FilterDlg::SetGroupIds +// name : SMESHGUI_FilterDlg::SetMesh // Purpose : Set mesh //======================================================================= void SMESHGUI_FilterDlg::SetMesh (SMESH::SMESH_Mesh_var theMesh) @@ -3067,19 +3111,30 @@ void SMESHGUI_FilterDlg::onSelectionDone() QList types; types << SMESH::FT_BelongToGeom << SMESH::FT_BelongToPlane << SMESH::FT_BelongToCylinder << SMESH::FT_BelongToGenSurface - << SMESH::FT_LyingOnGeom; + << SMESH::FT_LyingOnGeom << SMESH::FT_CoplanarFaces; if (aList.Extent() != 1 || !myTable->CurrentCell(aRow, aCol) || !types.contains(myTable->GetCriterionType(aRow))) return; - Handle(SALOME_InteractiveObject) anIO = aList.First(); - GEOM::GEOM_Object_var anObj = SMESH::IObjectToInterface(anIO); - if (!anObj->_is_nil()) + if ( myTable->GetCriterionType(aRow) == SMESH::FT_CoplanarFaces ) + { + QString aString; + int nbElems = SMESH::GetNameOfSelectedElements(mySelector,//myViewWindow->GetSelector(), + aList.First(), aString); + if (nbElems == 1) + myTable->SetThreshold(aRow, aString); + } + else + { + Handle(SALOME_InteractiveObject) anIO = aList.First(); + GEOM::GEOM_Object_var anObj = SMESH::IObjectToInterface(anIO); + if (!anObj->_is_nil()) { myTable->SetThreshold(aRow, GEOMBase::GetName(anObj)); //myTable->SetID( aRow, GEOMBase::GetIORFromObject(anObj)); myTable->SetID(aRow, anIO->getEntry()); } + } } @@ -3110,9 +3165,9 @@ void SMESHGUI_FilterDlg::updateSelection() if (mySelectionMgr == 0) return; - TColStd_MapOfInteger allTypes; - for( int i=0; i<10; i++ ) - allTypes.Add( i ); +// TColStd_MapOfInteger allTypes; +// for( int i=0; i<10; i++ ) +// allTypes.Add( i ); SalomeApp_Study* aStudy = dynamic_cast( mySMESHGUI->application()->activeStudy() ); if( !aStudy ) return; @@ -3128,8 +3183,8 @@ void SMESHGUI_FilterDlg::updateSelection() aCriterionType == SMESH::FT_BelongToPlane || aCriterionType == SMESH::FT_BelongToCylinder || aCriterionType == SMESH::FT_BelongToGenSurface || - aCriterionType == SMESH::FT_LyingOnGeom)) { - + aCriterionType == SMESH::FT_LyingOnGeom)) + { if (aCriterionType == SMESH::FT_BelongToGeom || aCriterionType == SMESH::FT_BelongToGenSurface || aCriterionType == SMESH::FT_LyingOnGeom) { @@ -3144,9 +3199,12 @@ void SMESHGUI_FilterDlg::updateSelection() } myIsSelectionChanged = true; - } else { + } + else + { if (myIsSelectionChanged) { - mySelectionMgr->installFilter( new GEOM_TypeFilter( aStudy, -1 ) ); // This filter deactivates selection + // mySelectionMgr->installFilter( new GEOM_TypeFilter( aStudy, -1 ) ); // This filter deactivates selection + // Impossible to select any object in the OB on the second opening of FilterDlg } } } diff --git a/src/SMESHGUI/SMESHGUI_GroupOnShapeDlg.cxx b/src/SMESHGUI/SMESHGUI_GroupOnShapeDlg.cxx index 9fefa98da..581aa5326 100644 --- a/src/SMESHGUI/SMESHGUI_GroupOnShapeDlg.cxx +++ b/src/SMESHGUI/SMESHGUI_GroupOnShapeDlg.cxx @@ -301,7 +301,7 @@ bool SMESHGUI_GroupOnShapeOp::onApply() if ( !aStudy ) return false; // mesh - _PTR(SObject) meshSO = aStudy->FindObjectID( myMeshID.toLatin1().data() ); + _PTR(SObject) meshSO = aStudy->FindObjectID( myMeshID.toLatin1().data() ); SMESH::SMESH_Mesh_var mesh = SMESH::SObjectToInterface( meshSO ); if ( mesh->_is_nil() ) return false; @@ -352,7 +352,15 @@ bool SMESHGUI_GroupOnShapeOp::onApply() update( UF_ObjBrowser | UF_Model ); - init(); + // Re-init controls to create the next group + myElemGeoIDs.clear(); + myNodeGeoIDs.clear(); + removeCustomFilters(); + myDlg->myNodeGeomList->clear(); + myDlg->myElemGeomList->clear(); + myDlg->myElemGeomBtn->setChecked(false); + myDlg->myNodeGeomBtn->setChecked(false); + myDlg->updateButtons(); return !group->_is_nil(); } diff --git a/src/SMESHGUI/SMESHGUI_Make2DFrom3DOp.cxx b/src/SMESHGUI/SMESHGUI_Make2DFrom3DOp.cxx index ffbc3b80d..4ffc3f09e 100644 --- a/src/SMESHGUI/SMESHGUI_Make2DFrom3DOp.cxx +++ b/src/SMESHGUI/SMESHGUI_Make2DFrom3DOp.cxx @@ -16,235 +16,389 @@ // // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // +// File : SMESHGUI_Make2DFrom3D.cxx +// Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com) -// File : SMESHGUI_Make2DFrom3DOp.cxx -// Author : Open CASCADE S.A.S. -// SMESH includes -// #include "SMESHGUI_Make2DFrom3DOp.h" #include "SMESHGUI.h" #include "SMESHGUI_Utils.h" -#include "SMESHGUI_VTKUtils.h" #include "SMESHGUI_MeshUtils.h" -#include "SMESHGUI_MeshInfosBox.h" +#include "SMESH_TypeFilter.hxx" +#include "SMESH_LogicalFilter.hxx" // SALOME GUI includes -#include - +#include +#include +#include #include #include -#include #include -#include - -// SALOME KERNEL includes -#include -#include - -// Qt includes // IDL includes #include -#include CORBA_SERVER_HEADER(SMESH_Gen) -#include CORBA_SERVER_HEADER(SMESH_MeshEditor) +#include CORBA_SERVER_HEADER(SMESH_Group) -#include -#include -#include +// Qt includes #include -#include -#include - -// MESH includes -#include "SMDSAbs_ElementType.hxx" -#include "SMDSAbs_ElementType.hxx" - +#include +#include +#include +#include +#include #define SPACING 6 #define MARGIN 11 -// ========================================================================================= /*! - * \brief Dialog to show creted mesh statistic - */ -//======================================================================= + \class SMESHGUI_Make2DFrom3DDlg + \brief Copy Mesh dialog box +*/ SMESHGUI_Make2DFrom3DDlg::SMESHGUI_Make2DFrom3DDlg( QWidget* parent ) - : SMESHGUI_Dialog( parent, false, true, Close/* | Help*/ ) + : SMESHGUI_Dialog( parent, false, true, OK | Apply | Close | Help ) { + // title setWindowTitle( tr("CAPTION") ); - QVBoxLayout* aDlgLay = new QVBoxLayout (mainFrame()); + + // mesh + setObjectPixmap( "SMESH", tr( "ICON_SELECT" ) ); + createObject( tr( "MESH" ), mainFrame(), Mesh ); + + // mode + QGroupBox* aModeGrp = new QGroupBox( tr( "MODE" ), mainFrame() ); + QHBoxLayout* aModeGrpLayout = new QHBoxLayout( aModeGrp ); + aModeGrpLayout->setMargin( MARGIN ); + aModeGrpLayout->setSpacing( SPACING ); + my2dFrom3dRB = new QRadioButton( tr( "2D_FROM_3D" ), aModeGrp ); + my1dFrom2dRB = new QRadioButton( tr( "1D_FROM_2D" ), aModeGrp ); + my1dFrom3dRB = new QRadioButton( tr( "1D_FROM_3D" ), aModeGrp ); + aModeGrpLayout->addWidget( my2dFrom3dRB ); + aModeGrpLayout->addWidget( my1dFrom2dRB ); + aModeGrpLayout->addWidget( my1dFrom3dRB ); + + // target + QGroupBox* aTargetGrp = new QGroupBox( tr( "TARGET" ), mainFrame() ); + QGridLayout* aTargetGrpLayout = new QGridLayout( aTargetGrp ); + aTargetGrpLayout->setMargin( MARGIN ); + aTargetGrpLayout->setSpacing( SPACING ); + myThisMeshRB = new QRadioButton( tr( "THIS_MESH" ), aTargetGrp ); + myNewMeshRB = new QRadioButton( tr( "NEW_MESH" ), aTargetGrp ); + myMeshName = new QLineEdit( aTargetGrp ); + myCopyCheck = new QCheckBox( tr( "COPY_SRC" ), aTargetGrp ); + myMissingCheck = new QCheckBox( tr( "MISSING_ONLY" ), aTargetGrp ); + aTargetGrpLayout->addWidget( myThisMeshRB, 0, 0 ); + aTargetGrpLayout->addWidget( myNewMeshRB, 1, 0 ); + aTargetGrpLayout->addWidget( myMeshName, 1, 1 ); + aTargetGrpLayout->addWidget( myCopyCheck, 2, 0 ); + aTargetGrpLayout->addWidget( myMissingCheck, 2, 1 ); + myGroupCheck = new QCheckBox( tr( "CREATE_GROUP" ), mainFrame() ); + myGroupName = new QLineEdit( mainFrame() ); + + // layout + QGridLayout* aDlgLay = new QGridLayout( mainFrame() ); aDlgLay->setMargin( 0 ); aDlgLay->setSpacing( SPACING ); - QFrame* aMainFrame = createMainFrame(mainFrame()); - aDlgLay->addWidget(aMainFrame); - aDlgLay->setStretchFactor(aMainFrame, 1); + aDlgLay->addWidget( objectWg( Mesh, Label ), 0, 0 ); + aDlgLay->addWidget( objectWg( Mesh, Btn ), 0, 1 ); + aDlgLay->addWidget( objectWg( Mesh, Control ), 0, 2 ); + aDlgLay->addWidget( aModeGrp, 1, 0, 1, 3 ); + aDlgLay->addWidget( aTargetGrp, 2, 0, 1, 3 ); + aDlgLay->addWidget( myGroupCheck, 3, 0 ); + aDlgLay->addWidget( myGroupName, 3, 1, 1, 2 ); + + // connect signals + connect( myThisMeshRB, SIGNAL( clicked() ), this, SLOT( onTargetChanged() ) ); + connect( myNewMeshRB, SIGNAL( clicked() ), this, SLOT( onTargetChanged() ) ); + connect( myGroupCheck, SIGNAL( clicked() ), this, SLOT( onGroupChecked() ) ); + + // init dlg + my2dFrom3dRB->setChecked( true ); + myThisMeshRB->setChecked( true ); + myMissingCheck->setChecked( true ); + onTargetChanged(); + onGroupChecked(); } -// ========================================================================================= -/*! - * \brief Dialog destructor - */ -//======================================================================= - SMESHGUI_Make2DFrom3DDlg::~SMESHGUI_Make2DFrom3DDlg() { } -//======================================================================= -// function : createMainFrame() -// purpose : Create frame containing dialog's fields -//======================================================================= - -QFrame* SMESHGUI_Make2DFrom3DDlg::createMainFrame (QWidget* theParent) +SMESH::Bnd_Dimension SMESHGUI_Make2DFrom3DDlg::mode() const { - QFrame* aFrame = new QFrame(theParent); + if ( my2dFrom3dRB->isChecked() ) + return SMESH::BND_2DFROM3D; + else if ( my1dFrom2dRB->isChecked() ) + return SMESH::BND_1DFROM2D; + else + return SMESH::BND_1DFROM3D; +} - SUIT_ResourceMgr* rm = resourceMgr(); - QPixmap iconCompute (rm->loadPixmap("SMESH", tr("ICON_2D_FROM_3D"))); +bool SMESHGUI_Make2DFrom3DDlg::needNewMesh() const +{ + return myNewMeshRB->isChecked(); +} - // Mesh name - QGroupBox* nameBox = new QGroupBox(tr("SMESH_MESHINFO_NAME"), aFrame ); - QHBoxLayout* nameBoxLayout = new QHBoxLayout(nameBox); - nameBoxLayout->setMargin(MARGIN); nameBoxLayout->setSpacing(SPACING); - myMeshName = new QLabel(nameBox); - nameBoxLayout->addWidget(myMeshName); +QString SMESHGUI_Make2DFrom3DDlg::getNewMeshName() const +{ + return myMeshName->text().trimmed(); +} - // Mesh Info +void SMESHGUI_Make2DFrom3DDlg::setNewMeshName( const QString& name ) +{ + myMeshName->setText( name ); +} - myFullInfo = new SMESHGUI_MeshInfosBox(true, aFrame); +bool SMESHGUI_Make2DFrom3DDlg::needGroup() const +{ + return myGroupCheck->isChecked(); +} - // add all widgets to aFrame - QVBoxLayout* aLay = new QVBoxLayout(aFrame); - aLay->setMargin( 0 ); - aLay->setSpacing( 0 ); - aLay->addWidget( nameBox ); - aLay->addWidget( myFullInfo ); +QString SMESHGUI_Make2DFrom3DDlg::getGroupName() const +{ + return myGroupName->text().trimmed(); +} - ((QPushButton*) button( OK ))->setDefault( true ); - return aFrame; +void SMESHGUI_Make2DFrom3DDlg::setGroupName( const QString& name ) +{ + myGroupName->setText( name ); } -//================================================================================ -/*! - * \brief set name of the mesh -*/ -//================================================================================ +bool SMESHGUI_Make2DFrom3DDlg::copySource() const +{ + return myCopyCheck->isChecked(); +} -void SMESHGUI_Make2DFrom3DDlg::SetMeshName(const QString& theName) +bool SMESHGUI_Make2DFrom3DDlg::copyMissingOnly() const { - myMeshName->setText( theName ); + return myMissingCheck->isChecked(); } -//================================================================================ -/*! - * \brief set mesh info -*/ -//================================================================================ +void SMESHGUI_Make2DFrom3DDlg::onTargetChanged() +{ + myMeshName->setEnabled( myNewMeshRB->isChecked() ); + myCopyCheck->setEnabled( myNewMeshRB->isChecked() ); + myMissingCheck->setEnabled( myNewMeshRB->isChecked() ); +} -void SMESHGUI_Make2DFrom3DDlg::SetMeshInfo(const SMESH::long_array& theInfo) +void SMESHGUI_Make2DFrom3DDlg::onGroupChecked() { - myFullInfo->SetMeshInfo( theInfo ); + myGroupName->setEnabled( myGroupCheck->isChecked() ); } -//================================================================================ /*! - * \brief Constructor + \class SMESHGUI_Make2DFrom3DOp + \brief Copy Mesh operation class */ -//================================================================================ SMESHGUI_Make2DFrom3DOp::SMESHGUI_Make2DFrom3DOp() - : SMESHGUI_Operation() + : SMESHGUI_SelectionOp() { - myDlg = new SMESHGUI_Make2DFrom3DDlg(desktop()); } -//================================================================================ -/*! - * \brief Desctructor -*/ -//================================================================================ - SMESHGUI_Make2DFrom3DOp::~SMESHGUI_Make2DFrom3DOp() { + if ( myDlg ) + delete myDlg; } -//================================================================================ -/*! - * \brief perform it's intention action: compute 2D mesh on 3D - */ -//================================================================================ +LightApp_Dialog* SMESHGUI_Make2DFrom3DOp::dlg() const +{ + return myDlg; +} void SMESHGUI_Make2DFrom3DOp::startOperation() { - myMesh = SMESH::SMESH_Mesh::_nil(); + if( !myDlg ) + myDlg = new SMESHGUI_Make2DFrom3DDlg( desktop() ); + + mySrc = SMESH::SMESH_IDSource::_nil(); - // check selection - LightApp_SelectionMgr *Sel = selectionMgr(); - SALOME_ListIO selected; Sel->selectedObjects( selected ); + myHelpFileName = "make_2dmesh_from_3d_page.html"; - int nbSel = selected.Extent(); - if (nbSel != 1) { - SUIT_MessageBox::warning(desktop(), - tr("SMESH_WRN_WARNING"), - tr("SMESH_WRN_NO_AVAILABLE_DATA")); - onCancel(); - return; - } + SMESHGUI_SelectionOp::startOperation(); + + myDlg->activateObject( SMESHGUI_Make2DFrom3DDlg::Mesh ); + myDlg->setNewMeshName( SMESH::UniqueName( "Mesh_1" ) ); + myDlg->setGroupName( SMESH::UniqueName( "Group" ) ); + myDlg->show(); + + selectionDone(); +} - Handle(SALOME_InteractiveObject) anIO = selected.First(); - myMesh = SMESH::GetMeshByIO(anIO); - if (myMesh->_is_nil()) { - SUIT_MessageBox::warning(desktop(), - tr("SMESH_WRN_WARNING"), - tr("SMESH_WRN_NO_AVAILABLE_DATA")); - onCancel(); - return; +void SMESHGUI_Make2DFrom3DOp::selectionDone() +{ + if ( !dlg() ) return; + + if ( dlg()->isVisible() ) { + try { + QStringList names, ids; + LightApp_Dialog::TypesList types; + selected( names, types, ids ); + if ( names.count() == 1 ) + myDlg->selectObject( names, types, ids ); + else + myDlg->clearSelection(); + } + catch ( const SALOME::SALOME_Exception& S_ex ) { + SalomeApp_Tools::QtCatchCorbaException( S_ex ); + } + catch ( ... ) { + } } +} - SMESHGUI_Operation::startOperation(); +SUIT_SelectionFilter* SMESHGUI_Make2DFrom3DOp::createFilter( const int theId ) const +{ + SUIT_SelectionFilter* f = 0; + if ( theId == SMESHGUI_Make2DFrom3DDlg::Mesh ) { + QList filters; + filters.append( new SMESH_TypeFilter( MESHorSUBMESH ) ); + filters.append( new SMESH_TypeFilter( GROUP ) ); + f = new SMESH_LogicalFilter( filters, SMESH_LogicalFilter::LO_OR ); + } + return f; +} +bool SMESHGUI_Make2DFrom3DOp::isValid( QString& msg ) const +{ + if ( !dlg() ) return false; + + // check if any source data is selected + QString entry = myDlg->selectedObject( SMESHGUI_Make2DFrom3DDlg::Mesh ); + SMESH::SMESH_IDSource_var obj; + _PTR(SObject) sobj = SMESHGUI::activeStudy()->studyDS()->FindObjectID( entry.toLatin1().constData() ); + if ( sobj ) + obj = SMESH::SObjectToInterface( sobj ); + + if ( obj->_is_nil() ) { + msg = tr( "SMESH_ERR_NO_INPUT_MESH" ); + return false; + } - // backup mesh info before 2D mesh computation - SMESH::long_array_var anOldInfo = myMesh->GetMeshInfo(); + // check if source contains elements of required type + SMESH::Bnd_Dimension mode = myDlg->mode(); + SMESH::array_of_ElementType_var types = obj->GetTypes(); + bool has3d = false; + bool has2d = false; + for ( int i = 0; i < types->length(); i++ ) { + if ( types[i] == SMESH::VOLUME ) has3d = true; + else if ( types[i] == SMESH::FACE ) has2d = true; + } - if (!compute2DMesh()) { - SUIT_MessageBox::warning(desktop(), - tr("SMESH_WRN_WARNING"), - tr("SMESH_WRN_COMPUTE_FAILED")); - onCancel(); - return; - } - // get new mesh statistic - SMESH::long_array_var aNewInfo = myMesh->GetMeshInfo(); - // get difference in mesh statistic from old to new - for ( int i = SMDSEntity_Node; i < SMDSEntity_Last; i++ ) - aNewInfo[i] -= anOldInfo[i]; - - // update presentation - SMESH::Update(anIO, SMESH::eDisplay); - - // show computated result - _PTR(SObject) aMeshSObj = SMESH::FindSObject(myMesh); - if ( aMeshSObj ) - myDlg->SetMeshName( aMeshSObj->GetName().c_str() ); - myDlg->SetMeshInfo( aNewInfo ); - myDlg->show(); /*exec();*/ - commit(); - SMESHGUI::Modified(); -} - -//================================================================================ -/*! - * \brief compute 2D mesh on initial 3D - */ -//================================================================================ + if ( ( mode == SMESH::BND_2DFROM3D || mode == SMESH::BND_1DFROM3D ) && !has3d ) { + msg = tr( "SMESH_ERR_NO_3D_ELEMENTS" ); + return false; + } + else if ( mode == SMESH::BND_1DFROM2D && !has2d ) { + msg = tr( "SMESH_ERR_NO_2D_ELEMENTS" ); + return false; + } + + // check if new mesh name is specified + if ( myDlg->needNewMesh() && myDlg->getNewMeshName().isEmpty() ) { + msg = tr( "SMESH_ERR_MESH_NAME_NOT_SPECIFIED" ); + return false; + } + + // check if group name is specified + if ( myDlg->needGroup() && myDlg->getGroupName().isEmpty() ) { + msg = tr( "SMESH_ERR_GRP_NAME_NOT_SPECIFIED" ); + return false; + } + + return true; +} bool SMESHGUI_Make2DFrom3DOp::compute2DMesh() { SUIT_OverrideCursor wc; - SMESH::SMESH_MeshEditor_var aMeshEditor = myMesh->GetMeshEditor(); - return aMeshEditor->Make2DMeshFrom3D(); + + bool ok = false; + try { + QString entry = myDlg->selectedObject( SMESHGUI_Make2DFrom3DDlg::Mesh ); + _PTR(SObject) sobj = SMESHGUI::activeStudy()->studyDS()->FindObjectID( entry.toLatin1().constData() ); + SMESH::SMESH_IDSource_var obj = SMESH::SObjectToInterface( sobj ); + + SMESH::Bnd_Dimension mode = myDlg->mode(); + QString meshName = myDlg->needNewMesh() ? myDlg->getNewMeshName() : QString(); + QString groupName = myDlg->needGroup() ? myDlg->getGroupName() : QString(); + bool copySrc = myDlg->copySource(); + bool copyAll = !myDlg->copyMissingOnly(); + + SMESH::SMESH_Mesh_var srcMesh = SMESH::SMESH_Mesh::_narrow( obj ); + if ( CORBA::is_nil( srcMesh ) ) { + SMESH::SMESH_subMesh_var subMesh = SMESH::SMESH_subMesh::_narrow( obj ); + if ( !CORBA::is_nil( subMesh ) ) + srcMesh = subMesh->GetFather(); + } + if ( CORBA::is_nil( srcMesh ) ) { + SMESH::SMESH_GroupBase_var grp = SMESH::SMESH_GroupBase::_narrow( obj ); + if ( !CORBA::is_nil( grp ) ) + srcMesh = grp->GetMesh(); + } + + if ( !CORBA::is_nil( srcMesh ) ) { + SMESH::SMESH_MeshEditor_var aMeshEditor = srcMesh->GetMeshEditor(); + SMESH::SMESH_Group_var newGrp; + SMESH::SMESH_Mesh_var mesh = aMeshEditor->MakeBoundaryMesh( obj.in(), + mode, + groupName.toLatin1().constData(), + meshName.toLatin1().constData(), + copySrc, + copyAll, + newGrp.out() ); + if ( !mesh->_is_nil() ) { +#ifdef WITHGENERICOBJ + mesh->Destroy(); +#endif + } + if ( !newGrp->_is_nil() ) { +#ifdef WITHGENERICOBJ + newGrp->Destroy(); +#endif + } + ok = true; + } + } + catch ( ... ) { + } + return ok; +} + +bool SMESHGUI_Make2DFrom3DOp::onApply() +{ + if ( isStudyLocked() ) + return false; + + QString msg; + if ( !isValid( msg ) ) { + dlg()->show(); + if ( msg != "" ) + SUIT_MessageBox::warning( myDlg, tr( "SMESH_ERROR" ), msg ); + return false; + } + + bool res = false; + try { + res = compute2DMesh(); + } + catch ( const SALOME::SALOME_Exception& S_ex ) { + SalomeApp_Tools::QtCatchCorbaException( S_ex ); + } + catch ( ... ) { + } + + if ( res ) { + SMESHGUI::Modified(); + update( UF_ObjBrowser | UF_Model ); + myDlg->setNewMeshName( SMESH::UniqueName( "Mesh_1" ) ); + myDlg->setGroupName( SMESH::UniqueName( "Group" ) ); + } + else { + SUIT_MessageBox::warning( myDlg, tr( "SMESH_ERROR" ), tr( "SMESH_OPERATION_FAILED" ) ); + } + + return res; } diff --git a/src/SMESHGUI/SMESHGUI_Make2DFrom3DOp.h b/src/SMESHGUI/SMESHGUI_Make2DFrom3DOp.h index f2ef2d9fd..23bab5e61 100644 --- a/src/SMESHGUI/SMESHGUI_Make2DFrom3DOp.h +++ b/src/SMESHGUI/SMESHGUI_Make2DFrom3DOp.h @@ -16,69 +16,96 @@ // // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // - -// SMESH SMESHGUI : GUI for SMESH component // File : SMESHGUI_Make2DFrom3D.h -// Author : Open CASCADE S.A.S. -// +// Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com) + #ifndef SMESHGUI_Make2DFrom3DOp_H #define SMESHGUI_Make2DFrom3DOp_H // SMESH includes #include "SMESH_SMESHGUI.hxx" - #include "SMESHGUI_Dialog.h" -#include "SMESHGUI_Operation.h" +#include "SMESHGUI_SelectionOp.h" -// IDL includes #include -#include CORBA_SERVER_HEADER(SMESH_Mesh) +#include CORBA_SERVER_HEADER(SMESH_MeshEditor) -class QFrame; -class SMESHGUI_MeshInfosBox; +class QCheckBox; +class QLineEdit; +class QRadioButton; /*! * \brief Dialog to show result mesh statistic */ -class SMESHGUI_Make2DFrom3DDlg : public SMESHGUI_Dialog +class SMESHGUI_EXPORT SMESHGUI_Make2DFrom3DDlg : public SMESHGUI_Dialog { Q_OBJECT - public: +public: + enum { Mesh }; + SMESHGUI_Make2DFrom3DDlg( QWidget* ); virtual ~SMESHGUI_Make2DFrom3DDlg(); - void SetMeshName(const QString& theName); - void SetMeshInfo(const SMESH::long_array& theInfo); - - private: - QFrame* createMainFrame( QWidget* ); - - private: - QLabel* myMeshName; - SMESHGUI_MeshInfosBox* myFullInfo; + SMESH::Bnd_Dimension mode() const; + + bool needNewMesh() const; + QString getNewMeshName() const; + void setNewMeshName( const QString& ); + + bool needGroup() const; + QString getGroupName() const; + void setGroupName( const QString& ); + + bool copySource() const; + bool copyMissingOnly() const; + +private slots: + void onTargetChanged(); + void onGroupChecked(); + +private: + QRadioButton* my2dFrom3dRB; + QRadioButton* my1dFrom2dRB; + QRadioButton* my1dFrom3dRB; + QRadioButton* myThisMeshRB; + QRadioButton* myNewMeshRB; + QLineEdit* myMeshName; + QCheckBox* myCopyCheck; + QCheckBox* myMissingCheck; + QCheckBox* myGroupCheck; + QLineEdit* myGroupName; }; - /*! * \brief Operation to compute 2D mesh on 3D */ -class SMESHGUI_Make2DFrom3DOp : public SMESHGUI_Operation +class SMESHGUI_EXPORT SMESHGUI_Make2DFrom3DOp : public SMESHGUI_SelectionOp { - public: + Q_OBJECT + +public: SMESHGUI_Make2DFrom3DOp(); virtual ~SMESHGUI_Make2DFrom3DOp(); - protected: + virtual LightApp_Dialog* dlg() const; + +protected: virtual void startOperation(); + virtual void selectionDone(); + virtual SUIT_SelectionFilter* createFilter( const int ) const; + bool isValid( QString& ) const; + +protected slots: + virtual bool onApply(); - private: +private: bool compute2DMesh(); - private: - SMESH::SMESH_Mesh_var myMesh; +private: + SMESH::SMESH_IDSource_var mySrc; QPointer myDlg; }; diff --git a/src/SMESHGUI/SMESHGUI_MeshUtils.cxx b/src/SMESHGUI/SMESHGUI_MeshUtils.cxx index 0763be3ed..bf53ecd7f 100644 --- a/src/SMESHGUI/SMESHGUI_MeshUtils.cxx +++ b/src/SMESHGUI/SMESHGUI_MeshUtils.cxx @@ -82,4 +82,44 @@ namespace SMESH } return baseName; } + + QString UniqueName(const QString& theBaseName, _PTR(SObject) theParent, const QString& thePostfix) + { + QString baseName = thePostfix.isEmpty() ? + theBaseName : theBaseName + "_" + thePostfix; + QString name = baseName; + if ( _PTR(Study) aStudy = GetActiveStudyDocument() ) { + _PTR(SObject) p = theParent; + if ( !p ) p = aStudy->FindComponent( "SMESH" ); + if ( p ) { + _PTR(ChildIterator) iter = aStudy->NewChildIterator( p ); + int idx = 0; + while( true ) { + bool found = false; + for ( ; iter->More(); iter->Next() ) { + _PTR(SObject) so = iter->Value(); + if ( !so ) continue; // skip bad objects + _PTR(SObject) ref; + if ( so->ReferencedObject( ref ) ) continue; // skip references + QString n = so->GetName().c_str(); + if ( !n.isEmpty() && n == name ) { + QStringList names = name.split("_", QString::KeepEmptyParts); + if ( names.count() > 0 ) { + bool ok; + names.last().toInt( &ok ); + if ( ok ) + names.removeLast(); + } + names.append( QString::number( ++idx ) ); + name = names.join( "_" ); + found = true; + break; + } + } + if ( !found ) break; + } + } + } + return name; + } } // end of namespace SMESH diff --git a/src/SMESHGUI/SMESHGUI_MeshUtils.h b/src/SMESHGUI/SMESHGUI_MeshUtils.h index 5edffe9f3..5a959cb39 100644 --- a/src/SMESHGUI/SMESHGUI_MeshUtils.h +++ b/src/SMESHGUI/SMESHGUI_MeshUtils.h @@ -36,10 +36,15 @@ // SALOME GUI includes #include +// SALOME KERNEL includes +#include + // IDL includes #include #include CORBA_SERVER_HEADER(SMESH_Mesh) +class SALOMEDSClient_SObject; + namespace SMESH { SMESHGUI_EXPORT @@ -47,6 +52,8 @@ namespace SMESH SMESHGUI_EXPORT QString UniqueMeshName( const QString&, const QString& = QString() ); + SMESHGUI_EXPORT + QString UniqueName( const QString&, _PTR(SObject) = _PTR(SObject)(), const QString& = QString() ); } #endif // SMESHGUI_MESHUTILS_H diff --git a/src/SMESHGUI/SMESH_msg_en.ts b/src/SMESHGUI/SMESH_msg_en.ts index 4a3a32e3f..a42af7217 100644 --- a/src/SMESHGUI/SMESH_msg_en.ts +++ b/src/SMESHGUI/SMESH_msg_en.ts @@ -181,7 +181,7 @@ MEN_2D_FROM_3D - Create 2D mesh from 3D + Create boundary elements MEN_MESH_ORDER @@ -2060,6 +2060,12 @@ Consider saving your work before application crash SMESH_WRN_VIEWER_VTK Study frame with VTK Viewer must be activated + + SMESH_WRN_SIZE_LIMIT_EXCEEDED + No automatic update of the presentation has been done: new mesh size (%1 elements) exceeds current size limit (%2 elements). +Please check preferences of Mesh module. + + SMESH_WRN_WARNING Warning @@ -2174,7 +2180,7 @@ Consider saving your work before application crash STB_2D_FROM_3D - Create 2D mesh from 3D + Create boundary elements STB_MESH_ORDER @@ -2694,7 +2700,7 @@ Consider saving your work before application crash TOP_2D_FROM_3D - Create 2D mesh from 3D + Create boundary elements TOP_MESH_ORDER @@ -3246,6 +3252,14 @@ Please, create VTK viewer and try again PREF_AUTO_UPDATE Automatic update + + PREF_UPDATE_LIMIT + Size limit (elements) + + + PREF_UPDATE_LIMIT_NOLIMIT + No limit + PREF_BACKFACE Back face @@ -3346,10 +3360,6 @@ Please, create VTK viewer and try again PREF_GROUP_SELECTION Selection - - PREF_GROUP_UPDATE - Update - PREF_HIGHLIGHT_COLOR Highlight color @@ -3631,13 +3641,6 @@ Please specify it and try again No valid mesh object selected - - SMESHGUI_Make2DFrom3DDlg - - CAPTION - Create 2D mesh from 3D - - SMESHGUI_CreatePatternDlg @@ -3923,6 +3926,16 @@ Please select a face and try again SHAPE_IS_NOT_A_PLANE "%1" is not a plane Please select a plane and try again + + + FACE_ID_NOT_SELECTED + Mesh face is not selected +Please specify it and try again + + + NOT_FACE_ID + "%1" is not an ID of a mesh face. +Please select a face and try again SOURCE @@ -4131,6 +4144,10 @@ Please check input data and try again COMPARE Compare + + COPLANAR_FACES + Coplanar faces + COPY_FROM Copy from... @@ -5248,4 +5265,78 @@ It is impossible to read point coordinates from file Construct group with newly created elements + + SMESHGUI_Make2DFrom3DDlg + + CAPTION + Create boundary elements + + + MESH + Mesh, submesh or group + + + MODE + Mode + + + 2D_FROM_3D + 2D from 3D + + + 1D_FROM_3D + 1D from 3D + + + 1D_FROM_2D + 1D from 2D + + + TARGET + Target + + + THIS_MESH + This mesh + + + NEW_MESH + New mesh + + + COPY_SRC + Copy source mesh + + + MISSING_ONLY + Copy missing elements only + + + CREATE_GROUP + Create group + + + + SMESHGUI_Make2DFrom3DOp + + SMESH_ERR_NO_INPUT_MESH + Source mesh, sub-mesh or group is not specified + + + SMESH_ERR_NO_3D_ELEMENTS + The source object does not contain 3D elements + + + SMESH_ERR_NO_2D_ELEMENTS + The source object does not contain 2D elements + + + SMESH_ERR_MESH_NAME_NOT_SPECIFIED + New mesh name is not specified + + + SMESH_ERR_GRP_NAME_NOT_SPECIFIED + Group name is not specified + + diff --git a/src/SMESHGUI/SMESH_msg_fr.ts b/src/SMESHGUI/SMESH_msg_fr.ts index 4c267d36e..9c648f40a 100755 --- a/src/SMESHGUI/SMESH_msg_fr.ts +++ b/src/SMESHGUI/SMESH_msg_fr.ts @@ -181,7 +181,7 @@ MEN_2D_FROM_3D - Créer un maillage 2D à partir de 3D + Créer les éléments de frontière MEN_MESH_ORDER @@ -2056,6 +2056,12 @@ Enregistrez votre progrès avant que l'application se plante SMESH_WRN_VIEWER_VTK Il faut ouvrir la scène dans le visualisateur VTK + + SMESH_WRN_SIZE_LIMIT_EXCEEDED + La présentation n'a pas été mise à jour automatiquement: la taille nouvelle du maillage (%1 éléments) dépasse la limite de taille actuelle (%2 éléments). +Il serait utile de changer la limite dans les préférences du module Mesh. + + SMESH_WRN_WARNING Avertissement @@ -2170,7 +2176,7 @@ Enregistrez votre progrès avant que l'application se plante STB_2D_FROM_3D - Créer un maillage 2D à partir de 3D + Créer les éléments de frontière STB_MESH_ORDER @@ -2690,7 +2696,7 @@ Enregistrez votre progrès avant que l'application se plante TOP_2D_FROM_3D - Créer un Maillage 2D à partir de 3D + Créer les éléments de frontière TOP_MESH_ORDER @@ -3240,6 +3246,14 @@ Ouvrez le visualisateur VTK et essayez de nouveau PREF_AUTO_UPDATE Mettre à Jour Automatiquement + + PREF_UPDATE_LIMIT + Limite de taille (nombre d'éléments) + + + PREF_UPDATE_LIMIT_NOLIMIT + Sans limite + PREF_BACKFACE Face Arrière @@ -3340,10 +3354,6 @@ Ouvrez le visualisateur VTK et essayez de nouveau PREF_GROUP_SELECTION Sélection - - PREF_GROUP_UPDATE - Mettre à jour - PREF_HIGHLIGHT_COLOR Couleur de sélection @@ -3625,13 +3635,6 @@ Indiquez-le et essayez de nouveau Un maillage valide n'est pas choisi - - SMESHGUI_Make2DFrom3DDlg - - CAPTION - Créer un maillage 2D à partir de 3D - - SMESHGUI_CreatePatternDlg @@ -3752,7 +3755,7 @@ Choisissez un groupe et essayez de nouveau - SMESHGUI_EditMeshDlg + SMESHGUI_MergeDlg COINCIDENT_ELEMENTS Eléments Coïncidents @@ -3773,6 +3776,10 @@ Choisissez un groupe et essayez de nouveau SELECT_ALL Choisir Tous + + EXCLUDE_GROUPS + Exclure les Groupes + SMESHGUI_ExtrusionAlongPathDlg @@ -3913,6 +3920,16 @@ Choisissez une face et essayez de nouveau SHAPE_IS_NOT_A_PLANE "%1" n'est pas un plan Choisissez un plan et essayez de nouveau + + + FACE_ID_NOT_SELECTED + La face de maillage n'est pas choisie. +Indiquez-la et essayez de nouveau. + + + NOT_FACE_ID + "%1" n'est l'ID valide d'une face du maillage. +Choisissez la face et essayez de nouveau. SOURCE @@ -4121,6 +4138,10 @@ Vérifiez la validité de l'information d'entrée et essayez de nouvea COMPARE Comparer + + COPLANAR_FACES + Faces Coplanaires + COPY_FROM Copier de... @@ -4845,6 +4866,10 @@ Il y a trop peu de points au fichier pour charger le circuit SPLIT_HEX_TO_6_TETRA En 6 tétraèdres + + SPLIT_HEX_TO_24_TETRA + En 24 tétraèdres + SMESHGUI_PrecisionDlg @@ -5234,4 +5259,78 @@ Il y a trop peu de points au fichier pour charger le circuit Construire un groupe avec les éléments créés de nouveau + + SMESHGUI_Make2DFrom3DDlg + + CAPTION + Créer les éléments de frontière + + + MESH + Maillage, sous-maillage ou groupe + + + MODE + Mode + + + 2D_FROM_3D + 2D à partir de 3D + + + 1D_FROM_3D + 1D à partir de 3D + + + 1D_FROM_2D + 1D à partir de 2D + + + TARGET + Cible + + + THIS_MESH + Ce maillage + + + NEW_MESH + Maillage nouveau + + + COPY_SRC + Copier le maillage source + + + MISSING_ONLY + Copier seulment les éléments manquants + + + CREATE_GROUP + Créer un groupe + + + + SMESHGUI_Make2DFrom3DOp + + SMESH_ERR_NO_INPUT_MESH + Aucun maillage, sous-maillage ou groupe source n'est indiqué + + + SMESH_ERR_NO_3D_ELEMENTS + L'objet source ne contient pas d'éléments 3D + + + SMESH_ERR_NO_2D_ELEMENTS + L'objet source ne contient pas d'éléments 2D + + + SMESH_ERR_MESH_NAME_NOT_SPECIFIED + Le nouveau nom du maillage n'est pas indiqué + + + SMESH_ERR_GRP_NAME_NOT_SPECIFIED + Le nom du groupe n'est pas indiqué + + diff --git a/src/SMESH_I/SMESH_DumpPython.cxx b/src/SMESH_I/SMESH_DumpPython.cxx index 91aaa656e..4bc9f1aa2 100644 --- a/src/SMESH_I/SMESH_DumpPython.cxx +++ b/src/SMESH_I/SMESH_DumpPython.cxx @@ -287,6 +287,7 @@ namespace SMESH case FT_BelongToCylinder: myStream<< "aBelongToCylinder"; break; case FT_BelongToGenSurface:myStream<<"aBelongToGenSurface";break; case FT_LyingOnGeom: myStream<< "aLyingOnGeom"; break; + case FT_CoplanarFaces: myStream<< "aCoplanarFaces"; break; case FT_RangeOfIds: myStream<< "aRangeOfIds"; break; case FT_BadOrientedVolume:myStream<< "aBadOrientedVolume";break; case FT_LinearOrQuadratic:myStream<< "aLinearOrQuadratic";break; diff --git a/src/SMESH_I/SMESH_Filter_i.cxx b/src/SMESH_I/SMESH_Filter_i.cxx index 67c0addd1..477e92a13 100644 --- a/src/SMESH_I/SMESH_Filter_i.cxx +++ b/src/SMESH_I/SMESH_Filter_i.cxx @@ -1443,7 +1443,7 @@ void ElemGeomType_i::SetGeometryType(GeometryType theType) GeometryType ElemGeomType_i::GetGeometryType() const { - return (GeometryType)myElemGeomTypePtr->GetGeomType();; + return (GeometryType)myElemGeomTypePtr->GetGeomType(); } FunctorType ElemGeomType_i::GetFunctorType() @@ -1451,6 +1451,49 @@ FunctorType ElemGeomType_i::GetFunctorType() return SMESH::FT_ElemGeomType; } +/* + Class : CoplanarFaces_i + Description : Returns true if a mesh face is a coplanar neighbour to a given one +*/ +CoplanarFaces_i::CoplanarFaces_i() +{ + myCoplanarFacesPtr.reset(new Controls::CoplanarFaces()); + myFunctorPtr = myPredicatePtr = myCoplanarFacesPtr; +} + +void CoplanarFaces_i::SetFace ( CORBA::Long theFaceID ) +{ + myCoplanarFacesPtr->SetFace(theFaceID); + TPythonDump()<SetTolerance(theToler); + TPythonDump()<GetFace(); +} + +char* CoplanarFaces_i::GetFaceAsString () const +{ + TCollection_AsciiString str(Standard_Integer(myCoplanarFacesPtr->GetFace())); + return CORBA::string_dup( str.ToCString() ); +} + +CORBA::Double CoplanarFaces_i::GetTolerance() const +{ + return myCoplanarFacesPtr->GetTolerance(); +} + +FunctorType CoplanarFaces_i::GetFunctorType() +{ + return SMESH::FT_CoplanarFaces; +} + /* Class : Comparator_i Description : Base class for comparators @@ -1867,6 +1910,14 @@ LyingOnGeom_ptr FilterManager_i::CreateLyingOnGeom() return anObj._retn(); } +CoplanarFaces_ptr FilterManager_i::CreateCoplanarFaces() +{ + SMESH::CoplanarFaces_i* aServant = new SMESH::CoplanarFaces_i(); + SMESH::CoplanarFaces_var anObj = aServant->_this(); + TPythonDump()<GetElementType(); theCriteria[ i ].Tolerance = aPred->GetTolerance(); + return true; + } + case FT_CoplanarFaces: + { + CoplanarFaces_i* aPred = dynamic_cast( thePred ); + + CORBA::ULong i = theCriteria->length(); + theCriteria->length( i + 1 ); + + theCriteria[ i ] = createCriterion(); + CORBA::String_var faceId = aPred->GetFaceAsString(); + + theCriteria[ i ].Type = FT_CoplanarFaces; + theCriteria[ i ].ThresholdID = faceId; + theCriteria[ i ].Tolerance = aPred->GetTolerance(); + return true; } case FT_RangeOfIds: @@ -2593,6 +2660,14 @@ CORBA::Boolean Filter_i::SetCriteria( const SMESH::Filter::Criteria& theCriteria aPredicate = tmpPred; break; } + case SMESH::FT_CoplanarFaces: + { + SMESH::CoplanarFaces_ptr tmpPred = aFilterMgr->CreateCoplanarFaces(); + tmpPred->SetFace( atol (aThresholdID )); + tmpPred->SetTolerance( aTolerance ); + aPredicate = tmpPred; + break; + } default: continue; diff --git a/src/SMESH_I/SMESH_Filter_i.hxx b/src/SMESH_I/SMESH_Filter_i.hxx index 5451f821f..aefc71ef6 100644 --- a/src/SMESH_I/SMESH_Filter_i.hxx +++ b/src/SMESH_I/SMESH_Filter_i.hxx @@ -622,6 +622,26 @@ namespace SMESH Controls::ElemGeomTypePtr myElemGeomTypePtr; }; + /* + Class : CoplanarFaces_i + Description : Returns true if a mesh face is a coplanar neighbour to a given one + */ + class SMESH_I_EXPORT CoplanarFaces_i: public virtual POA_SMESH::CoplanarFaces, + public virtual Predicate_i + { + public: + CoplanarFaces_i(); + FunctorType GetFunctorType(); + + void SetFace ( CORBA::Long theFaceID ); + void SetTolerance( CORBA::Double theToler ); + char* GetFaceAsString () const; + CORBA::Long GetFace () const; + CORBA::Double GetTolerance () const; + private: + Controls::CoplanarFacesPtr myCoplanarFacesPtr; + }; + /* Class : Comparator_i Description : Base class for comparators @@ -908,13 +928,11 @@ namespace SMESH FreeFaces_ptr CreateFreeFaces(); RangeOfIds_ptr CreateRangeOfIds(); - BadOrientedVolume_ptr CreateBadOrientedVolume(); LinearOrQuadratic_ptr CreateLinearOrQuadratic(); - GroupColor_ptr CreateGroupColor(); - ElemGeomType_ptr CreateElemGeomType(); + CoplanarFaces_ptr CreateCoplanarFaces(); LessThan_ptr CreateLessThan(); MoreThan_ptr CreateMoreThan(); diff --git a/src/SMESH_I/SMESH_Gen_i.cxx b/src/SMESH_I/SMESH_Gen_i.cxx index 96d566b5b..08ce77e36 100644 --- a/src/SMESH_I/SMESH_Gen_i.cxx +++ b/src/SMESH_I/SMESH_Gen_i.cxx @@ -3198,7 +3198,7 @@ SALOMEDS::TMPFile* SMESH_Gen_i::SaveASCII( SALOMEDS::SComponent_ptr theComponent bool isMultiFile ) { if(MYDEBUG) MESSAGE( "SMESH_Gen_i::SaveASCII" ); SALOMEDS::TMPFile_var aStreamFile = Save( theComponent, theURL, isMultiFile ); - //return aStreamFile._retn(); + return aStreamFile._retn(); //after usual saving needs to encipher binary to text string //Any binary symbol will be represent as "|xx" () hexadecimal format number @@ -4300,7 +4300,7 @@ bool SMESH_Gen_i::LoadASCII( SALOMEDS::SComponent_ptr theComponent, const char* theURL, bool isMultiFile ) { if(MYDEBUG) MESSAGE( "SMESH_Gen_i::LoadASCII" ); - //return Load( theComponent, theStream, theURL, isMultiFile ); + return Load( theComponent, theStream, theURL, isMultiFile ); //before call main ::Load method it's need for decipher text format to //binary ( "|xx" => x' ) diff --git a/src/SMESH_I/SMESH_Group_i.cxx b/src/SMESH_I/SMESH_Group_i.cxx index e600c37f0..592d172ba 100644 --- a/src/SMESH_I/SMESH_Group_i.cxx +++ b/src/SMESH_I/SMESH_Group_i.cxx @@ -36,6 +36,8 @@ #include "SMESH_Filter_i.hxx" #include "SMESH_PythonDump.hxx" +#include CORBA_SERVER_HEADER(SMESH_Filter) + #include "utilities.h" using namespace SMESH; @@ -353,19 +355,20 @@ CORBA::Long SMESH_Group_i::AddFrom( SMESH::SMESH_IDSource_ptr theSource ) SMESHDS_Group* aGroupDS = dynamic_cast( GetGroupDS() ); if (aGroupDS) { SMESH::long_array_var anIds; - if ( !CORBA::is_nil(SMESH::SMESH_GroupBase::_narrow(theSource)) && - SMESH::SMESH_GroupBase::_narrow(theSource)->GetType() == GetType() ) { + SMESH::SMESH_GroupBase_var group = SMESH::SMESH_GroupBase::_narrow(theSource); + SMESH::SMESH_Mesh_var mesh = SMESH::SMESH_Mesh::_narrow(theSource); + SMESH::SMESH_subMesh_var submesh = SMESH::SMESH_subMesh::_narrow(theSource); + SMESH::Filter_var filter = SMESH::Filter::_narrow(theSource); + if ( !group->_is_nil()) + anIds = group->GetType()==GetType() ? theSource->GetIDs() : new SMESH::long_array(); + else if ( !mesh->_is_nil() ) + anIds = mesh->GetElementsByType( GetType() ); + else if ( !submesh->_is_nil()) + anIds = submesh->GetElementsByType( GetType() ); + else if ( !filter->_is_nil() ) + anIds = filter->GetElementType()==GetType() ? theSource->GetIDs() : new SMESH::long_array(); + else anIds = theSource->GetIDs(); - } - else if ( !CORBA::is_nil(SMESH::SMESH_Mesh::_narrow(theSource)) ) { - anIds = SMESH::SMESH_Mesh::_narrow(theSource)->GetElementsByType( GetType() ); - } - else if ( !CORBA::is_nil(SMESH::SMESH_subMesh::_narrow(theSource)) ) { - anIds = SMESH::SMESH_subMesh::_narrow(theSource)->GetElementsByType( GetType() ); - } - else { - anIds->length( 0 ); - } for ( int i = 0, total = anIds->length(); i < total; i++ ) { if ( aGroupDS->Add((int)anIds[i]) ) nbAdd++; } diff --git a/src/SMESH_I/SMESH_MeshEditor_i.cxx b/src/SMESH_I/SMESH_MeshEditor_i.cxx index b88de2d39..5da4f5ceb 100644 --- a/src/SMESH_I/SMESH_MeshEditor_i.cxx +++ b/src/SMESH_I/SMESH_MeshEditor_i.cxx @@ -25,6 +25,10 @@ // Author : Nicolas REJNERI // Module : SMESH // +#ifdef WNT +#define NOMINMAX +#endif + #include "SMESH_MeshEditor_i.hxx" #include "SMDS_Mesh0DElement.hxx" @@ -5182,7 +5186,98 @@ CORBA::Boolean SMESH_MeshEditor_i::Make2DMeshFrom3D() ::SMESH_MeshEditor aMeshEditor( myMesh ); bool aResult = aMeshEditor.Make2DMeshFrom3D(); storeResult( aMeshEditor) ; - + TPythonDump() << "isDone = " << this << ".Make2DMeshFrom3D()"; return aResult; } + +// issue 20749 =================================================================== +/*! + * \brief Creates missing boundary elements + * \param elements - elements whose boundary is to be checked + * \param dimension - defines type of boundary elements to create + * \param groupName - a name of group to store created boundary elements in, + * "" means not to create the group + * \param meshName - a name of new mesh to store created boundary elements in, + * "" means not to create the new mesh + * \param toCopyElements - if true, the checked elements will be copied into the new mesh + * \param toCopyExistingBondary - if true, not only new but also pre-existing + * boundary elements will be copied into the new mesh + * \param group - returns the create group, if any + * \retval SMESH::SMESH_Mesh - the mesh where elements were added to + */ +// ================================================================================ + +SMESH::SMESH_Mesh_ptr +SMESH_MeshEditor_i::MakeBoundaryMesh(SMESH::SMESH_IDSource_ptr idSource, + SMESH::Bnd_Dimension dim, + const char* groupName, + const char* meshName, + CORBA::Boolean toCopyElements, + CORBA::Boolean toCopyExistingBondary, + SMESH::SMESH_Group_out group) +{ + initData(); + + if ( dim > SMESH::BND_1DFROM2D ) + THROW_SALOME_CORBA_EXCEPTION("Invalid boundary dimension", SALOME::BAD_PARAM); + + + SMESHDS_Mesh* aMeshDS = GetMeshDS(); + + SMESH::SMESH_Mesh_var mesh_var; + SMESH::SMESH_Group_var group_var; + + TPythonDump pyDump; + + TIDSortedElemSet elements; + SMDSAbs_ElementType elemType = (dim == SMESH::BND_1DFROM2D) ? SMDSAbs_Face : SMDSAbs_Volume; + if ( idSourceToSet( idSource, aMeshDS, elements, elemType,/*emptyIfIsMesh=*/true )) + { + // mesh to fill in + mesh_var = + strlen(meshName) ? makeMesh(meshName) : SMESH::SMESH_Mesh::_duplicate(myMesh_i->_this()); + SMESH_Mesh_i* mesh_i = SMESH::DownCast( mesh_var ); + // other mesh + SMESH_Mesh* smesh_mesh = (mesh_i==myMesh_i) ? (SMESH_Mesh*)0 : &mesh_i->GetImpl(); + + // group of new boundary elements + SMESH_Group* smesh_group = 0; + if ( strlen(groupName) ) + { + group_var = mesh_i->CreateGroup( SMESH::ElementType(elemType),groupName); + if ( SMESH_GroupBase_i* group_i = SMESH::DownCast( group_var )) + smesh_group = group_i->GetSmeshGroup(); + } + + // do it + ::SMESH_MeshEditor aMeshEditor( myMesh ); + aMeshEditor.MakeBoundaryMesh( elements, + ::SMESH_MeshEditor::Bnd_Dimension(dim), + smesh_group, + smesh_mesh, + toCopyElements, + toCopyExistingBondary); + storeResult( aMeshEditor ); + } + + // result of MakeBoundaryMesh() is a tuple (mesh, group) + if ( mesh_var->_is_nil() ) + pyDump << myMesh_i->_this() << ", "; + else + pyDump << mesh_var << ", "; + if ( group_var->_is_nil() ) + pyDump << "_NoneGroup = "; // assignment to None is forbiden + else + pyDump << group_var << " = "; + pyDump << this << ".MakeBoundaryMesh( " + << idSource << ", " + << dim << ", " + << groupName << ", " + << meshName<< ", " + << toCopyElements << ", " + << toCopyExistingBondary << ")"; + + group = group_var._retn(); + return mesh_var._retn(); +} diff --git a/src/SMESH_I/SMESH_MeshEditor_i.hxx b/src/SMESH_I/SMESH_MeshEditor_i.hxx index 330a52faf..3a96b87cd 100644 --- a/src/SMESH_I/SMESH_MeshEditor_i.hxx +++ b/src/SMESH_I/SMESH_MeshEditor_i.hxx @@ -671,14 +671,22 @@ public: const SMESH::ListOfGroups& theNodesNot, GEOM::GEOM_Object_ptr theShape ); - /*! - * \brief Generated skin mesh (containing 2D cells) from 3D mesh - * The created 2D mesh elements based on nodes of free faces of boundary volumes - * \return TRUE if operation has been completed successfully, FALSE otherwise - */ - CORBA::Boolean Make2DMeshFrom3D(); - - private: //!< private methods + /*! + * \brief Generated skin mesh (containing 2D cells) from 3D mesh + * The created 2D mesh elements based on nodes of free faces of boundary volumes + * \return TRUE if operation has been completed successfully, FALSE otherwise + */ + CORBA::Boolean Make2DMeshFrom3D(); + + SMESH::SMESH_Mesh_ptr MakeBoundaryMesh(SMESH::SMESH_IDSource_ptr elements, + SMESH::Bnd_Dimension dimension, + const char* groupName, + const char* meshName, + CORBA::Boolean toCopyElements, + CORBA::Boolean toCopyMissingBondary, + SMESH::SMESH_Group_out group); + +private: //!< private methods SMESHDS_Mesh * GetMeshDS() { return myMesh->GetMeshDS(); } diff --git a/src/SMESH_I/SMESH_Mesh_i.cxx b/src/SMESH_I/SMESH_Mesh_i.cxx index bb8c8b497..de07a09f7 100644 --- a/src/SMESH_I/SMESH_Mesh_i.cxx +++ b/src/SMESH_I/SMESH_Mesh_i.cxx @@ -2788,7 +2788,7 @@ SMESH::long_array* SMESH_Mesh_i::GetNodesId() long nbNodes = NbNodes(); aResult->length( nbNodes ); - SMDS_NodeIteratorPtr anIt = aSMESHDS_Mesh->nodesIterator(); + SMDS_NodeIteratorPtr anIt = aSMESHDS_Mesh->nodesIterator(/*idInceasingOrder=*/true); for ( int i = 0, n = nbNodes; i < n && anIt->more(); i++ ) aResult[i] = anIt->next()->GetID(); diff --git a/src/SMESH_I/SMESH_Pattern_i.cxx b/src/SMESH_I/SMESH_Pattern_i.cxx index 3d725b8fb..2a799a5b6 100644 --- a/src/SMESH_I/SMESH_Pattern_i.cxx +++ b/src/SMESH_I/SMESH_Pattern_i.cxx @@ -387,7 +387,14 @@ CORBA::Boolean SMESH_Pattern_i::MakeMesh (SMESH::SMESH_Mesh_ptr theMesh, << CreatePolygons << ", " << CreatePolyedrs << " )"; addErrorCode( "MakeMesh" ); - return myPattern.MakeMesh( aMesh, CreatePolygons, CreatePolyedrs ); + int nb = aMesh->NbNodes() + aMesh->NbEdges() + aMesh->NbFaces() + aMesh->NbVolumes(); + + bool res = myPattern.MakeMesh( aMesh, CreatePolygons, CreatePolyedrs ); + + if ( nb > 0 && nb != aMesh->NbNodes() + aMesh->NbEdges() + aMesh->NbFaces() + aMesh->NbVolumes()) + aMesh->SetIsModified(true); + + return res; } //======================================================================= diff --git a/src/SMESH_I/SMESH_subMesh_i.cxx b/src/SMESH_I/SMESH_subMesh_i.cxx index 8401ce775..faa7aa1ca 100644 --- a/src/SMESH_I/SMESH_subMesh_i.cxx +++ b/src/SMESH_I/SMESH_subMesh_i.cxx @@ -555,16 +555,26 @@ SMESH::long_array* SMESH_subMesh_i::GetMeshInfo() SMESH::array_of_ElementType* SMESH_subMesh_i::GetTypes() { SMESH::array_of_ElementType_var types = new SMESH::array_of_ElementType; - types->length( 1 ); + ::SMESH_subMesh* aSubMesh = _mesh_i->_mapSubMesh[_localId]; - switch ( ::SMESH_Gen::GetShapeDim( aSubMesh->GetSubShape() )) + TopoDS_Shape shape = aSubMesh->GetSubShape(); + while ( !shape.IsNull() && shape.ShapeType() == TopAbs_COMPOUND ) { - case 0: types[0] = SMESH::ELEM0D; break; - case 1: types[0] = SMESH::EDGE; break; - case 2: types[0] = SMESH::FACE; break; - case 3: types[0] = SMESH::VOLUME; break; - default: - types->length(0); + TopoDS_Iterator it( shape ); + shape = it.More() ? it.Value() : TopoDS_Shape(); + } + if ( !shape.IsNull() ) + { + types->length( 1 ); + switch ( ::SMESH_Gen::GetShapeDim( shape )) + { + case 0: types[0] = SMESH::ELEM0D; break; + case 1: types[0] = SMESH::EDGE; break; + case 2: types[0] = SMESH::FACE; break; + case 3: types[0] = SMESH::VOLUME; break; + default: + types->length(0); + } } return types._retn(); } diff --git a/src/SMESH_SWIG/smeshDC.py b/src/SMESH_SWIG/smeshDC.py index 9a88f94a0..1e01d2ac0 100644 --- a/src/SMESH_SWIG/smeshDC.py +++ b/src/SMESH_SWIG/smeshDC.py @@ -50,6 +50,7 @@ ## @defgroup l3_hypos_ghs3dh GHS3D Parameters hypothesis ## @defgroup l3_hypos_blsurf BLSURF Parameters hypothesis ## @defgroup l3_hypos_hexotic Hexotic Parameters hypothesis +## @defgroup l3_hypos_quad Quadrangle Parameters hypothesis ## @defgroup l3_hypos_additi Additional Hypotheses ## @} @@ -201,6 +202,9 @@ PrecisionConfusion = 1e-07 # Methods of splitting a hexahedron into tetrahedra Hex_5Tet, Hex_6Tet, Hex_24Tet = 1, 2, 3 +# import items of enum QuadType +for e in StdMeshers.QuadType._items: exec('%s = StdMeshers.%s'%(e,e)) + ## Converts an angle from degrees to radians def DegreesToRadians(AngleInDegrees): from math import pi @@ -772,6 +776,18 @@ class smeshDC(SMESH._objref_SMESH_Gen): else: print "Error: The treshold should be a string." return None + elif CritType == FT_CoplanarFaces: + # Checks the treshold + if isinstance(aTreshold, int): + aCriterion.ThresholdID = "%s"%aTreshold + elif isinstance(aTreshold, str): + ID = int(aTreshold) + if ID < 1: + raise ValueError, "Invalid ID of mesh face: '%s'"%aTreshold + aCriterion.ThresholdID = aTreshold + else: + raise ValueError,\ + "The treshold should be an ID of mesh face and not '%s'"%aTreshold elif CritType == FT_ElemGeomType: # Checks the treshold try: @@ -1643,9 +1659,9 @@ class Mesh: # @return SMESH_Group # @ingroup l2_grps_create def MakeGroupByFilter(self, groupName, theFilter): - anIds = theFilter.GetElementsId(self.mesh) - anElemType = theFilter.GetElementType() - group = self.MakeGroupByIds(groupName, anElemType, anIds) + group = self.CreateEmptyGroup(theFilter.GetElementType(), groupName) + theFilter.SetMesh( self.mesh ) + group.AddFrom( theFilter ) return group ## Passes mesh elements through the given filter and return IDs of fitting elements @@ -1653,7 +1669,8 @@ class Mesh: # @return a list of ids # @ingroup l1_controls def GetIdsFromFilter(self, theFilter): - return theFilter.GetElementsId(self.mesh) + theFilter.SetMesh( self.mesh ) + return theFilter.GetIDs() ## Verifies whether a 2D mesh element has free edges (edges connected to one face only)\n # Returns a list of special structures (borders). @@ -2558,6 +2575,8 @@ class Mesh: def SplitVolumesIntoTetra(self, elemIDs, method=Hex_5Tet ): if isinstance( elemIDs, Mesh ): elemIDs = elemIDs.GetMesh() + if ( isinstance( elemIDs, list )): + elemIDs = self.editor.MakeIDSource(elemIDs, SMESH.VOLUME) self.editor.SplitVolumesIntoTetra(elemIDs, method) ## Splits quadrangle faces near triangular facets of volumes @@ -2792,7 +2811,34 @@ class Mesh: # @ingroup l2_modif_edit def Make2DMeshFrom3D(self): return self.editor. Make2DMeshFrom3D() - + + ## Creates missing boundary elements + # @param elements - elements whose boundary is to be checked: + # mesh, group, sub-mesh or list of elements + # @param dimension - defines type of boundary elements to create: + # SMESH.BND_2DFROM3D, SMESH.BND_1DFROM3D, SMESH.BND_1DFROM2D + # @param groupName - a name of group to store created boundary elements in, + # "" means not to create the group + # @param meshName - a name of new mesh to store created boundary elements in, + # "" means not to create the new mesh + # @param toCopyElements - if true, the checked elements will be copied into the new mesh + # @param toCopyExistingBondary - if true, not only new but also pre-existing + # boundary elements will be copied into the new mesh + # @return tuple (mesh, group) where bondary elements were added to + # @ingroup l2_modif_edit + def MakeBoundaryMesh(self, elements, dimension=SMESH.BND_2DFROM3D, groupName="", meshName="", + toCopyElements=False, toCopyExistingBondary=False): + if isinstance( elements, Mesh ): + elements = elements.GetMesh() + if ( isinstance( elements, list )): + elemType = SMESH.ALL + if elements: elemType = self.GetElementType( elements[0], iselem=True) + elements = self.editor.MakeIDSource(elements, elemType) + mesh, group = self.editor.MakeBoundaryMesh(elements,dimension,groupName,meshName, + toCopyElements,toCopyExistingBondary) + if mesh: mesh = self.smeshpyD.Mesh(mesh) + return mesh, group + ## Renumber mesh nodes # @ingroup l2_modif_renumber def RenumberNodes(self): @@ -3584,11 +3630,11 @@ class Mesh: def FindCoincidentNodesOnPart (self, SubMeshOrGroup, Tolerance, exceptNodes=[]): if (isinstance( SubMeshOrGroup, Mesh )): SubMeshOrGroup = SubMeshOrGroup.GetMesh() - if not isinstance( ExceptSubMeshOrGroups, list): - ExceptSubMeshOrGroups = [ ExceptSubMeshOrGroups ] - if ExceptSubMeshOrGroups and isinstance( ExceptSubMeshOrGroups[0], int): - ExceptSubMeshOrGroups = [ self.editor.MakeIDSource( ExceptSubMeshOrGroups, SMESH.NODE)] - return self.editor.FindCoincidentNodesOnPartBut(SubMeshOrGroup, Tolerance,ExceptSubMeshOrGroups) + if not isinstance( exceptNodes, list): + exceptNodes = [ exceptNodes ] + if exceptNodes and isinstance( exceptNodes[0], int): + exceptNodes = [ self.editor.MakeIDSource( exceptNodes, SMESH.NODE)] + return self.editor.FindCoincidentNodesOnPartBut(SubMeshOrGroup, Tolerance,exceptNodes) ## Merges nodes # @param GroupsOfNodes the list of groups of nodes @@ -3944,7 +3990,8 @@ class Mesh_Algorithm: pass except: name = mesh.geompyD.SubShapeName(geom, piece) - mesh.geompyD.addToStudyInFather(piece, geom, name) + if not name: + name = "%s_%s"%(geom.GetShapeType(), id(geom%1000)) pass self.subm = mesh.mesh.GetSubMesh(geom, algo.GetName()) @@ -4649,48 +4696,96 @@ class Mesh_Triangle(Mesh_Algorithm): # @ingroup l3_algos_basic class Mesh_Quadrangle(Mesh_Algorithm): + params=0 + ## Private constructor. def __init__(self, mesh, geom=0): Mesh_Algorithm.__init__(self) self.Create(mesh, geom, "Quadrangle_2D") + return - ## Defines "QuadranglePreference" hypothesis, forcing construction - # of quadrangles if the number of nodes on the opposite edges is not the same - # while the total number of nodes on edges is even - # - # @ingroup l3_hypos_additi - def QuadranglePreference(self): - hyp = self.Hypothesis("QuadranglePreference", UseExisting=1, - CompareMethod=self.CompareEqualHyp) - return hyp + ## Defines "QuadrangleParameters" hypothesis + # @param quadType defines the algorithm of transition between differently descretized + # sides of a geometrical face: + # - QUAD_STANDARD - both triangles and quadrangles are possible in the transition + # area along the finer meshed sides. + # - QUAD_TRIANGLE_PREF - only triangles are built in the transition area along the + # finer meshed sides. + # - QUAD_QUADRANGLE_PREF - only quadrangles are built in the transition area along + # the finer meshed sides, iff the total quantity of segments on + # all four sides of the face is even (divisible by 2). + # - QUAD_QUADRANGLE_PREF_REVERSED - same as QUAD_QUADRANGLE_PREF but the transition + # area is located along the coarser meshed sides. + # - QUAD_REDUCED - only quadrangles are built and the transition between the sides + # is made gradually, layer by layer. This type has a limitation on + # the number of segments: one pair of opposite sides must have the + # same number of segments, the other pair must have an even difference + # between the numbers of segments on the sides. + # @param triangleVertex: vertex of a trilateral geometrical face, around which triangles + # will be created while other elements will be quadrangles. + # Vertex can be either a GEOM_Object or a vertex ID within the + # shape to mesh + # @param UseExisting: if ==true - searches for the existing hypothesis created with + # the same parameters, else (default) - creates a new one + # @ingroup l3_hypos_quad + def QuadrangleParameters(self, quadType=StdMeshers.QUAD_STANDARD, triangleVertex=0, UseExisting=0): + vertexID = triangleVertex + if isinstance( triangleVertex, geompyDC.GEOM._objref_GEOM_Object ): + vertexID = self.mesh.geompyD.GetSubShapeID( self.mesh.geom, triangleVertex ) + if not self.params: + compFun = lambda hyp,args: \ + hyp.GetQuadType() == args[0] and \ + ( hyp.GetTriaVertex()==args[1] or ( hyp.GetTriaVertex()<1 and args[1]<1)) + self.params = self.Hypothesis("QuadrangleParams", [quadType,vertexID], + UseExisting = UseExisting, CompareMethod=compFun) + pass + if self.params.GetQuadType() != quadType: + self.params.SetQuadType(quadType) + if vertexID > 0: + self.params.SetTriaVertex( vertexID ) + return self.params - ## Defines "TrianglePreference" hypothesis, forcing construction - # of triangles in the refinement area if the number of nodes - # on the opposite edges is not the same - # - # @ingroup l3_hypos_additi - def TrianglePreference(self): - hyp = self.Hypothesis("TrianglePreference", UseExisting=1, - CompareMethod=self.CompareEqualHyp) - return hyp + ## Defines "QuadrangleParams" hypothesis with a type of quadrangulation that only + # quadrangles are built in the transition area along the finer meshed sides, + # iff the total quantity of segments on all four sides of the face is even. + # @param reversed if True, transition area is located along the coarser meshed sides. + # @param UseExisting: if ==true - searches for the existing hypothesis created with + # the same parameters, else (default) - creates a new one + # @ingroup l3_hypos_quad + def QuadranglePreference(self, reversed=False, UseExisting=0): + if reversed: + return self.QuadrangleParameters(QUAD_QUADRANGLE_PREF_REVERSED,UseExisting=UseExisting) + return self.QuadrangleParameters(QUAD_QUADRANGLE_PREF,UseExisting=UseExisting) + + ## Defines "QuadrangleParams" hypothesis with a type of quadrangulation that only + # triangles are built in the transition area along the finer meshed sides. + # @param UseExisting: if ==true - searches for the existing hypothesis created with + # the same parameters, else (default) - creates a new one + # @ingroup l3_hypos_quad + def TrianglePreference(self, UseExisting=0): + return self.QuadrangleParameters(QUAD_TRIANGLE_PREF,UseExisting=UseExisting) + + ## Defines "QuadrangleParams" hypothesis with a type of quadrangulation that only + # quadrangles are built and the transition between the sides is made gradually, + # layer by layer. This type has a limitation on the number of segments: one pair + # of opposite sides must have the same number of segments, the other pair must + # have an even difference between the numbers of segments on the sides. + # @param UseExisting: if ==true - searches for the existing hypothesis created with + # the same parameters, else (default) - creates a new one + # @ingroup l3_hypos_quad + def Reduced(self, UseExisting=0): + return self.QuadrangleParameters(QUAD_REDUCED,UseExisting=UseExisting) - ## Defines "QuadrangleParams" hypothesis + ## Defines "QuadrangleParams" hypothesis with QUAD_STANDARD type of quadrangulation # @param vertex: vertex of a trilateral geometrical face, around which triangles # will be created while other elements will be quadrangles. # Vertex can be either a GEOM_Object or a vertex ID within the # shape to mesh # @param UseExisting: if ==true - searches for the existing hypothesis created with # the same parameters, else (default) - creates a new one - # - # @ingroup l3_hypos_additi + # @ingroup l3_hypos_quad def TriangleVertex(self, vertex, UseExisting=0): - vertexID = vertex - if isinstance( vertexID, geompyDC.GEOM._objref_GEOM_Object ): - vertexID = self.mesh.geompyD.GetSubShapeID( self.mesh.geom, vertex ) - hyp = self.Hypothesis("QuadrangleParams", [vertexID], UseExisting = UseExisting, - CompareMethod=lambda hyp,args: hyp.GetTriaVertex()==args[0]) - hyp.SetTriaVertex( vertexID ) - return hyp + return self.QuadrangleParameters(QUAD_STANDARD,vertex,UseExisting) # Public class: Mesh_Tetrahedron diff --git a/src/StdMeshers/StdMeshers_FaceSide.cxx b/src/StdMeshers/StdMeshers_FaceSide.cxx index 036da0ba9..f882f5c92 100644 --- a/src/StdMeshers/StdMeshers_FaceSide.cxx +++ b/src/StdMeshers/StdMeshers_FaceSide.cxx @@ -452,9 +452,12 @@ void StdMeshers_FaceSide::Reverse() reverse( myEdgeLength ); reverse( myIsUniform ); } - myNormPar[nbEdges-1]=1.; - myPoints.clear(); - myFalsePoints.clear(); + if ( nbEdges > 0 ) + { + myNormPar[nbEdges-1]=1.; + myPoints.clear(); + myFalsePoints.clear(); + } } //================================================================================ diff --git a/src/StdMeshers/StdMeshers_QuadToTriaAdaptor.cxx b/src/StdMeshers/StdMeshers_QuadToTriaAdaptor.cxx index 3ae9552d9..39dfd2e13 100644 --- a/src/StdMeshers/StdMeshers_QuadToTriaAdaptor.cxx +++ b/src/StdMeshers/StdMeshers_QuadToTriaAdaptor.cxx @@ -60,7 +60,7 @@ namespace */ //================================================================================ - class SMDS_EXPORT Q2TAdaptor_Triangle : public SMDS_MeshFace + class STDMESHERS_EXPORT Q2TAdaptor_Triangle : public SMDS_MeshFace { const SMDS_MeshNode* _nodes[3]; public: @@ -228,7 +228,7 @@ namespace // Check angle between normals double angle = nI.Angle( nJ ); - bool tooClose = ( angle < 10 * PI180 ); + bool tooClose = ( angle < 15 * PI180 ); // Check if pyramids collide bool isOutI, isOutJ; @@ -315,8 +315,14 @@ namespace } } if ( !mergedPyrams.empty() ) - for (TIDSortedElemSet::iterator prm = mergedPyrams.begin(); prm != mergedPyrams.end(); ++prm) + { + TIDSortedElemSet::iterator prm; +// for (prm = mergedPyrams.begin(); prm != mergedPyrams.end(); ++prm) +// MergeAdjacent( *prm, mesh, nodesToMove ); + + for (prm = adjacentPyrams.begin(); prm != adjacentPyrams.end(); ++prm) MergeAdjacent( *prm, mesh, nodesToMove ); + } } } diff --git a/src/StdMeshers/StdMeshers_QuadrangleParams.cxx b/src/StdMeshers/StdMeshers_QuadrangleParams.cxx index 07cd7f649..c0e106364 100644 --- a/src/StdMeshers/StdMeshers_QuadrangleParams.cxx +++ b/src/StdMeshers/StdMeshers_QuadrangleParams.cxx @@ -16,12 +16,11 @@ // // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // - // SMESH SMESH : implementaion of SMESH idl descriptions // File : StdMeshers_QuadrangleParams.cxx // Author : Sergey KUUL, OCC // Module : SMESH -// + #include "StdMeshers_QuadrangleParams.hxx" #include "SMESH_Algo.hxx" @@ -41,38 +40,36 @@ using namespace std; //============================================================================= /*! - * + * */ //============================================================================= - StdMeshers_QuadrangleParams::StdMeshers_QuadrangleParams(int hypId, int studyId, SMESH_Gen * gen) - :SMESH_Hypothesis(hypId, studyId, gen) + : SMESH_Hypothesis(hypId, studyId, gen) { _name = "QuadrangleParams"; _param_algo_dim = 2; _triaVertexID = -1; + _quadType = QUAD_STANDARD; } //============================================================================= /*! - * + * */ //============================================================================= - StdMeshers_QuadrangleParams::~StdMeshers_QuadrangleParams() { } //============================================================================= /*! - * + * */ //============================================================================= - -void StdMeshers_QuadrangleParams::SetTriaVertex(int id) +void StdMeshers_QuadrangleParams::SetTriaVertex (int id) { - if ( id != _triaVertexID ) { + if (id != _triaVertexID) { _triaVertexID = id; NotifySubMeshesHypothesisModification(); } @@ -80,22 +77,36 @@ void StdMeshers_QuadrangleParams::SetTriaVertex(int id) //============================================================================= /*! - * + * */ //============================================================================= +void StdMeshers_QuadrangleParams::SetQuadType (StdMeshers_QuadType type) +{ + if (type != _quadType) { + _quadType = type; + NotifySubMeshesHypothesisModification(); + } +} +//============================================================================= +/*! + * + */ +//============================================================================= ostream & StdMeshers_QuadrangleParams::SaveTo(ostream & save) { - save << _triaVertexID << " " << _objEntry; + if (_objEntry.size() == 0) + save << _triaVertexID << " UNDEFINED " << int(_quadType); + else + save << _triaVertexID << " " << _objEntry << " " << int(_quadType); return save; } //============================================================================= /*! - * + * */ //============================================================================= - istream & StdMeshers_QuadrangleParams::LoadFrom(istream & load) { bool isOK = true; @@ -104,16 +115,22 @@ istream & StdMeshers_QuadrangleParams::LoadFrom(istream & load) load.clear(ios::badbit | load.rdstate()); isOK = (load >> _objEntry); + if (!isOK) + load.clear(ios::badbit | load.rdstate()); + + int type; + isOK = (load >> type); + if (isOK) + _quadType = StdMeshers_QuadType(type); return load; } //============================================================================= /*! - * + * */ //============================================================================= - ostream & operator <<(ostream & save, StdMeshers_QuadrangleParams & hyp) { return hyp.SaveTo( save ); @@ -121,10 +138,9 @@ ostream & operator <<(ostream & save, StdMeshers_QuadrangleParams & hyp) //============================================================================= /*! - * + * */ //============================================================================= - istream & operator >>(istream & load, StdMeshers_QuadrangleParams & hyp) { return hyp.LoadFrom( load ); @@ -138,7 +154,6 @@ istream & operator >>(istream & load, StdMeshers_QuadrangleParams & hyp) * \retval bool - true if parameter values have been successfully defined */ //================================================================================ - bool StdMeshers_QuadrangleParams::SetParametersByMesh(const SMESH_Mesh* theMesh, const TopoDS_Shape& theShape) { @@ -154,10 +169,8 @@ bool StdMeshers_QuadrangleParams::SetParametersByMesh(const SMESH_Mesh* theMesh, * \retval bool - true if parameter values have been successfully defined */ //================================================================================ - bool StdMeshers_QuadrangleParams::SetParametersByDefaults(const TDefaults& dflts, const SMESH_Mesh* /*mesh*/) { return true; } - diff --git a/src/StdMeshers/StdMeshers_QuadrangleParams.hxx b/src/StdMeshers/StdMeshers_QuadrangleParams.hxx index da37f0755..d880c5008 100644 --- a/src/StdMeshers/StdMeshers_QuadrangleParams.hxx +++ b/src/StdMeshers/StdMeshers_QuadrangleParams.hxx @@ -16,22 +16,29 @@ // // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // - // SMESH SMESH : implementaion of SMESH idl descriptions // File : StdMeshers_QuadrangleParams.hxx // Author : Sergey KUUL, OCC // Module : SMESH -// + #ifndef _SMESH_QUADRANGLEPARAMS_HXX_ #define _SMESH_QUADRANGLEPARAMS_HXX_ - - #include "SMESH_StdMeshers.hxx" #include "SMESH_Hypothesis.hxx" #include "Utils_SALOME_Exception.hxx" +enum StdMeshers_QuadType + { + QUAD_STANDARD, + QUAD_TRIANGLE_PREF, + QUAD_QUADRANGLE_PREF, + QUAD_QUADRANGLE_PREF_REVERSED, + QUAD_REDUCED, + QUAD_NB_TYPES + }; + class STDMESHERS_EXPORT StdMeshers_QuadrangleParams: public SMESH_Hypothesis { @@ -39,13 +46,14 @@ public: StdMeshers_QuadrangleParams(int hypId, int studyId, SMESH_Gen* gen); virtual ~StdMeshers_QuadrangleParams(); - void SetTriaVertex(int id); - - void SetObjectEntry( const char* entry ) { _objEntry = entry; } + void SetTriaVertex (int id); + int GetTriaVertex() const { return _triaVertexID; } + void SetObjectEntry (const char* entry) { _objEntry = entry; } const char* GetObjectEntry() { return _objEntry.c_str(); } - int GetTriaVertex() const { return _triaVertexID; } + void SetQuadType (StdMeshers_QuadType type); + StdMeshers_QuadType GetQuadType() const { return _quadType; } virtual std::ostream & SaveTo(std::ostream & save); virtual std::istream & LoadFrom(std::istream & load); @@ -71,8 +79,9 @@ public: const SMESH_Mesh* theMesh=0); protected: - int _triaVertexID; - std::string _objEntry; + int _triaVertexID; + std::string _objEntry; + StdMeshers_QuadType _quadType; }; #endif diff --git a/src/StdMeshers/StdMeshers_Quadrangle_2D.cxx b/src/StdMeshers/StdMeshers_Quadrangle_2D.cxx index c78c755d9..1075db412 100644 --- a/src/StdMeshers/StdMeshers_Quadrangle_2D.cxx +++ b/src/StdMeshers/StdMeshers_Quadrangle_2D.cxx @@ -18,14 +18,11 @@ // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -// -// SMESH SMESH : implementaion of SMESH idl descriptions // File : StdMeshers_Quadrangle_2D.cxx -// Moved here from SMESH_Quadrangle_2D.cxx // Author : Paul RASCLE, EDF // Module : SMESH -// + #include "StdMeshers_Quadrangle_2D.hxx" #include "StdMeshers_FaceSide.hxx" @@ -49,6 +46,7 @@ #include #include #include +#include #include #include #include @@ -116,69 +114,75 @@ bool StdMeshers_Quadrangle_2D::CheckHypothesis bool isOk = true; aStatus = SMESH_Hypothesis::HYP_OK; - const list &hyps = + const list & hyps = GetUsedHypothesis(aMesh, aShape, false); - const SMESHDS_Hypothesis *theHyp = 0; - - if( hyps.size() == 1 ) { - myTriaVertexID = -1; - theHyp = hyps.front(); - if(strcmp("QuadrangleParams", theHyp->GetName()) == 0) { - const StdMeshers_QuadrangleParams* theHyp1 = - (const StdMeshers_QuadrangleParams*)theHyp; - myTriaVertexID = theHyp1->GetTriaVertex(); - myQuadranglePreference= false; - myTrianglePreference= false; - } - if(strcmp("QuadranglePreference", theHyp->GetName()) == 0) { - myQuadranglePreference= true; - myTrianglePreference= false; - myTriaVertexID = -1; - } - else if(strcmp("TrianglePreference", theHyp->GetName()) == 0){ - myQuadranglePreference= false; - myTrianglePreference= true; - myTriaVertexID = -1; + const SMESHDS_Hypothesis * aHyp = 0; + + myTriaVertexID = -1; + myQuadType = QUAD_STANDARD; + myQuadranglePreference = false; + myTrianglePreference = false; + + bool isFirstParams = true; + + // First assigned hypothesis (if any) is processed now + if (hyps.size() > 0) { + aHyp = hyps.front(); + if (strcmp("QuadrangleParams", aHyp->GetName()) == 0) { + const StdMeshers_QuadrangleParams* aHyp1 = + (const StdMeshers_QuadrangleParams*)aHyp; + myTriaVertexID = aHyp1->GetTriaVertex(); + myQuadType = aHyp1->GetQuadType(); + if (myQuadType == QUAD_QUADRANGLE_PREF || + myQuadType == QUAD_QUADRANGLE_PREF_REVERSED) + myQuadranglePreference = true; + else if (myQuadType == QUAD_TRIANGLE_PREF) + myTrianglePreference = true; + } + else if (strcmp("QuadranglePreference", aHyp->GetName()) == 0) { + isFirstParams = false; + myQuadranglePreference = true; + } + else if (strcmp("TrianglePreference", aHyp->GetName()) == 0){ + isFirstParams = false; + myTrianglePreference = true; + } + else { + isFirstParams = false; } } - else if( hyps.size() > 1 ) { - theHyp = hyps.front(); - if(strcmp("QuadrangleParams", theHyp->GetName()) == 0) { - const StdMeshers_QuadrangleParams* theHyp1 = - (const StdMeshers_QuadrangleParams*)theHyp; - myTriaVertexID = theHyp1->GetTriaVertex(); - theHyp = hyps.back(); - if(strcmp("QuadranglePreference", theHyp->GetName()) == 0) { - myQuadranglePreference= true; - myTrianglePreference= false; + // Second(last) assigned hypothesis (if any) is processed now + if (hyps.size() > 1) { + aHyp = hyps.back(); + if (isFirstParams) { + if (strcmp("QuadranglePreference", aHyp->GetName()) == 0) { + myQuadranglePreference = true; + myTrianglePreference = false; + myQuadType = QUAD_STANDARD; } - else if(strcmp("TrianglePreference", theHyp->GetName()) == 0){ - myQuadranglePreference= false; - myTrianglePreference= true; + else if (strcmp("TrianglePreference", aHyp->GetName()) == 0){ + myQuadranglePreference = false; + myTrianglePreference = true; + myQuadType = QUAD_STANDARD; } } else { - if(strcmp("QuadranglePreference", theHyp->GetName()) == 0) { - myQuadranglePreference= true; - myTrianglePreference= false; + const StdMeshers_QuadrangleParams* aHyp2 = + (const StdMeshers_QuadrangleParams*)aHyp; + myTriaVertexID = aHyp2->GetTriaVertex(); + + if (!myQuadranglePreference && !myTrianglePreference) { // priority of hypos + myQuadType = aHyp2->GetQuadType(); + if (myQuadType == QUAD_QUADRANGLE_PREF || + myQuadType == QUAD_QUADRANGLE_PREF_REVERSED) + myQuadranglePreference = true; + else if (myQuadType == QUAD_TRIANGLE_PREF) + myTrianglePreference = true; } - else if(strcmp("TrianglePreference", theHyp->GetName()) == 0){ - myQuadranglePreference= false; - myTrianglePreference= true; - } - const StdMeshers_QuadrangleParams* theHyp2 = - (const StdMeshers_QuadrangleParams*)hyps.back(); - myTriaVertexID = theHyp2->GetTriaVertex(); } } - else { - myQuadranglePreference = false; - myTrianglePreference = false; - myTriaVertexID = -1; - } - return isOk; } @@ -197,17 +201,17 @@ bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh& aMesh, SMESHDS_Mesh * meshDS = aMesh.GetMeshDS(); aMesh.GetSubMesh(aShape); - SMESH_MesherHelper helper(aMesh); + SMESH_MesherHelper helper (aMesh); myTool = &helper; _quadraticMesh = myTool->IsQuadraticSubMesh(aShape); - FaceQuadStruct *quad = CheckNbEdges( aMesh, aShape ); - std::auto_ptr quadDeleter( quad ); // to delete quad at exit from Compute() + FaceQuadStruct *quad = CheckNbEdges(aMesh, aShape); + std::auto_ptr quadDeleter (quad); // to delete quad at exit from Compute() if (!quad) return false; - if(myQuadranglePreference) { + if (myQuadranglePreference) { int n1 = quad->side[0]->NbPoints(); int n2 = quad->side[1]->NbPoints(); int n3 = quad->side[2]->NbPoints(); @@ -215,12 +219,27 @@ bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh& aMesh, int nfull = n1+n2+n3+n4; int ntmp = nfull/2; ntmp = ntmp*2; - if( nfull==ntmp && ( (n1!=n3) || (n2!=n4) ) ) { + if (nfull == ntmp && ((n1 != n3) || (n2 != n4))) { // special path for using only quandrangle faces bool ok = ComputeQuadPref(aMesh, aShape, quad); return ok; } } + else if (myQuadType == QUAD_REDUCED) { + int n1 = quad->side[0]->NbPoints(); + int n2 = quad->side[1]->NbPoints(); + int n3 = quad->side[2]->NbPoints(); + int n4 = quad->side[3]->NbPoints(); + int n13 = n1 - n3; + int n24 = n2 - n4; + int n13tmp = n13/2; n13tmp = n13tmp*2; + int n24tmp = n24/2; n24tmp = n24tmp*2; + if ((n1 == n3 && n2 != n4 && n24tmp == n24) || + (n2 == n4 && n1 != n3 && n13tmp == n13)) { + bool ok = ComputeReduced(aMesh, aShape, quad); + return ok; + } + } // set normalized grid on unit square in parametric domain @@ -242,7 +261,7 @@ bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh& aMesh, Handle(Geom_Surface) S = BRep_Tool::Surface(F); // internal mesh nodes - int i, j, geomFaceID = meshDS->ShapeToIndex( F ); + int i, j, geomFaceID = meshDS->ShapeToIndex(F); for (i = 1; i < nbhoriz - 1; i++) { for (j = 1; j < nbvertic - 1; j++) { int ij = j * nbhoriz + i; @@ -287,19 +306,19 @@ bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh& aMesh, c = quad->uv_grid[(j + 1) * nbhoriz + i + 1].node; d = quad->uv_grid[(j + 1) * nbhoriz + i].node; SMDS_MeshFace* face = myTool->AddFace(a, b, c, d); - if(face) { + if (face) { meshDS->SetMeshElementOnShape(face, geomFaceID); } } } - const vector& uv_e0 = quad->side[0]->GetUVPtStruct(true,0 ); + const vector& uv_e0 = quad->side[0]->GetUVPtStruct(true,0); const vector& uv_e1 = quad->side[1]->GetUVPtStruct(false,1); - const vector& uv_e2 = quad->side[2]->GetUVPtStruct(true,1 ); + const vector& uv_e2 = quad->side[2]->GetUVPtStruct(true,1); const vector& uv_e3 = quad->side[3]->GetUVPtStruct(false,0); - if ( uv_e0.empty() || uv_e1.empty() || uv_e2.empty() || uv_e3.empty() ) - return error( COMPERR_BAD_INPUT_MESH ); + if (uv_e0.empty() || uv_e1.empty() || uv_e2.empty() || uv_e3.empty()) + return error(COMPERR_BAD_INPUT_MESH); double eps = Precision::Confusion(); @@ -364,7 +383,7 @@ bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh& aMesh, if (near == g) { // make triangle SMDS_MeshFace* face = myTool->AddFace(a, b, c); - if(face) meshDS->SetMeshElementOnShape(face, geomFaceID); + if (face) meshDS->SetMeshElementOnShape(face, geomFaceID); } else { // make quadrangle if (near - 1 < ilow) @@ -373,9 +392,9 @@ bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh& aMesh, d = quad->uv_grid[nbhoriz + near - 1].node; //SMDS_MeshFace* face = meshDS->AddFace(a, b, c, d); - if(!myTrianglePreference){ + if (!myTrianglePreference){ SMDS_MeshFace* face = myTool->AddFace(a, b, c, d); - if(face) meshDS->SetMeshElementOnShape(face, geomFaceID); + if (face) meshDS->SetMeshElementOnShape(face, geomFaceID); } else { SplitQuad(meshDS, geomFaceID, a, b, c, d); @@ -390,7 +409,7 @@ bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh& aMesh, else d = quad->uv_grid[nbhoriz + k - 1].node; SMDS_MeshFace* face = myTool->AddFace(a, c, d); - if(face) meshDS->SetMeshElementOnShape(face, geomFaceID); + if (face) meshDS->SetMeshElementOnShape(face, geomFaceID); } } g = near; @@ -452,7 +471,7 @@ bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh& aMesh, if (near == g) { // make triangle SMDS_MeshFace* face = myTool->AddFace(a, b, c); - if(face) meshDS->SetMeshElementOnShape(face, geomFaceID); + if (face) meshDS->SetMeshElementOnShape(face, geomFaceID); } else { // make quadrangle if (near + 1 > iup) @@ -460,9 +479,9 @@ bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh& aMesh, else d = quad->uv_grid[nbhoriz*(nbvertic - 2) + near + 1].node; //SMDS_MeshFace* face = meshDS->AddFace(a, b, c, d); - if(!myTrianglePreference){ + if (!myTrianglePreference){ SMDS_MeshFace* face = myTool->AddFace(a, b, c, d); - if(face) meshDS->SetMeshElementOnShape(face, geomFaceID); + if (face) meshDS->SetMeshElementOnShape(face, geomFaceID); } else { SplitQuad(meshDS, geomFaceID, a, b, c, d); @@ -476,7 +495,7 @@ bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh& aMesh, else d = quad->uv_grid[nbhoriz*(nbvertic - 2) + k + 1].node; SMDS_MeshFace* face = myTool->AddFace(a, c, d); - if(face) meshDS->SetMeshElementOnShape(face, geomFaceID); + if (face) meshDS->SetMeshElementOnShape(face, geomFaceID); } } g = near; @@ -524,7 +543,7 @@ bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh& aMesh, if (near == g) { // make triangle SMDS_MeshFace* face = myTool->AddFace(a, b, c); - if(face) meshDS->SetMeshElementOnShape(face, geomFaceID); + if (face) meshDS->SetMeshElementOnShape(face, geomFaceID); } else { // make quadrangle if (near - 1 < jlow) @@ -533,9 +552,9 @@ bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh& aMesh, d = quad->uv_grid[nbhoriz*near - 2].node; //SMDS_MeshFace* face = meshDS->AddFace(a, b, c, d); - if(!myTrianglePreference){ + if (!myTrianglePreference){ SMDS_MeshFace* face = myTool->AddFace(a, b, c, d); - if(face) meshDS->SetMeshElementOnShape(face, geomFaceID); + if (face) meshDS->SetMeshElementOnShape(face, geomFaceID); } else { SplitQuad(meshDS, geomFaceID, a, b, c, d); @@ -549,7 +568,7 @@ bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh& aMesh, else d = quad->uv_grid[nbhoriz*k - 2].node; SMDS_MeshFace* face = myTool->AddFace(a, c, d); - if(face) meshDS->SetMeshElementOnShape(face, geomFaceID); + if (face) meshDS->SetMeshElementOnShape(face, geomFaceID); } } g = near; @@ -594,7 +613,7 @@ bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh& aMesh, if (near == g) { // make triangle SMDS_MeshFace* face = myTool->AddFace(a, b, c); - if(face) meshDS->SetMeshElementOnShape(face, geomFaceID); + if (face) meshDS->SetMeshElementOnShape(face, geomFaceID); } else { // make quadrangle if (near + 1 > jup) @@ -602,9 +621,9 @@ bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh& aMesh, else d = quad->uv_grid[nbhoriz*(near + 1) + 1].node; //SMDS_MeshFace* face = meshDS->AddFace(a, b, c, d); - if(!myTrianglePreference){ + if (!myTrianglePreference){ SMDS_MeshFace* face = myTool->AddFace(a, b, c, d); - if(face) meshDS->SetMeshElementOnShape(face, geomFaceID); + if (face) meshDS->SetMeshElementOnShape(face, geomFaceID); } else { SplitQuad(meshDS, geomFaceID, a, b, c, d); @@ -618,7 +637,7 @@ bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh& aMesh, else d = quad->uv_grid[nbhoriz*(k + 1) + 1].node; SMDS_MeshFace* face = myTool->AddFace(a, c, d); - if(face) meshDS->SetMeshElementOnShape(face, geomFaceID); + if (face) meshDS->SetMeshElementOnShape(face, geomFaceID); } } g = near; @@ -647,17 +666,17 @@ bool StdMeshers_Quadrangle_2D::Evaluate(SMESH_Mesh& aMesh, std::vector aNbNodes(4); bool IsQuadratic = false; - if( !CheckNbEdgesForEvaluate( aMesh, aShape, aResMap, aNbNodes, IsQuadratic ) ) { + if (!CheckNbEdgesForEvaluate(aMesh, aShape, aResMap, aNbNodes, IsQuadratic)) { std::vector aResVec(SMDSEntity_Last); - for(int i=SMDSEntity_Node; iGetComputeError(); - smError.reset( new SMESH_ComputeError(COMPERR_ALGO_FAILED,"Submesh can not be evaluated",this)); + smError.reset(new SMESH_ComputeError(COMPERR_ALGO_FAILED,"Submesh can not be evaluated",this)); return false; } - if(myQuadranglePreference) { + if (myQuadranglePreference) { int n1 = aNbNodes[0]; int n2 = aNbNodes[1]; int n3 = aNbNodes[2]; @@ -665,7 +684,7 @@ bool StdMeshers_Quadrangle_2D::Evaluate(SMESH_Mesh& aMesh, int nfull = n1+n2+n3+n4; int ntmp = nfull/2; ntmp = ntmp*2; - if( nfull==ntmp && ( (n1!=n3) || (n2!=n4) ) ) { + if (nfull==ntmp && ((n1!=n3) || (n2!=n4))) { // special path for using only quandrangle faces return EvaluateQuadPref(aMesh, aShape, aNbNodes, aResMap, IsQuadratic); //return true; @@ -685,27 +704,27 @@ bool StdMeshers_Quadrangle_2D::Evaluate(SMESH_Mesh& aMesh, int dv = Max(nbright, nbleft) - nbvertic; //int kdh = 0; - //if(dh>0) kdh = 1; + //if (dh>0) kdh = 1; //int kdv = 0; - //if(dv>0) kdv = 1; + //if (dv>0) kdv = 1; int nbNodes = (nbhoriz-2)*(nbvertic-2); //int nbFaces3 = dh + dv + kdh*(nbvertic-1)*2 + kdv*(nbhoriz-1)*2; int nbFaces3 = dh + dv; - //if( kdh==1 && kdv==1 ) nbFaces3 -= 2; - //if( dh>0 && dv>0 ) nbFaces3 -= 2; + //if (kdh==1 && kdv==1) nbFaces3 -= 2; + //if (dh>0 && dv>0) nbFaces3 -= 2; //int nbFaces4 = (nbhoriz-1-kdh)*(nbvertic-1-kdv); int nbFaces4 = (nbhoriz-1)*(nbvertic-1); std::vector aVec(SMDSEntity_Last); - for(int i=SMDSEntity_Node; i::iterator edgeIt = edges.begin(); - if ( nbEdgesInWire.front() == 3 ) // exactly 3 edges + if (nbEdgesInWire.front() == 3) // exactly 3 edges { SMESH_Comment comment; SMESHDS_Mesh* meshDS = aMesh.GetMeshDS(); - if ( myTriaVertexID == -1) + if (myTriaVertexID == -1) { comment << "No Base vertex parameter provided for a trilateral geometrical face"; } else { TopoDS_Vertex V = TopoDS::Vertex(meshDS->IndexToShape(myTriaVertexID)); - if ( !V.IsNull() ) { + if (!V.IsNull()) { TopoDS_Edge E1,E2,E3; - for(; edgeIt != edges.end(); ++edgeIt) { + for (; edgeIt != edges.end(); ++edgeIt) { TopoDS_Edge E = *edgeIt; TopoDS_Vertex VF, VL; TopExp::Vertices(E, VF, VL, true); - if( VF.IsSame(V) ) + if (VF.IsSame(V)) E1 = E; - else if( VL.IsSame(V) ) + else if (VL.IsSame(V)) E3 = E; else E2 = E; } - if ( !E1.IsNull() && !E2.IsNull() && !E3.IsNull() ) + if (!E1.IsNull() && !E2.IsNull() && !E3.IsNull()) { - quad->side.push_back( new StdMeshers_FaceSide(F, E1, &aMesh, true, ignoreMediumNodes)); - quad->side.push_back( new StdMeshers_FaceSide(F, E2, &aMesh, true, ignoreMediumNodes)); - quad->side.push_back( new StdMeshers_FaceSide(F, E3, &aMesh, false,ignoreMediumNodes)); + quad->side.push_back(new StdMeshers_FaceSide(F, E1, &aMesh, true, ignoreMediumNodes)); + quad->side.push_back(new StdMeshers_FaceSide(F, E2, &aMesh, true, ignoreMediumNodes)); + quad->side.push_back(new StdMeshers_FaceSide(F, E3, &aMesh, false,ignoreMediumNodes)); const vector& UVPSleft = quad->side[0]->GetUVPtStruct(true,0); /* vector& UVPStop = */quad->side[1]->GetUVPtStruct(false,1); /* vector& UVPSright = */quad->side[2]->GetUVPtStruct(true,1); const SMDS_MeshNode* aNode = UVPSleft[0].node; - gp_Pnt2d aPnt2d( UVPSleft[0].u, UVPSleft[0].v ); - quad->side.push_back( new StdMeshers_FaceSide(aNode, aPnt2d, quad->side[1])); + gp_Pnt2d aPnt2d(UVPSleft[0].u, UVPSleft[0].v); + quad->side.push_back(new StdMeshers_FaceSide(aNode, aPnt2d, quad->side[1])); return quad; } } comment << "Invalid Base vertex parameter: " << myTriaVertexID << " is not among ["; TopTools_MapOfShape vMap; - for ( TopExp_Explorer v( aShape, TopAbs_VERTEX ); v.More(); v.Next()) - if ( vMap.Add( v.Current() )) - comment << meshDS->ShapeToIndex( v.Current() ) << ( vMap.Extent()==3 ? "]" : ", "); + for (TopExp_Explorer v(aShape, TopAbs_VERTEX); v.More(); v.Next()) + if (vMap.Add(v.Current())) + comment << meshDS->ShapeToIndex(v.Current()) << (vMap.Extent()==3 ? "]" : ", "); } - error( comment ); + error(comment); delete quad; return quad = 0; } - else if ( nbEdgesInWire.front() == 4 ) { // exactly 4 edges - for ( ; edgeIt != edges.end(); ++edgeIt, nbSides++ ) - quad->side.push_back( new StdMeshers_FaceSide(F, *edgeIt, &aMesh, + else if (nbEdgesInWire.front() == 4) { // exactly 4 edges + for (; edgeIt != edges.end(); ++edgeIt, nbSides++) + quad->side.push_back(new StdMeshers_FaceSide(F, *edgeIt, &aMesh, nbSides 4 ) { // more than 4 edges - try to unite some + else if (nbEdgesInWire.front() > 4) { // more than 4 edges - try to unite some list< TopoDS_Edge > sideEdges; - while ( !edges.empty()) { + while (!edges.empty()) { sideEdges.clear(); - sideEdges.splice( sideEdges.end(), edges, edges.begin()); // edges.front() -> sideEdges.end() + sideEdges.splice(sideEdges.end(), edges, edges.begin()); // edges.front() -> sideEdges.end() bool sameSide = true; - while ( !edges.empty() && sameSide ) { - sameSide = SMESH_Algo::IsContinuous( sideEdges.back(), edges.front() ); - if ( sameSide ) - sideEdges.splice( sideEdges.end(), edges, edges.begin()); + while (!edges.empty() && sameSide) { + sameSide = SMESH_Algo::IsContinuous(sideEdges.back(), edges.front()); + if (sameSide) + sideEdges.splice(sideEdges.end(), edges, edges.begin()); } - if ( nbSides == 0 ) { // go backward from the first edge + if (nbSides == 0) { // go backward from the first edge sameSide = true; - while ( !edges.empty() && sameSide ) { - sameSide = SMESH_Algo::IsContinuous( sideEdges.front(), edges.back() ); - if ( sameSide ) - sideEdges.splice( sideEdges.begin(), edges, --edges.end()); + while (!edges.empty() && sameSide) { + sameSide = SMESH_Algo::IsContinuous(sideEdges.front(), edges.back()); + if (sameSide) + sideEdges.splice(sideEdges.begin(), edges, --edges.end()); } } - quad->side.push_back( new StdMeshers_FaceSide(F, sideEdges, &aMesh, + quad->side.push_back(new StdMeshers_FaceSide(F, sideEdges, &aMesh, nbSidesside.clear(); quad->side.reserve(nbEdgesInWire.front()); nbSides = 0; SMESH_Block::GetOrderedEdges (F, V, edges, nbEdgesInWire); - while ( !edges.empty()) { + while (!edges.empty()) { sideEdges.clear(); - sideEdges.splice( sideEdges.end(), edges, edges.begin()); + sideEdges.splice(sideEdges.end(), edges, edges.begin()); bool sameSide = true; - while ( !edges.empty() && sameSide ) { + while (!edges.empty() && sameSide) { sameSide = - SMESH_Algo::IsContinuous( sideEdges.back(), edges.front() ) && - twoEdgesMeatAtVertex( sideEdges.back(), edges.front(), aMesh ); - if ( sameSide ) - sideEdges.splice( sideEdges.end(), edges, edges.begin()); + SMESH_Algo::IsContinuous(sideEdges.back(), edges.front()) && + twoEdgesMeatAtVertex(sideEdges.back(), edges.front(), aMesh); + if (sameSide) + sideEdges.splice(sideEdges.end(), edges, edges.begin()); } - if ( nbSides == 0 ) { // go backward from the first edge + if (nbSides == 0) { // go backward from the first edge sameSide = true; - while ( !edges.empty() && sameSide ) { + while (!edges.empty() && sameSide) { sameSide = - SMESH_Algo::IsContinuous( sideEdges.front(), edges.back() ) && - twoEdgesMeatAtVertex( sideEdges.front(), edges.back(), aMesh ); - if ( sameSide ) - sideEdges.splice( sideEdges.begin(), edges, --edges.end()); + SMESH_Algo::IsContinuous(sideEdges.front(), edges.back()) && + twoEdgesMeatAtVertex(sideEdges.front(), edges.back(), aMesh); + if (sameSide) + sideEdges.splice(sideEdges.begin(), edges, --edges.end()); } } - quad->side.push_back( new StdMeshers_FaceSide(F, sideEdges, &aMesh, + quad->side.push_back(new StdMeshers_FaceSide(F, sideEdges, &aMesh, nbSidesside[i]->NbEdges(); ++e ) - MESSAGE ( myTool->GetMeshDS()->ShapeToIndex( quad->side[i]->Edge( e )) << " " ); - MESSAGE ( ")\n" ); + MESSAGE ("StdMeshers_Quadrangle_2D. Edge IDs of " << nbSides << " sides:\n"); + for (int i = 0; i < nbSides; ++i) { + MESSAGE (" ("); + for (int e = 0; e < quad->side[i]->NbEdges(); ++e) + MESSAGE (myTool->GetMeshDS()->ShapeToIndex(quad->side[i]->Edge(e)) << " "); + MESSAGE (")\n"); } //cout << endl; #endif - if ( !nbSides ) + if (!nbSides) nbSides = nbEdgesInWire.front(); error(COMPERR_BAD_SHAPE, TComm("Face must have 4 sides but not ") << nbSides); delete quad; @@ -938,51 +957,51 @@ bool StdMeshers_Quadrangle_2D::CheckNbEdgesForEvaluate(SMESH_Mesh& aMesh, int nbSides = 0; list< TopoDS_Edge >::iterator edgeIt = edges.begin(); - SMESH_subMesh * sm = aMesh.GetSubMesh( *edgeIt ); + SMESH_subMesh * sm = aMesh.GetSubMesh(*edgeIt); MapShapeNbElemsItr anIt = aResMap.find(sm); - if(anIt==aResMap.end()) { + if (anIt==aResMap.end()) { return false; } std::vector aVec = (*anIt).second; IsQuadratic = (aVec[SMDSEntity_Quad_Edge] > aVec[SMDSEntity_Edge]); - if ( nbEdgesInWire.front() == 3 ) { // exactly 3 edges - if(myTriaVertexID>0) { + if (nbEdgesInWire.front() == 3) { // exactly 3 edges + if (myTriaVertexID>0) { SMESHDS_Mesh* meshDS = aMesh.GetMeshDS(); TopoDS_Vertex V = TopoDS::Vertex(meshDS->IndexToShape(myTriaVertexID)); - if(!V.IsNull()) { + if (!V.IsNull()) { TopoDS_Edge E1,E2,E3; - for(; edgeIt != edges.end(); ++edgeIt) { + for (; edgeIt != edges.end(); ++edgeIt) { TopoDS_Edge E = TopoDS::Edge(*edgeIt); TopoDS_Vertex VF, VL; TopExp::Vertices(E, VF, VL, true); - if( VF.IsSame(V) ) + if (VF.IsSame(V)) E1 = E; - else if( VL.IsSame(V) ) + else if (VL.IsSame(V)) E3 = E; else E2 = E; } SMESH_subMesh * sm = aMesh.GetSubMesh(E1); MapShapeNbElemsItr anIt = aResMap.find(sm); - if(anIt==aResMap.end()) return false; + if (anIt==aResMap.end()) return false; std::vector aVec = (*anIt).second; - if(IsQuadratic) + if (IsQuadratic) aNbNodes[0] = (aVec[SMDSEntity_Node]-1)/2 + 2; else aNbNodes[0] = aVec[SMDSEntity_Node] + 2; sm = aMesh.GetSubMesh(E2); anIt = aResMap.find(sm); - if(anIt==aResMap.end()) return false; + if (anIt==aResMap.end()) return false; aVec = (*anIt).second; - if(IsQuadratic) + if (IsQuadratic) aNbNodes[1] = (aVec[SMDSEntity_Node]-1)/2 + 2; else aNbNodes[1] = aVec[SMDSEntity_Node] + 2; sm = aMesh.GetSubMesh(E3); anIt = aResMap.find(sm); - if(anIt==aResMap.end()) return false; + if (anIt==aResMap.end()) return false; aVec = (*anIt).second; - if(IsQuadratic) + if (IsQuadratic) aNbNodes[2] = (aVec[SMDSEntity_Node]-1)/2 + 2; else aNbNodes[2] = aVec[SMDSEntity_Node] + 2; @@ -992,50 +1011,50 @@ bool StdMeshers_Quadrangle_2D::CheckNbEdgesForEvaluate(SMESH_Mesh& aMesh, } } } - if ( nbEdgesInWire.front() == 4 ) { // exactly 4 edges - for(; edgeIt != edges.end(); edgeIt++) { - SMESH_subMesh * sm = aMesh.GetSubMesh( *edgeIt ); + if (nbEdgesInWire.front() == 4) { // exactly 4 edges + for (; edgeIt != edges.end(); edgeIt++) { + SMESH_subMesh * sm = aMesh.GetSubMesh(*edgeIt); MapShapeNbElemsItr anIt = aResMap.find(sm); - if(anIt==aResMap.end()) { + if (anIt==aResMap.end()) { return false; } std::vector aVec = (*anIt).second; - if(IsQuadratic) + if (IsQuadratic) aNbNodes[nbSides] = (aVec[SMDSEntity_Node]-1)/2 + 2; else aNbNodes[nbSides] = aVec[SMDSEntity_Node] + 2; nbSides++; } } - else if ( nbEdgesInWire.front() > 4 ) { // more than 4 edges - try to unite some + else if (nbEdgesInWire.front() > 4) { // more than 4 edges - try to unite some list< TopoDS_Edge > sideEdges; - while ( !edges.empty()) { + while (!edges.empty()) { sideEdges.clear(); - sideEdges.splice( sideEdges.end(), edges, edges.begin()); // edges.front() -> sideEdges.end() + sideEdges.splice(sideEdges.end(), edges, edges.begin()); // edges.front() -> sideEdges.end() bool sameSide = true; - while ( !edges.empty() && sameSide ) { - sameSide = SMESH_Algo::IsContinuous( sideEdges.back(), edges.front() ); - if ( sameSide ) - sideEdges.splice( sideEdges.end(), edges, edges.begin()); + while (!edges.empty() && sameSide) { + sameSide = SMESH_Algo::IsContinuous(sideEdges.back(), edges.front()); + if (sameSide) + sideEdges.splice(sideEdges.end(), edges, edges.begin()); } - if ( nbSides == 0 ) { // go backward from the first edge + if (nbSides == 0) { // go backward from the first edge sameSide = true; - while ( !edges.empty() && sameSide ) { - sameSide = SMESH_Algo::IsContinuous( sideEdges.front(), edges.back() ); - if ( sameSide ) - sideEdges.splice( sideEdges.begin(), edges, --edges.end()); + while (!edges.empty() && sameSide) { + sameSide = SMESH_Algo::IsContinuous(sideEdges.front(), edges.back()); + if (sameSide) + sideEdges.splice(sideEdges.begin(), edges, --edges.end()); } } list::iterator ite = sideEdges.begin(); aNbNodes[nbSides] = 1; - for(; ite!=sideEdges.end(); ite++) { - SMESH_subMesh * sm = aMesh.GetSubMesh( *ite ); + for (; ite!=sideEdges.end(); ite++) { + SMESH_subMesh * sm = aMesh.GetSubMesh(*ite); MapShapeNbElemsItr anIt = aResMap.find(sm); - if(anIt==aResMap.end()) { + if (anIt==aResMap.end()) { return false; } std::vector aVec = (*anIt).second; - if(IsQuadratic) + if (IsQuadratic) aNbNodes[nbSides] += (aVec[SMDSEntity_Node]-1)/2 + 1; else aNbNodes[nbSides] += aVec[SMDSEntity_Node] + 1; @@ -1046,37 +1065,37 @@ bool StdMeshers_Quadrangle_2D::CheckNbEdgesForEvaluate(SMESH_Mesh& aMesh, if (nbSides < 4) { nbSides = 0; SMESH_Block::GetOrderedEdges (F, V, edges, nbEdgesInWire); - while ( !edges.empty()) { + while (!edges.empty()) { sideEdges.clear(); - sideEdges.splice( sideEdges.end(), edges, edges.begin()); + sideEdges.splice(sideEdges.end(), edges, edges.begin()); bool sameSide = true; - while ( !edges.empty() && sameSide ) { + while (!edges.empty() && sameSide) { sameSide = - SMESH_Algo::IsContinuous( sideEdges.back(), edges.front() ) && - twoEdgesMeatAtVertex( sideEdges.back(), edges.front(), aMesh ); - if ( sameSide ) - sideEdges.splice( sideEdges.end(), edges, edges.begin()); + SMESH_Algo::IsContinuous(sideEdges.back(), edges.front()) && + twoEdgesMeatAtVertex(sideEdges.back(), edges.front(), aMesh); + if (sameSide) + sideEdges.splice(sideEdges.end(), edges, edges.begin()); } - if ( nbSides == 0 ) { // go backward from the first edge + if (nbSides == 0) { // go backward from the first edge sameSide = true; - while ( !edges.empty() && sameSide ) { + while (!edges.empty() && sameSide) { sameSide = - SMESH_Algo::IsContinuous( sideEdges.front(), edges.back() ) && - twoEdgesMeatAtVertex( sideEdges.front(), edges.back(), aMesh ); - if ( sameSide ) - sideEdges.splice( sideEdges.begin(), edges, --edges.end()); + SMESH_Algo::IsContinuous(sideEdges.front(), edges.back()) && + twoEdgesMeatAtVertex(sideEdges.front(), edges.back(), aMesh); + if (sameSide) + sideEdges.splice(sideEdges.begin(), edges, --edges.end()); } } list::iterator ite = sideEdges.begin(); aNbNodes[nbSides] = 1; - for(; ite!=sideEdges.end(); ite++) { - SMESH_subMesh * sm = aMesh.GetSubMesh( *ite ); + for (; ite!=sideEdges.end(); ite++) { + SMESH_subMesh * sm = aMesh.GetSubMesh(*ite); MapShapeNbElemsItr anIt = aResMap.find(sm); - if(anIt==aResMap.end()) { + if (anIt==aResMap.end()) { return false; } std::vector aVec = (*anIt).second; - if(IsQuadratic) + if (IsQuadratic) aNbNodes[nbSides] += (aVec[SMDSEntity_Node]-1)/2 + 1; else aNbNodes[nbSides] += aVec[SMDSEntity_Node] + 1; @@ -1086,7 +1105,7 @@ bool StdMeshers_Quadrangle_2D::CheckNbEdgesForEvaluate(SMESH_Mesh& aMesh, } } if (nbSides != 4) { - if ( !nbSides ) + if (!nbSides) nbSides = nbEdgesInWire.front(); error(COMPERR_BAD_SHAPE, TComm("Face must have 4 sides but not ") << nbSides); return false; @@ -1111,13 +1130,12 @@ FaceQuadStruct *StdMeshers_Quadrangle_2D::CheckAnd2Dcompute FaceQuadStruct *quad = CheckNbEdges(aMesh, aShape); - if(!quad) return 0; + if (!quad) return 0; // set normalized grid on unit square in parametric domain bool stat = SetNormalizedGrid(aMesh, aShape, quad); - if(!stat) { - if(!quad) - delete quad; + if (!stat) { + if (quad) delete quad; quad = 0; } @@ -1141,13 +1159,21 @@ faceQuadStruct::~faceQuadStruct() namespace { inline const vector& GetUVPtStructIn(FaceQuadStruct* quad, int i, int nbSeg) { - bool isXConst = ( i == BOTTOM_SIDE || i == TOP_SIDE ); - double constValue = ( i == BOTTOM_SIDE || i == LEFT_SIDE ) ? 0 : 1; + bool isXConst = (i == BOTTOM_SIDE || i == TOP_SIDE); + double constValue = (i == BOTTOM_SIDE || i == LEFT_SIDE) ? 0 : 1; return quad->isEdgeOut[i] ? quad->side[i]->SimulateUVPtStruct(nbSeg,isXConst,constValue) : quad->side[i]->GetUVPtStruct(isXConst,constValue); } + inline gp_UV CalcUV(double x, double y, + const gp_UV& a0,const gp_UV& a1,const gp_UV& a2,const gp_UV& a3, + const gp_UV& p0,const gp_UV& p1,const gp_UV& p2,const gp_UV& p3) + { + return + ((1 - y) * p0 + x * p1 + y * p2 + (1 - x) * p3 ) - + ((1 - x) * (1 - y) * a0 + x * (1 - y) * a1 + x * y * a2 + (1 - x) * y * a3); + } } //============================================================================= @@ -1194,14 +1220,14 @@ bool StdMeshers_Quadrangle_2D::SetNormalizedGrid (SMESH_Mesh & aMesh, UVPtStruct *uv_grid = quad->uv_grid = new UVPtStruct[nbvertic * nbhoriz]; - const vector& uv_e0 = GetUVPtStructIn( quad, 0, nbhoriz - 1 ); - const vector& uv_e1 = GetUVPtStructIn( quad, 1, nbvertic - 1 ); - const vector& uv_e2 = GetUVPtStructIn( quad, 2, nbhoriz - 1 ); - const vector& uv_e3 = GetUVPtStructIn( quad, 3, nbvertic - 1 ); + const vector& uv_e0 = GetUVPtStructIn(quad, 0, nbhoriz - 1); + const vector& uv_e1 = GetUVPtStructIn(quad, 1, nbvertic - 1); + const vector& uv_e2 = GetUVPtStructIn(quad, 2, nbhoriz - 1); + const vector& uv_e3 = GetUVPtStructIn(quad, 3, nbvertic - 1); - if ( uv_e0.empty() || uv_e1.empty() || uv_e2.empty() || uv_e3.empty() ) - //return error( "Can't find nodes on sides"); - return error( COMPERR_BAD_INPUT_MESH ); + if (uv_e0.empty() || uv_e1.empty() || uv_e2.empty() || uv_e3.empty()) + //return error("Can't find nodes on sides"); + return error(COMPERR_BAD_INPUT_MESH); // nodes Id on "in" edges if (! quad->isEdgeOut[0]) { @@ -1254,10 +1280,10 @@ bool StdMeshers_Quadrangle_2D::SetNormalizedGrid (SMESH_Mesh & aMesh, } // 4 --- projection on 2d domain (u,v) - gp_UV a0( uv_e0.front().u, uv_e0.front().v ); - gp_UV a1( uv_e0.back().u, uv_e0.back().v ); - gp_UV a2( uv_e2.back().u, uv_e2.back().v ); - gp_UV a3( uv_e2.front().u, uv_e2.front().v ); + gp_UV a0(uv_e0.front().u, uv_e0.front().v); + gp_UV a1(uv_e0.back().u, uv_e0.back().v); + gp_UV a2(uv_e2.back().u, uv_e2.back().v); + gp_UV a3(uv_e2.front().u, uv_e2.front().v); for (int i = 0; i < nbhoriz; i++) { for (int j = 0; j < nbvertic; j++) { @@ -1275,8 +1301,7 @@ bool StdMeshers_Quadrangle_2D::SetNormalizedGrid (SMESH_Mesh & aMesh, gp_UV p2 = quad->side[2]->Value2d(param_2).XY(); gp_UV p3 = quad->side[3]->Value2d(param_3).XY(); - gp_UV uv = (1 - y) * p0 + x * p1 + y * p2 + (1 - x) * p3; - uv -= (1 - x) * (1 - y) * a0 + x * (1 - y) * a1 + x * y * a2 + (1 - x) * y * a3; + gp_UV uv = CalcUV(x,y, a0,a1,a2,a3, p0,p1,p2,p3); uv_grid[ij].u = uv.X(); uv_grid[ij].v = uv.Y(); @@ -1293,11 +1318,11 @@ bool StdMeshers_Quadrangle_2D::SetNormalizedGrid (SMESH_Mesh & aMesh, static void ShiftQuad(FaceQuadStruct* quad, const int num, bool) { StdMeshers_FaceSide* side[4] = { quad->side[0], quad->side[1], quad->side[2], quad->side[3] }; - for (int i = BOTTOM_SIDE; i < NB_SIDES; ++i ) { - int id = ( i + num ) % NB_SIDES; - bool wasForward = ( i < TOP_SIDE ); - bool newForward = ( id < TOP_SIDE ); - if ( wasForward != newForward ) + for (int i = BOTTOM_SIDE; i < NB_SIDES; ++i) { + int id = (i + num) % NB_SIDES; + bool wasForward = (i < TOP_SIDE); + bool newForward = (id < TOP_SIDE); + if (wasForward != newForward) side[ i ]->Reverse(); quad->side[ id ] = side[ i ]; } @@ -1313,9 +1338,9 @@ static gp_UV CalcUV(double x0, double x1, double y0, double y1, const gp_UV& a0, const gp_UV& a1, const gp_UV& a2, const gp_UV& a3) { - const vector& uv_eb = quad->side[0]->GetUVPtStruct(true,0 ); + const vector& uv_eb = quad->side[0]->GetUVPtStruct(true,0); const vector& uv_er = quad->side[1]->GetUVPtStruct(false,1); - const vector& uv_et = quad->side[2]->GetUVPtStruct(true,1 ); + const vector& uv_et = quad->side[2]->GetUVPtStruct(true,1); const vector& uv_el = quad->side[3]->GetUVPtStruct(false,0); double x = (x0 + y0 * (x1 - x0)) / (1 - (y1 - y0) * (x1 - x0)); @@ -1331,9 +1356,7 @@ static gp_UV CalcUV(double x0, double x1, double y0, double y1, gp_UV p2 = quad->side[TOP_SIDE ]->Value2d(param_t).XY(); gp_UV p3 = quad->side[LEFT_SIDE ]->Value2d(param_l).XY(); - gp_UV uv = p0 * (1 - y) + p1 * x + p2 * y + p3 * (1 - x); - - uv -= (1 - x) * (1 - y) * a0 + x * (1 - y) * a1 + x * y * a2 + (1 - x) * y * a3; + gp_UV uv = CalcUV(x,y, a0,a1,a2,a3, p0,p1,p2,p3); return uv; } @@ -1348,27 +1371,12 @@ static gp_UV CalcUV2(double x, double y, const gp_UV& a0, const gp_UV& a1, const gp_UV& a2, const gp_UV& a3) { - const vector& uv_eb = quad->side[0]->GetUVPtStruct(true,0 ); - const vector& uv_er = quad->side[1]->GetUVPtStruct(false,1); - const vector& uv_et = quad->side[2]->GetUVPtStruct(true,1 ); - const vector& uv_el = quad->side[3]->GetUVPtStruct(false,0); - - //double x = (x0 + y0 * (x1 - x0)) / (1 - (y1 - y0) * (x1 - x0)); - //double y = y0 + x * (y1 - y0); - - double param_b = uv_eb[0].normParam + x * (uv_eb.back().normParam - uv_eb[0].normParam); - double param_t = uv_et[0].normParam + x * (uv_et.back().normParam - uv_et[0].normParam); - double param_r = uv_er[0].normParam + y * (uv_er.back().normParam - uv_er[0].normParam); - double param_l = uv_el[0].normParam + y * (uv_el.back().normParam - uv_el[0].normParam); - - gp_UV p0 = quad->side[BOTTOM_SIDE]->Value2d(param_b).XY(); - gp_UV p1 = quad->side[RIGHT_SIDE ]->Value2d(param_r).XY(); - gp_UV p2 = quad->side[TOP_SIDE ]->Value2d(param_t).XY(); - gp_UV p3 = quad->side[LEFT_SIDE ]->Value2d(param_l).XY(); - - gp_UV uv = p0 * (1 - y) + p1 * x + p2 * y + p3 * (1 - x); + gp_UV p0 = quad->side[BOTTOM_SIDE]->Value2d(x).XY(); + gp_UV p1 = quad->side[RIGHT_SIDE ]->Value2d(y).XY(); + gp_UV p2 = quad->side[TOP_SIDE ]->Value2d(x).XY(); + gp_UV p3 = quad->side[LEFT_SIDE ]->Value2d(y).XY(); - uv -= (1 - x) * (1 - y) * a0 + x * (1 - y) * a1 + x * y * a2 + (1 - x) * y * a3; + gp_UV uv = CalcUV(x,y, a0,a1,a2,a3, p0,p1,p2,p3); return uv; } @@ -1388,20 +1396,14 @@ bool StdMeshers_Quadrangle_2D::ComputeQuadPref (SMESH_Mesh & aMesh, // of meshing after implementation new variant // for bug 0016220 from Mantis. bool OldVersion = false; + if (myQuadType == QUAD_QUADRANGLE_PREF_REVERSED) + OldVersion = true; SMESHDS_Mesh * meshDS = aMesh.GetMeshDS(); const TopoDS_Face& F = TopoDS::Face(aShape); Handle(Geom_Surface) S = BRep_Tool::Surface(F); -// const TopoDS_Wire& W = BRepTools::OuterWire(F); bool WisF = true; -// if(W.Orientation()==TopAbs_FORWARD) -// WisF = true; - //if(WisF) cout<<"W is FORWARD"<ShapeToIndex( F ); + int i,j,geomFaceID = meshDS->ShapeToIndex(F); int nb = quad->side[0]->NbPoints(); int nr = quad->side[1]->NbPoints(); @@ -1410,8 +1412,8 @@ bool StdMeshers_Quadrangle_2D::ComputeQuadPref (SMESH_Mesh & aMesh, int dh = abs(nb-nt); int dv = abs(nr-nl); - if( dh>=dv ) { - if( nt>nb ) { + if (dh>=dv) { + if (nt>nb) { // it is a base case => not shift quad but me be replacement is need ShiftQuad(quad,0,WisF); } @@ -1421,7 +1423,7 @@ bool StdMeshers_Quadrangle_2D::ComputeQuadPref (SMESH_Mesh & aMesh, } } else { - if( nr>nl ) { + if (nr>nl) { // we have to shift quad on 1 ShiftQuad(quad,1,WisF); } @@ -1470,7 +1472,7 @@ bool StdMeshers_Quadrangle_2D::ComputeQuadPref (SMESH_Mesh & aMesh, // 0------------0 // 0 bottom 1 - if(dh>dv) { + if (dh>dv) { addv = (dh-dv)/2; nbv = nbv + addv; } @@ -1479,82 +1481,81 @@ bool StdMeshers_Quadrangle_2D::ComputeQuadPref (SMESH_Mesh & aMesh, nbh = nbh + addh; } - const vector& uv_eb = quad->side[0]->GetUVPtStruct(true,0 ); + const vector& uv_eb = quad->side[0]->GetUVPtStruct(true,0); const vector& uv_er = quad->side[1]->GetUVPtStruct(false,1); - const vector& uv_et = quad->side[2]->GetUVPtStruct(true,1 ); + const vector& uv_et = quad->side[2]->GetUVPtStruct(true,1); const vector& uv_el = quad->side[3]->GetUVPtStruct(false,0); - if ( uv_eb.size() != nb || uv_er.size() != nr || uv_et.size() != nt || uv_el.size() != nl ) - return error( COMPERR_BAD_INPUT_MESH ); + if (uv_eb.size() != nb || uv_er.size() != nr || uv_et.size() != nt || uv_el.size() != nl) + return error(COMPERR_BAD_INPUT_MESH); // arrays for normalized params //cout<<"Dump B:"<X()<<","<Y()<<","<Z()<<")"<0) { + if (dl>0) { // add top nodes - for(i=1; i<=dl; i++) + for (i=1; i<=dl; i++) NodesL.SetValue(i+1,nl,uv_et[i].node); // create and add needed nodes TColgp_SequenceOfXY UVtmp; - for(i=1; i<=dl; i++) { + for (i=1; i<=dl; i++) { double x0 = npt.Value(i+1); double x1 = x0; // diagonal node @@ -1565,9 +1566,9 @@ bool StdMeshers_Quadrangle_2D::ComputeQuadPref (SMESH_Mesh & aMesh, SMDS_MeshNode * N = meshDS->AddNode(P.X(), P.Y(), P.Z()); meshDS->SetNodeOnFace(N, geomFaceID, UV.X(), UV.Y()); NodesL.SetValue(i+1,1,N); - if(UVL.Length()AddNode(P.X(), P.Y(), P.Z()); meshDS->SetNodeOnFace(N, geomFaceID, UV.X(), UV.Y()); NodesL.SetValue(i+1,j,N); - if( i==dl ) UVtmp.Append(UV); + if (i==dl) UVtmp.Append(UV); } } - for(i=1; i<=UVtmp.Length() && UVL.Length()X()<<","<Y()<<","<Z()<<")"; // } // cout<AddFace(NodesL.Value(i,j), NodesL.Value(i+1,j), NodesL.Value(i+1,j+1), NodesL.Value(i,j+1)); - if(F) meshDS->SetMeshElementOnShape(F, geomFaceID); + if (F) meshDS->SetMeshElementOnShape(F, geomFaceID); } else { SMDS_MeshFace* F = myTool->AddFace(NodesL.Value(i,j), NodesL.Value(i,j+1), NodesL.Value(i+1,j+1), NodesL.Value(i+1,j)); - if(F) meshDS->SetMeshElementOnShape(F, geomFaceID); + if (F) meshDS->SetMeshElementOnShape(F, geomFaceID); } } } } else { // fill UVL using c2d - for(i=1; i0) { + if (dr>0) { // add top nodes - for(i=1; i<=dr; i++) + for (i=1; i<=dr; i++) NodesR.SetValue(i+1,1,uv_et[nt-1-i].node); // create and add needed nodes TColgp_SequenceOfXY UVtmp; - for(i=1; i<=dr; i++) { + for (i=1; i<=dr; i++) { double x0 = npt.Value(nt-i); double x1 = x0; // diagonal node @@ -1636,9 +1637,9 @@ bool StdMeshers_Quadrangle_2D::ComputeQuadPref (SMESH_Mesh & aMesh, SMDS_MeshNode * N = meshDS->AddNode(P.X(), P.Y(), P.Z()); meshDS->SetNodeOnFace(N, geomFaceID, UV.X(), UV.Y()); NodesR.SetValue(i+1,nr,N); - if(UVR.Length()AddNode(P.X(), P.Y(), P.Z()); meshDS->SetNodeOnFace(N, geomFaceID, UV.X(), UV.Y()); NodesR.SetValue(i+1,j,N); - if( i==dr ) UVtmp.Prepend(UV); + if (i==dr) UVtmp.Prepend(UV); } } - for(i=1; i<=UVtmp.Length() && UVR.Length()AddFace(NodesR.Value(i,j), NodesR.Value(i+1,j), NodesR.Value(i+1,j+1), NodesR.Value(i,j+1)); - if(F) meshDS->SetMeshElementOnShape(F, geomFaceID); + if (F) meshDS->SetMeshElementOnShape(F, geomFaceID); } else { SMDS_MeshFace* F = myTool->AddFace(NodesR.Value(i,j), NodesR.Value(i,j+1), NodesR.Value(i+1,j+1), NodesR.Value(i+1,j)); - if(F) meshDS->SetMeshElementOnShape(F, geomFaceID); + if (F) meshDS->SetMeshElementOnShape(F, geomFaceID); } } } } else { // fill UVR using c2d - for(i=1; iAddNode(P.X(), P.Y(), P.Z()); meshDS->SetNodeOnFace(N, geomFaceID, UV.X(), UV.Y()); NodesC.SetValue(i,nbv-nnn+j,N); + if ( j==1 ) + UVT.Append( UV ); } } // add diagonal layers //cout<<"UVL.Length()="<Value(u,v); + gp_UV A2 = UVR.Value(nbv-nnn); + gp_UV A3 = UVL.Value(nbv-nnn); + for (i=1; iValue(UV.X(),UV.Y()); SMDS_MeshNode* N = meshDS->AddNode(P.X(), P.Y(), P.Z()); - meshDS->SetNodeOnFace(N, geomFaceID, u, v); + meshDS->SetNodeOnFace(N, geomFaceID, UV.X(),UV.Y()); NodesC.SetValue(j,i+1,N); } } // create faces - for(i=1; iAddFace(NodesC.Value(i,j), NodesC.Value(i+1,j), NodesC.Value(i+1,j+1), NodesC.Value(i,j+1)); - if(F) meshDS->SetMeshElementOnShape(F, geomFaceID); + if (F) meshDS->SetMeshElementOnShape(F, geomFaceID); } else { SMDS_MeshFace* F = myTool->AddFace(NodesC.Value(i,j), NodesC.Value(i,j+1), NodesC.Value(i+1,j+1), NodesC.Value(i+1,j)); - if(F) meshDS->SetMeshElementOnShape(F, geomFaceID); + if (F) meshDS->SetMeshElementOnShape(F, geomFaceID); } } } @@ -1753,39 +1761,35 @@ bool StdMeshers_Quadrangle_2D::ComputeQuadPref (SMESH_Mesh & aMesh, // step1: create faces for bottom rectangle domain StdMeshers_Array2OfNode NodesBRD(1,nb,1,nnn-1); // fill UVL and UVR using c2d - for(j=0; jValue(u,v); + for (j=2; jValue(UV.X(),UV.Y()); SMDS_MeshNode* N = meshDS->AddNode(P.X(), P.Y(), P.Z()); - meshDS->SetNodeOnFace(N, geomFaceID, u, v); + meshDS->SetNodeOnFace(N, geomFaceID, UV.X(),UV.Y()); NodesBRD.SetValue(j,i+1,N); - } } - int nbf=0; - for(j=1; jAddFace(NodesBRD.Value(i,j), NodesBRD.Value(i+1,j), NodesBRD.Value(i+1,j+1), NodesBRD.Value(i,j+1)); - if(F) meshDS->SetMeshElementOnShape(F, geomFaceID); + if (F) meshDS->SetMeshElementOnShape(F, geomFaceID); } else { SMDS_MeshFace* F = myTool->AddFace(NodesBRD.Value(i,j), NodesBRD.Value(i,j+1), NodesBRD.Value(i+1,j+1), NodesBRD.Value(i+1,j)); - if(F) meshDS->SetMeshElementOnShape(F, geomFaceID); + if (F) meshDS->SetMeshElementOnShape(F, geomFaceID); } } } @@ -1793,19 +1797,19 @@ bool StdMeshers_Quadrangle_2D::ComputeQuadPref (SMESH_Mesh & aMesh, // create faces for region C StdMeshers_Array2OfNode NodesC(1,nb,1,drl+1+addv); // add nodes from previous region - for(j=1; j<=nb; j++) { + for (j=1; j<=nb; j++) { NodesC.SetValue(j,1,NodesBRD.Value(j,nnn-1)); } - if( (drl+addv) > 0 ) { + if ((drl+addv) > 0) { int n1,n2; - if(nr>nl) { + if (nr>nl) { n1 = 1; n2 = drl + 1; TColgp_SequenceOfXY UVtmp; double drparam = npr.Value(nr) - npr.Value(nnn-1); double dlparam = npl.Value(nnn) - npl.Value(nnn-1); double y0,y1; - for(i=1; i<=drl; i++) { + for (i=1; i<=drl; i++) { // add existed nodes from right edge NodesC.SetValue(nb,i+1,uv_er[nnn+i-2].node); //double dtparam = npt.Value(i+1); @@ -1813,7 +1817,7 @@ bool StdMeshers_Quadrangle_2D::ComputeQuadPref (SMESH_Mesh & aMesh, double dpar = (y1 - npr.Value(nnn-1))/drparam; y0 = npl.Value(nnn-1) + dpar*dlparam; // param on left edge double dy = y1 - y0; - for(j=1; jValue(UV.X(),UV.Y()); @@ -1849,14 +1853,14 @@ bool StdMeshers_Quadrangle_2D::ComputeQuadPref (SMESH_Mesh & aMesh, double drparam = npr.Value(nnn) - npr.Value(nnn-1); double y0 = npl.Value(nnn-1); double y1 = npr.Value(nnn-1); - for(i=1; i<=drl; i++) { + for (i=1; i<=drl; i++) { // add existed nodes from right edge NodesC.SetValue(1,i+1,uv_el[nnn+i-2].node); y0 = npl.Value(nnn+i-1); // param on left edge double dpar = (y0 - npl.Value(nnn-1))/dlparam; y1 = npr.Value(nnn-1) + dpar*drparam; // param on right edge double dy = y1 - y0; - for(j=2; j<=nb; j++) { + for (j=2; j<=nb; j++) { double x = npb.Value(j)*npt.Value(nt-i); double y = y0 + dy*x; gp_UV UV = CalcUV2(x, y, quad, a0, a1, a2, a3); @@ -1868,13 +1872,13 @@ bool StdMeshers_Quadrangle_2D::ComputeQuadPref (SMESH_Mesh & aMesh, } double dy0 = (1-y0)/(addv+1); double dy1 = (1-y1)/(addv+1); - for(i=1; i<=addv; i++) { + for (i=1; i<=addv; i++) { double yy0 = y0 + dy0*i; double yy1 = y1 + dy1*i; double dyy = yy1 - yy0; - for(j=1; j<=nb; j++) { + for (j=1; j<=nb; j++) { double x = npt.Value(i+1) + - npb.Value(j) * ( npt.Value(nt-i-drl) - npt.Value(i+1) ); + npb.Value(j) * (npt.Value(nt-i-drl) - npt.Value(i+1)); double y = yy0 + dyy*x; gp_UV UV = CalcUV2(x, y, quad, a0, a1, a2, a3); gp_Pnt P = S->Value(UV.X(),UV.Y()); @@ -1885,57 +1889,55 @@ bool StdMeshers_Quadrangle_2D::ComputeQuadPref (SMESH_Mesh & aMesh, } } // create faces - for(j=1; j<=drl+addv; j++) { - for(i=1; iAddFace(NodesC.Value(i,j), NodesC.Value(i+1,j), NodesC.Value(i+1,j+1), NodesC.Value(i,j+1)); - if(F) meshDS->SetMeshElementOnShape(F, geomFaceID); + if (F) meshDS->SetMeshElementOnShape(F, geomFaceID); } else { SMDS_MeshFace* F = myTool->AddFace(NodesC.Value(i,j), NodesC.Value(i,j+1), NodesC.Value(i+1,j+1), NodesC.Value(i+1,j)); - if(F) meshDS->SetMeshElementOnShape(F, geomFaceID); + if (F) meshDS->SetMeshElementOnShape(F, geomFaceID); } } } // end nr=n2; i--) { + for (i=drl+addv; i>=n2; i--) { nnn++; NodesLast.SetValue(nnn,1,NodesC.Value(nb,i)); } - for(i=1; iAddFace(NodesLast.Value(i,1), NodesLast.Value(i+1,1), NodesLast.Value(i+1,2), NodesLast.Value(i,2)); - if(F) meshDS->SetMeshElementOnShape(F, geomFaceID); + if (F) meshDS->SetMeshElementOnShape(F, geomFaceID); } else { SMDS_MeshFace* F = myTool->AddFace(NodesLast.Value(i,1), NodesLast.Value(i,2), NodesLast.Value(i+1,2), NodesLast.Value(i+1,2)); - if(F) meshDS->SetMeshElementOnShape(F, geomFaceID); + if (F) meshDS->SetMeshElementOnShape(F, geomFaceID); } } - } // if( (drl+addv) > 0 ) + } // if ((drl+addv) > 0) } // end new version implementation @@ -1960,6 +1962,8 @@ bool StdMeshers_Quadrangle_2D::EvaluateQuadPref(SMESH_Mesh & aMesh, // of meshing after implementation new variant // for bug 0016220 from Mantis. bool OldVersion = false; + if (myQuadType == QUAD_QUADRANGLE_PREF_REVERSED) + OldVersion = true; const TopoDS_Face& F = TopoDS::Face(aShape); Handle(Geom_Surface) S = BRep_Tool::Surface(F); @@ -1971,8 +1975,8 @@ bool StdMeshers_Quadrangle_2D::EvaluateQuadPref(SMESH_Mesh & aMesh, int dh = abs(nb-nt); int dv = abs(nr-nl); - if( dh>=dv ) { - if( nt>nb ) { + if (dh>=dv) { + if (nt>nb) { // it is a base case => not shift } else { @@ -1984,7 +1988,7 @@ bool StdMeshers_Quadrangle_2D::EvaluateQuadPref(SMESH_Mesh & aMesh, } } else { - if( nr>nl ) { + if (nr>nl) { // we have to shift quad on 1 nb = aNbNodes[3]; nr = aNbNodes[0]; @@ -2007,7 +2011,7 @@ bool StdMeshers_Quadrangle_2D::EvaluateQuadPref(SMESH_Mesh & aMesh, int addh = 0; int addv = 0; - if(dh>dv) { + if (dh>dv) { addv = (dh-dv)/2; nbv = nbv + addv; } @@ -2017,7 +2021,7 @@ bool StdMeshers_Quadrangle_2D::EvaluateQuadPref(SMESH_Mesh & aMesh, } int dl,dr; - if(OldVersion) { + if (OldVersion) { // add some params to right and left after the first param // insert to right dr = nbv - nr; @@ -2029,14 +2033,14 @@ bool StdMeshers_Quadrangle_2D::EvaluateQuadPref(SMESH_Mesh & aMesh, int nbNodes = 0; int nbFaces = 0; - if(OldVersion) { + if (OldVersion) { // step1: create faces for left domain - if(dl>0) { + if (dl>0) { nbNodes += dl*(nl-1); nbFaces += dl*(nl-1); } // step2: create faces for right domain - if(dr>0) { + if (dr>0) { nbNodes += dr*(nr-1); nbFaces += dr*(nr-1); } @@ -2053,11 +2057,11 @@ bool StdMeshers_Quadrangle_2D::EvaluateQuadPref(SMESH_Mesh & aMesh, } // end new version implementation std::vector aVec(SMDSEntity_Last); - for(int i=SMDSEntity_Node; iX(),theNode3->Y(),theNode3->Z()); gp_Pnt d(theNode4->X(),theNode4->Y(),theNode4->Z()); SMDS_MeshFace* face; - if(a.Distance(c) > b.Distance(d)){ + if (a.Distance(c) > b.Distance(d)){ face = myTool->AddFace(theNode2, theNode4 , theNode1); - if(face) theMeshDS->SetMeshElementOnShape(face, theFaceID ); + if (face) theMeshDS->SetMeshElementOnShape(face, theFaceID); face = myTool->AddFace(theNode2, theNode3, theNode4); - if(face) theMeshDS->SetMeshElementOnShape(face, theFaceID ); + if (face) theMeshDS->SetMeshElementOnShape(face, theFaceID); } else{ face = myTool->AddFace(theNode1, theNode2 ,theNode3); - if(face) theMeshDS->SetMeshElementOnShape(face, theFaceID ); + if (face) theMeshDS->SetMeshElementOnShape(face, theFaceID); face = myTool->AddFace(theNode1, theNode3, theNode4); - if(face) theMeshDS->SetMeshElementOnShape(face, theFaceID ); + if (face) theMeshDS->SetMeshElementOnShape(face, theFaceID); } } +//======================================================================= +/*! + * Implementation of Reduced algorithm (meshing with quadrangles only) + */ +//======================================================================= +bool StdMeshers_Quadrangle_2D::ComputeReduced (SMESH_Mesh & aMesh, + const TopoDS_Shape& aShape, + FaceQuadStruct* quad) +{ + SMESHDS_Mesh * meshDS = aMesh.GetMeshDS(); + const TopoDS_Face& F = TopoDS::Face(aShape); + Handle(Geom_Surface) S = BRep_Tool::Surface(F); + int i,j,geomFaceID = meshDS->ShapeToIndex(F); + + int nb = quad->side[0]->NbPoints(); + int nr = quad->side[1]->NbPoints(); + int nt = quad->side[2]->NbPoints(); + int nl = quad->side[3]->NbPoints(); + + // Simple Reduce 8->6->4->2 (3 steps) Multiple Reduce 8->2 (1 step) + // + // .-----.-----.-----.-----. .-----.-----.-----.-----. + // | / \ | / \ | | / \ | / \ | + // | / .--.--. \ | | / \ | / \ | + // | / / | \ \ | | / .----.----. \ | + // .---.---.---.---.---.---. | / / \ | / \ \ | + // | / / \ | / \ \ | | / / \ | / \ \ | + // | / / .-.-. \ \ | | / / .---.---. \ \ | + // | / / / | \ \ \ | | / / / \ | / \ \ \ | + // .--.--.--.--.--.--.--.--. | / / / \ | / \ \ \ | + // | / / / \ | / \ \ \ | | / / / .-.-. \ \ \ | + // | / / / .-.-. \ \ \ | | / / / / | \ \ \ \ | + // | / / / / | \ \ \ \ | | / / / / | \ \ \ \ | + // .-.-.-.--.--.--.--.-.-.-. .-.-.-.--.--.--.--.-.-.-. + + bool MultipleReduce = false; + { + int nb1 = nb; + int nr1 = nr; + int nt1 = nt; + int nl1 = nl; + + if (nr == nl) { + if (nb < nt) { + nt1 = nb; + nb1 = nt; + } + } + else if (nb == nt) { + nl1 = nb; // and == nt + nr1 = nb; // and == nt + if (nl < nr) { + nt1 = nl; + nb1 = nr; + } + else { + nt1 = nr; + nb1 = nl; + } + } + else { + return false; + } + + // number of rows and columns + int nrows = nr1 - 1; // and also == nl1 - 1 + int ncol_top = nt1 - 1; + int ncol_bot = nb1 - 1; + int npair_top = ncol_top / 2; + // maximum number of bottom elements for "linear" simple reduce + //int max_lin = ncol_top + npair_top * 2 * nrows; + // maximum number of bottom elements for "tree" simple reduce + int max_tree = npair_top * pow(2.0, nrows + 1); + if (ncol_top > npair_top * 2) { + int delta = ncol_bot - max_tree; + for (int irow = 1; irow < nrows; irow++) { + int nfour = delta / 4; + delta -= nfour*2; + } + if (delta <= (ncol_top - npair_top * 2)) + max_tree = ncol_bot; + } + + if (ncol_bot > max_tree) + MultipleReduce = true; + } + + if (MultipleReduce) { // == ComputeQuadPref QUAD_QUADRANGLE_PREF_REVERSED + //================================================== + int dh = abs(nb-nt); + int dv = abs(nr-nl); + if (dh >= dv) { + if (nt > nb) { + // it is a base case => not shift quad but may be replacement is need + ShiftQuad(quad,0,true); + } + else { + // we have to shift quad on 2 + ShiftQuad(quad,2,true); + } + } + else { + if (nr > nl) { + // we have to shift quad on 1 + ShiftQuad(quad,1,true); + } + else { + // we have to shift quad on 3 + ShiftQuad(quad,3,true); + } + } + + nb = quad->side[0]->NbPoints(); + nr = quad->side[1]->NbPoints(); + nt = quad->side[2]->NbPoints(); + nl = quad->side[3]->NbPoints(); + dh = abs(nb-nt); + dv = abs(nr-nl); + int nbh = Max(nb,nt); + int nbv = Max(nr,nl); + int addh = 0; + int addv = 0; + + if (dh>dv) { + addv = (dh-dv)/2; + nbv = nbv + addv; + } + else { // dv>=dh + addh = (dv-dh)/2; + nbh = nbh + addh; + } + + const vector& uv_eb = quad->side[0]->GetUVPtStruct(true,0); + const vector& uv_er = quad->side[1]->GetUVPtStruct(false,1); + const vector& uv_et = quad->side[2]->GetUVPtStruct(true,1); + const vector& uv_el = quad->side[3]->GetUVPtStruct(false,0); + + if (uv_eb.size() != nb || uv_er.size() != nr || uv_et.size() != nt || uv_el.size() != nl) + return error(COMPERR_BAD_INPUT_MESH); + + // arrays for normalized params + TColStd_SequenceOfReal npb, npr, npt, npl; + for (j = 0; j < nb; j++) { + npb.Append(uv_eb[j].normParam); + } + for (i = 0; i < nr; i++) { + npr.Append(uv_er[i].normParam); + } + for (j = 0; j < nt; j++) { + npt.Append(uv_et[j].normParam); + } + for (i = 0; i < nl; i++) { + npl.Append(uv_el[i].normParam); + } + + int dl,dr; + // orientation of face and 3 main domain for future faces + // 0 top 1 + // 1------------1 + // | | | | + // | | | | + // | L | | R | + // left | | | | rigth + // | / \ | + // | / C \ | + // |/ \| + // 0------------0 + // 0 bottom 1 + + // add some params to right and left after the first param + // insert to right + dr = nbv - nr; + double dpr = (npr.Value(2) - npr.Value(1))/(dr+1); + for (i=1; i<=dr; i++) { + npr.InsertAfter(1,npr.Value(2)-dpr); + } + // insert to left + dl = nbv - nl; + dpr = (npl.Value(2) - npl.Value(1))/(dl+1); + for (i=1; i<=dl; i++) { + npl.InsertAfter(1,npl.Value(2)-dpr); + } + + gp_XY a0 (uv_eb.front().u, uv_eb.front().v); + gp_XY a1 (uv_eb.back().u, uv_eb.back().v); + gp_XY a2 (uv_et.back().u, uv_et.back().v); + gp_XY a3 (uv_et.front().u, uv_et.front().v); + + int nnn = Min(nr,nl); + // auxilary sequence of XY for creation nodes + // in the bottom part of central domain + // it's length must be == nbv-nnn-1 + TColgp_SequenceOfXY UVL; + TColgp_SequenceOfXY UVR; + //================================================== + + // step1: create faces for left domain + StdMeshers_Array2OfNode NodesL(1,dl+1,1,nl); + // add left nodes + for (j=1; j<=nl; j++) + NodesL.SetValue(1,j,uv_el[j-1].node); + if (dl>0) { + // add top nodes + for (i=1; i<=dl; i++) + NodesL.SetValue(i+1,nl,uv_et[i].node); + // create and add needed nodes + TColgp_SequenceOfXY UVtmp; + for (i=1; i<=dl; i++) { + double x0 = npt.Value(i+1); + double x1 = x0; + // diagonal node + double y0 = npl.Value(i+1); + double y1 = npr.Value(i+1); + gp_UV UV = CalcUV(x0, x1, y0, y1, quad, a0, a1, a2, a3); + gp_Pnt P = S->Value(UV.X(),UV.Y()); + SMDS_MeshNode * N = meshDS->AddNode(P.X(), P.Y(), P.Z()); + meshDS->SetNodeOnFace(N, geomFaceID, UV.X(), UV.Y()); + NodesL.SetValue(i+1,1,N); + if (UVL.Length()Value(UV.X(),UV.Y()); + SMDS_MeshNode* N = meshDS->AddNode(P.X(), P.Y(), P.Z()); + meshDS->SetNodeOnFace(N, geomFaceID, UV.X(), UV.Y()); + NodesL.SetValue(i+1,j,N); + if (i==dl) UVtmp.Append(UV); + } + } + for (i=1; i<=UVtmp.Length() && UVL.Length()AddFace(NodesL.Value(i,j), NodesL.Value(i+1,j), + NodesL.Value(i+1,j+1), NodesL.Value(i,j+1)); + if (F) meshDS->SetMeshElementOnShape(F, geomFaceID); + } + } + } + else { + // fill UVL using c2d + for (i=1; i0) { + // add top nodes + for (i=1; i<=dr; i++) + NodesR.SetValue(i+1,1,uv_et[nt-1-i].node); + // create and add needed nodes + TColgp_SequenceOfXY UVtmp; + for (i=1; i<=dr; i++) { + double x0 = npt.Value(nt-i); + double x1 = x0; + // diagonal node + double y0 = npl.Value(i+1); + double y1 = npr.Value(i+1); + gp_UV UV = CalcUV(x0, x1, y0, y1, quad, a0, a1, a2, a3); + gp_Pnt P = S->Value(UV.X(),UV.Y()); + SMDS_MeshNode * N = meshDS->AddNode(P.X(), P.Y(), P.Z()); + meshDS->SetNodeOnFace(N, geomFaceID, UV.X(), UV.Y()); + NodesR.SetValue(i+1,nr,N); + if (UVR.Length()Value(UV.X(),UV.Y()); + SMDS_MeshNode* N = meshDS->AddNode(P.X(), P.Y(), P.Z()); + meshDS->SetNodeOnFace(N, geomFaceID, UV.X(), UV.Y()); + NodesR.SetValue(i+1,j,N); + if (i==dr) UVtmp.Prepend(UV); + } + } + for (i=1; i<=UVtmp.Length() && UVR.Length()AddFace(NodesR.Value(i,j), NodesR.Value(i+1,j), + NodesR.Value(i+1,j+1), NodesR.Value(i,j+1)); + if (F) meshDS->SetMeshElementOnShape(F, geomFaceID); + } + } + } + else { + // fill UVR using c2d + for (i=1; iValue(UV.X(),UV.Y()); + SMDS_MeshNode* N = meshDS->AddNode(P.X(), P.Y(), P.Z()); + meshDS->SetNodeOnFace(N, geomFaceID, UV.X(), UV.Y()); + NodesC.SetValue(i,nbv-nnn+j,N); + } + } + // add diagonal layers + for (i=1; iValue(u,v); + SMDS_MeshNode* N = meshDS->AddNode(P.X(), P.Y(), P.Z()); + meshDS->SetNodeOnFace(N, geomFaceID, u, v); + NodesC.SetValue(j,i+1,N); + } + } + // create faces + for (i=1; iAddFace(NodesC.Value(i,j), NodesC.Value(i+1,j), + NodesC.Value(i+1,j+1), NodesC.Value(i,j+1)); + if (F) meshDS->SetMeshElementOnShape(F, geomFaceID); + } + } + // TODO ??? + } // end Multiple Reduce implementation + else { // Simple Reduce (!MultipleReduce) + //========================================================= + if (nr == nl) { + if (nt < nb) { + // it is a base case => not shift quad + //ShiftQuad(quad,0,true); + } + else { + // we have to shift quad on 2 + ShiftQuad(quad,2,true); + } + } + else { + if (nl > nr) { + // we have to shift quad on 1 + ShiftQuad(quad,1,true); + } + else { + // we have to shift quad on 3 + ShiftQuad(quad,3,true); + } + } + + nb = quad->side[0]->NbPoints(); + nr = quad->side[1]->NbPoints(); + nt = quad->side[2]->NbPoints(); + nl = quad->side[3]->NbPoints(); + + // number of rows and columns + int nrows = nr - 1; // and also == nl - 1 + int ncol_top = nt - 1; + int ncol_bot = nb - 1; + int npair_top = ncol_top / 2; + // maximum number of bottom elements for "linear" simple reduce + int max_lin = ncol_top + npair_top * 2 * nrows; + // maximum number of bottom elements for "tree" simple reduce + //int max_tree = npair_top * pow(2, nrows + 1); + + //if (ncol_bot > max_tree) + // MultipleReduce = true; + + const vector& uv_eb = quad->side[0]->GetUVPtStruct(true,0); + const vector& uv_er = quad->side[1]->GetUVPtStruct(false,1); + const vector& uv_et = quad->side[2]->GetUVPtStruct(true,1); + const vector& uv_el = quad->side[3]->GetUVPtStruct(false,0); + + if (uv_eb.size() != nb || uv_er.size() != nr || uv_et.size() != nt || uv_el.size() != nl) + return error(COMPERR_BAD_INPUT_MESH); + + // arrays for normalized params + TColStd_SequenceOfReal npb, npr, npt, npl; + for (j = 0; j < nb; j++) { + npb.Append(uv_eb[j].normParam); + } + for (i = 0; i < nr; i++) { + npr.Append(uv_er[i].normParam); + } + for (j = 0; j < nt; j++) { + npt.Append(uv_et[j].normParam); + } + for (i = 0; i < nl; i++) { + npl.Append(uv_el[i].normParam); + } + + // We will ajust new points to this grid + if (!SetNormalizedGrid(aMesh, aShape, quad)) + return false; + + // TODO ??? + gp_XY a0 (uv_eb.front().u, uv_eb.front().v); + gp_XY a1 (uv_eb.back().u, uv_eb.back().v); + gp_XY a2 (uv_et.back().u, uv_et.back().v); + gp_XY a3 (uv_et.front().u, uv_et.front().v); + //========================================================= + + TColStd_SequenceOfInteger curr_base, next_base; + TColStd_SequenceOfReal curr_par_u, curr_par_v; + TColStd_SequenceOfReal next_par_u, next_par_v; + StdMeshers_Array2OfNode NodesBRD (1,nb, 1,nr); + for (j = 1; j <= nb; j++) { + NodesBRD.SetValue(j, 1, uv_eb[j - 1].node); // bottom + curr_base.Append(j); + next_base.Append(-1); + curr_par_u.Append(uv_eb[j-1].u); + curr_par_v.Append(uv_eb[j-1].v); + next_par_u.Append(0.); + next_par_v.Append(0.); + } + for (j = 1; j <= nt; j++) { + NodesBRD.SetValue(j, nr, uv_et[j - 1].node); // top + } + + int curr_base_len = nb; + int next_base_len = 0; + + if (ncol_bot > max_lin) { + // "tree" simple reduce 2->4->8->16->32->... + // + // .---------------.---------------.---------------.---------------. nr + // | \ | / | \ | / | + // | \ .-------.-------. / | \ .-------.-------. / | + // | | | | | | | | | + // .-------.-------.-------.-------.-------.-------.-------.-------. + // |\ | /|\ | /|\ | /|\ | /| + // | \.---.---./ | \.---.---./ | \.---.---./ | \.---.---./ | i + // | | | | | | | | | | | | | | | | | + // .---.---.---.---.---.---.---.---.---.---.---.---.---.---.---.---. + // |\ | /|\ | /|\ | /|\ | /|\ | /|\ | /|\ | /|\ | /| + // | .-.-. | .-.-. | .-.-. | .-.-. | .-.-. | .-.-. | .-.-. | .-.-. | + // | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | + // .-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. 1 + // 1 j nb + + for (i = 1; i < nr; i++) { // layer by layer + // left + NodesBRD.SetValue(1, i+1, uv_el[i].node); + next_base.SetValue(++next_base_len, 1); + // right + NodesBRD.SetValue(nb, i+1, uv_er[i].node); + + next_par_u.SetValue(next_base_len, uv_el[i].u); + next_par_v.SetValue(next_base_len, uv_el[i].v); + + // to stop reducing, if number of nodes reaches nt + int delta = curr_base_len - nt; + + //double du = uv_er[i].u - uv_el[i].u; + //double dv = uv_er[i].v - uv_el[i].v; + + // to calculate normalized parameter, we must know number of points in next layer + int nb_four = (curr_base_len - 1) / 4; + int nb_next = nb_four*2 + (curr_base_len - nb_four*4); + if (nb_next < nt) nb_next = nt; + + for (j = 1; j + 4 <= curr_base_len && delta > 0; j += 4, delta -= 2) { + // add one "HH": nodes a,b,c,d,e and faces 1,2,3,4,5,6 + // + // .-----a-----b i + 1 + // |\ 5 | 6 /| + // | \ | / | + // | c--d--e | + // |1 |2 |3 |4 | + // | | | | | + // .--.--.--.--. i + // + // j j+2 j+4 + + double u,v; + + // a (i + 1, j + 2) + const SMDS_MeshNode* Na; + next_base_len++; + next_base.SetValue(next_base_len, curr_base.Value(j + 2)); + if (i + 1 == nr) { // top + Na = uv_et[next_base_len - 1].node; + NodesBRD.SetValue(next_base.Value(next_base_len), i + 1, Na); + u = uv_et[next_base_len - 1].u; + v = uv_et[next_base_len - 1].v; + } + else { + //double norm_par = double(next_base_len - 1)/double(nb_next - 1); + //u = uv_el[i].u + du * norm_par; + //v = uv_el[i].v + dv * norm_par; + { + double rel = double(next_base_len - 1) * double(nt - 1) / double(nb_next - 1) + 1; + int nearest_node_j = (int)rel; + rel -= nearest_node_j; + int ij = (i + 1 - 1) * nt + (nearest_node_j - 1); + double u1 = quad->uv_grid[ij].u; + double v1 = quad->uv_grid[ij].v; + double u2 = quad->uv_grid[ij + 1].u; + double v2 = quad->uv_grid[ij + 1].v; + double duj = (u2 - u1) * rel; + double dvj = (v2 - v1) * rel; + u = u1 + duj; + v = v1 + dvj; + } + //u = uv_el[i].u + du*npb.Value(curr_base.Value(j + 2)); + //v = uv_el[i].v + dv*npb.Value(curr_base.Value(j + 2)); + gp_Pnt P = S->Value(u,v); + SMDS_MeshNode* Na1 = meshDS->AddNode(P.X(), P.Y(), P.Z()); + meshDS->SetNodeOnFace(Na1, geomFaceID, u, v); + NodesBRD.SetValue(next_base.Value(next_base_len), i + 1, Na1); + Na = Na1; + } + next_par_u.SetValue(next_base_len, u); + next_par_v.SetValue(next_base_len, v); + + // b (i + 1, j + 4) + const SMDS_MeshNode* Nb; + next_base_len++; + next_base.SetValue(next_base_len, curr_base.Value(j + 4)); + if (i + 1 == nr) { // top + Nb = uv_et[next_base_len - 1].node; + NodesBRD.SetValue(next_base.Value(next_base_len), i + 1, Nb); + u = uv_et[next_base_len - 1].u; + v = uv_et[next_base_len - 1].v; + } + else if (j + 4 == curr_base_len) { // right + Nb = NodesBRD.Value(next_base.Value(next_base_len), i + 1); + u = uv_er[i].u; + v = uv_er[i].v; + } + else { + //double norm_par = double(next_base_len - 1)/double(nb_next - 1); + //u = uv_el[i].u + du * norm_par; + //v = uv_el[i].v + dv * norm_par; + { + double rel = double(next_base_len - 1) * double(nt - 1) / double(nb_next - 1) + 1; + int nearest_node_j = (int)rel; + rel -= nearest_node_j; + int ij = (i + 1 - 1) * nt + (nearest_node_j - 1); + double u1 = quad->uv_grid[ij].u; + double v1 = quad->uv_grid[ij].v; + double u2 = quad->uv_grid[ij + 1].u; + double v2 = quad->uv_grid[ij + 1].v; + double duj = (u2 - u1) * rel; + double dvj = (v2 - v1) * rel; + u = u1 + duj; + v = v1 + dvj; + } + //u = uv_el[i].u + du*npb.Value(curr_base.Value(j + 4)); + //v = uv_el[i].v + dv*npb.Value(curr_base.Value(j + 4)); + gp_Pnt P = S->Value(u,v); + SMDS_MeshNode* Nb1 = meshDS->AddNode(P.X(), P.Y(), P.Z()); + meshDS->SetNodeOnFace(Nb1, geomFaceID, u, v); + NodesBRD.SetValue(next_base.Value(next_base_len), i + 1, Nb1); + Nb = Nb1; + } + next_par_u.SetValue(next_base_len, u); + next_par_v.SetValue(next_base_len, v); + + // c + u = (curr_par_u.Value(j + 2) + next_par_u.Value(next_base_len - 2)) / 2.0; + v = (curr_par_v.Value(j + 2) + next_par_v.Value(next_base_len - 2)) / 2.0; + gp_Pnt P = S->Value(u,v); + SMDS_MeshNode* Nc = meshDS->AddNode(P.X(), P.Y(), P.Z()); + meshDS->SetNodeOnFace(Nc, geomFaceID, u, v); + + // d + u = (curr_par_u.Value(j + 2) + next_par_u.Value(next_base_len - 1)) / 2.0; + v = (curr_par_v.Value(j + 2) + next_par_v.Value(next_base_len - 1)) / 2.0; + P = S->Value(u,v); + SMDS_MeshNode* Nd = meshDS->AddNode(P.X(), P.Y(), P.Z()); + meshDS->SetNodeOnFace(Nd, geomFaceID, u, v); + + // e + u = (curr_par_u.Value(j + 2) + next_par_u.Value(next_base_len)) / 2.0; + v = (curr_par_v.Value(j + 2) + next_par_v.Value(next_base_len)) / 2.0; + P = S->Value(u,v); + SMDS_MeshNode* Ne = meshDS->AddNode(P.X(), P.Y(), P.Z()); + meshDS->SetNodeOnFace(Ne, geomFaceID, u, v); + + // Faces + SMDS_MeshFace* F1 = myTool->AddFace(NodesBRD.Value(curr_base.Value(j + 0), i), + NodesBRD.Value(curr_base.Value(j + 1), i), + Nc, + NodesBRD.Value(next_base.Value(next_base_len - 2), i + 1)); + if (F1) meshDS->SetMeshElementOnShape(F1, geomFaceID); + + SMDS_MeshFace* F2 = myTool->AddFace(NodesBRD.Value(curr_base.Value(j + 1), i), + NodesBRD.Value(curr_base.Value(j + 2), i), + Nd, Nc); + if (F2) meshDS->SetMeshElementOnShape(F2, geomFaceID); + + SMDS_MeshFace* F3 = myTool->AddFace(NodesBRD.Value(curr_base.Value(j + 2), i), + NodesBRD.Value(curr_base.Value(j + 3), i), + Ne, Nd); + if (F3) meshDS->SetMeshElementOnShape(F3, geomFaceID); + + SMDS_MeshFace* F4 = myTool->AddFace(NodesBRD.Value(curr_base.Value(j + 3), i), + NodesBRD.Value(curr_base.Value(j + 4), i), + Nb, Ne); + if (F4) meshDS->SetMeshElementOnShape(F4, geomFaceID); + + SMDS_MeshFace* F5 = myTool->AddFace(Nc, Nd, Na, + NodesBRD.Value(next_base.Value(next_base_len - 2), i + 1)); + if (F5) meshDS->SetMeshElementOnShape(F5, geomFaceID); + + SMDS_MeshFace* F6 = myTool->AddFace(Nd, Ne, Nb, Na); + if (F6) meshDS->SetMeshElementOnShape(F6, geomFaceID); + } + + // not reduced side elements (if any) + for (; j < curr_base_len; j++) { + // f (i + 1, j + 1) + const SMDS_MeshNode* Nf; + double u,v; + next_base.SetValue(++next_base_len, curr_base.Value(j + 1)); + if (i + 1 == nr) { // top + Nf = uv_et[next_base_len - 1].node; + NodesBRD.SetValue(next_base.Value(next_base_len), i + 1, Nf); + u = uv_et[next_base_len - 1].u; + v = uv_et[next_base_len - 1].v; + } + else if (j + 1 == curr_base_len) { // right + Nf = NodesBRD.Value(next_base.Value(next_base_len), i + 1); + u = uv_er[i].u; + v = uv_er[i].v; + } + else { + //double norm_par = double(next_base_len - 1)/double(nb_next - 1); + //u = uv_el[i].u + du * norm_par; + //v = uv_el[i].v + dv * norm_par; + { + double rel = double(next_base_len - 1) * double(nt - 1) / double(nb_next - 1) + 1; + int nearest_node_j = (int)rel; + rel -= nearest_node_j; + int ij = (i + 1 - 1) * nt + (nearest_node_j - 1); + double u1 = quad->uv_grid[ij].u; + double v1 = quad->uv_grid[ij].v; + double u2 = quad->uv_grid[ij + 1].u; + double v2 = quad->uv_grid[ij + 1].v; + double duj = (u2 - u1) * rel; + double dvj = (v2 - v1) * rel; + u = u1 + duj; + v = v1 + dvj; + } + //u = uv_el[i].u + du*npb.Value(curr_base.Value(j + 1)); + //v = uv_el[i].v + dv*npb.Value(curr_base.Value(j + 1)); + gp_Pnt P = S->Value(u,v); + SMDS_MeshNode* Nf1 = meshDS->AddNode(P.X(), P.Y(), P.Z()); + meshDS->SetNodeOnFace(Nf1, geomFaceID, u, v); + NodesBRD.SetValue(next_base.Value(next_base_len), i + 1, Nf1); + Nf = Nf1; + } + next_par_u.SetValue(next_base_len, u); + next_par_v.SetValue(next_base_len, v); + SMDS_MeshFace* F1 = myTool->AddFace(NodesBRD.Value(curr_base.Value(j), i), + NodesBRD.Value(curr_base.Value(j + 1), i), + NodesBRD.Value(next_base.Value(next_base_len), i + 1), + NodesBRD.Value(next_base.Value(next_base_len - 1), i + 1)); + if (F1) meshDS->SetMeshElementOnShape(F1, geomFaceID); + } + + curr_base_len = next_base_len; + curr_base = next_base; + curr_par_u = next_par_u; + curr_par_v = next_par_v; + next_base_len = 0; + } + } // end "tree" simple reduce + else { + // "linear" simple reduce 4->8->12->16 (3 steps) + // + // .---------------.---------------.---------------.---------------. nr + // | \ | / | \ | / | + // | \ .-------.-------. / | \ .-------.-------. / | + // | | | | | | | | | + // .-------.-------.-------.-------.-------.-------.-------.-------. + // | / \ | / \ | / \ | / \ | + // | / \.----.----./ \ | / \.----.----./ \ | i + // | / | | | \ | / | | | \ | + // .-----.----.----.----.----.-----.-----.----.----.----.----.-----. + // | / / \ | / \ \ | / / \ | / \ \ | + // | / / .-.-. \ \ | / / .-.-. \ \ | + // | / / / | \ \ \ | / / / | \ \ \ | + // .---.---.---.---.---.---.---.---.---.---.---.---.---.---.---.---. 1 + // 1 j nb + + // nt = 5, nb = 7, nr = 4 + //int delta_all = 2; + //int delta_one_col = 6; + //int nb_col = 0; + //int remainder = 2; + //if (remainder > 0) nb_col++; + //nb_col = 1; + //int free_left = 1; + //free_left += 2; + //int free_middle = 4; + + int delta_all = nb - nt; + int delta_one_col = (nr - 1) * 2; + int nb_col = delta_all / delta_one_col; + int remainder = delta_all - nb_col * delta_one_col; + if (remainder > 0) { + nb_col++; + } + int free_left = ((nt - 1) - nb_col * 2) / 2; + free_left += nr - 2; + int free_middle = (nr - 2) * 2; + if (remainder > 0 && nb_col == 1) { + int nb_rows_short_col = remainder / 2; + int nb_rows_thrown = (nr - 1) - nb_rows_short_col; + free_left -= nb_rows_thrown; + } + + // nt = 5, nb = 17, nr = 4 + //int delta_all = 12; + //int delta_one_col = 6; + //int nb_col = 2; + //int remainder = 0; + //int free_left = 2; + //int free_middle = 4; + + for (i = 1; i < nr; i++, free_middle -= 2, free_left -= 1) { // layer by layer + // left + NodesBRD.SetValue(1, i+1, uv_el[i].node); + next_base.SetValue(++next_base_len, 1); + // right + NodesBRD.SetValue(nb, i+1, uv_er[i].node); + + // left + next_par_u.SetValue(next_base_len, uv_el[i].u); + next_par_v.SetValue(next_base_len, uv_el[i].v); + + // to calculate normalized parameter, we must know number of points in next layer + int nb_next = curr_base_len - nb_col * 2; + if (remainder > 0 && i > remainder / 2) + // take into account short "column" + nb_next += 2; + if (nb_next < nt) nb_next = nt; + + // not reduced left elements + for (j = 1; j <= free_left; j++) { + // f (i + 1, j + 1) + const SMDS_MeshNode* Nf; + double u,v; + next_base.SetValue(++next_base_len, curr_base.Value(j + 1)); + if (i + 1 == nr) { // top + Nf = uv_et[next_base_len - 1].node; + NodesBRD.SetValue(next_base.Value(next_base_len), i + 1, Nf); + u = uv_et[next_base_len - 1].u; + v = uv_et[next_base_len - 1].v; + } + else { + { + double rel = double(next_base_len - 1) * double(nt - 1) / double(nb_next - 1) + 1; + int nearest_node_j = (int)rel; + rel -= nearest_node_j; + int ij = (i + 1 - 1) * nt + (nearest_node_j - 1); + double u1 = quad->uv_grid[ij].u; + double v1 = quad->uv_grid[ij].v; + double u2 = quad->uv_grid[ij + 1].u; + double v2 = quad->uv_grid[ij + 1].v; + double duj = (u2 - u1) * rel; + double dvj = (v2 - v1) * rel; + u = u1 + duj; + v = v1 + dvj; + } + gp_Pnt P = S->Value(u,v); + SMDS_MeshNode* Nf1 = meshDS->AddNode(P.X(), P.Y(), P.Z()); + meshDS->SetNodeOnFace(Nf1, geomFaceID, u, v); + NodesBRD.SetValue(next_base.Value(next_base_len), i + 1, Nf1); + Nf = Nf1; + } + next_par_u.SetValue(next_base_len, u); + next_par_v.SetValue(next_base_len, v); + SMDS_MeshFace* F1 = myTool->AddFace(NodesBRD.Value(curr_base.Value(j), i), + NodesBRD.Value(curr_base.Value(j + 1), i), + NodesBRD.Value(next_base.Value(next_base_len), i + 1), + NodesBRD.Value(next_base.Value(next_base_len - 1), i + 1)); + if (F1) meshDS->SetMeshElementOnShape(F1, geomFaceID); + } + + for (int icol = 1; icol <= nb_col; icol++) { + + if (remainder > 0 && icol == nb_col && i > remainder / 2) + // stop short "column" + break; + + // add one "HH": nodes a,b,c,d,e and faces 1,2,3,4,5,6 + // + // .-----a-----b i + 1 + // |\ 5 | 6 /| + // | \ | / | + // | c--d--e | + // |1 |2 |3 |4 | + // | | | | | + // .--.--.--.--. i + // + // j j+2 j+4 + + double u,v; + + // a (i + 1, j + 2) + const SMDS_MeshNode* Na; + next_base_len++; + next_base.SetValue(next_base_len, curr_base.Value(j + 2)); + if (i + 1 == nr) { // top + Na = uv_et[next_base_len - 1].node; + NodesBRD.SetValue(next_base.Value(next_base_len), i + 1, Na); + u = uv_et[next_base_len - 1].u; + v = uv_et[next_base_len - 1].v; + } + else { + { + double rel = double(next_base_len - 1) * double(nt - 1) / double(nb_next - 1) + 1; + int nearest_node_j = (int)rel; + rel -= nearest_node_j; + int ij = (i + 1 - 1) * nt + (nearest_node_j - 1); + double u1 = quad->uv_grid[ij].u; + double v1 = quad->uv_grid[ij].v; + double u2 = quad->uv_grid[ij + 1].u; + double v2 = quad->uv_grid[ij + 1].v; + double duj = (u2 - u1) * rel; + double dvj = (v2 - v1) * rel; + u = u1 + duj; + v = v1 + dvj; + } + gp_Pnt P = S->Value(u,v); + SMDS_MeshNode* Na1 = meshDS->AddNode(P.X(), P.Y(), P.Z()); + meshDS->SetNodeOnFace(Na1, geomFaceID, u, v); + NodesBRD.SetValue(next_base.Value(next_base_len), i + 1, Na1); + Na = Na1; + } + next_par_u.SetValue(next_base_len, u); + next_par_v.SetValue(next_base_len, v); + + // b (i + 1, j + 4) + const SMDS_MeshNode* Nb; + next_base_len++; + next_base.SetValue(next_base_len, curr_base.Value(j + 4)); + if (i + 1 == nr) { // top + Nb = uv_et[next_base_len - 1].node; + NodesBRD.SetValue(next_base.Value(next_base_len), i + 1, Nb); + u = uv_et[next_base_len - 1].u; + v = uv_et[next_base_len - 1].v; + } + else if (j + 4 == curr_base_len) { // right + Nb = NodesBRD.Value(next_base.Value(next_base_len), i + 1); + u = uv_er[i].u; + v = uv_er[i].v; + } + else { + { + double rel = double(next_base_len - 1) * double(nt - 1) / double(nb_next - 1) + 1; + int nearest_node_j = (int)rel; + rel -= nearest_node_j; + int ij = (i + 1 - 1) * nt + (nearest_node_j - 1); + double u1 = quad->uv_grid[ij].u; + double v1 = quad->uv_grid[ij].v; + double u2 = quad->uv_grid[ij + 1].u; + double v2 = quad->uv_grid[ij + 1].v; + double duj = (u2 - u1) * rel; + double dvj = (v2 - v1) * rel; + u = u1 + duj; + v = v1 + dvj; + } + gp_Pnt P = S->Value(u,v); + SMDS_MeshNode* Nb1 = meshDS->AddNode(P.X(), P.Y(), P.Z()); + meshDS->SetNodeOnFace(Nb1, geomFaceID, u, v); + NodesBRD.SetValue(next_base.Value(next_base_len), i + 1, Nb1); + Nb = Nb1; + } + next_par_u.SetValue(next_base_len, u); + next_par_v.SetValue(next_base_len, v); + + // c + u = (curr_par_u.Value(j + 2) + next_par_u.Value(next_base_len - 2)) / 2.0; + v = (curr_par_v.Value(j + 2) + next_par_v.Value(next_base_len - 2)) / 2.0; + gp_Pnt P = S->Value(u,v); + SMDS_MeshNode* Nc = meshDS->AddNode(P.X(), P.Y(), P.Z()); + meshDS->SetNodeOnFace(Nc, geomFaceID, u, v); + + // d + u = (curr_par_u.Value(j + 2) + next_par_u.Value(next_base_len - 1)) / 2.0; + v = (curr_par_v.Value(j + 2) + next_par_v.Value(next_base_len - 1)) / 2.0; + P = S->Value(u,v); + SMDS_MeshNode* Nd = meshDS->AddNode(P.X(), P.Y(), P.Z()); + meshDS->SetNodeOnFace(Nd, geomFaceID, u, v); + + // e + u = (curr_par_u.Value(j + 2) + next_par_u.Value(next_base_len)) / 2.0; + v = (curr_par_v.Value(j + 2) + next_par_v.Value(next_base_len)) / 2.0; + P = S->Value(u,v); + SMDS_MeshNode* Ne = meshDS->AddNode(P.X(), P.Y(), P.Z()); + meshDS->SetNodeOnFace(Ne, geomFaceID, u, v); + + // Faces + SMDS_MeshFace* F1 = myTool->AddFace(NodesBRD.Value(curr_base.Value(j + 0), i), + NodesBRD.Value(curr_base.Value(j + 1), i), + Nc, + NodesBRD.Value(next_base.Value(next_base_len - 2), i + 1)); + if (F1) meshDS->SetMeshElementOnShape(F1, geomFaceID); + + SMDS_MeshFace* F2 = myTool->AddFace(NodesBRD.Value(curr_base.Value(j + 1), i), + NodesBRD.Value(curr_base.Value(j + 2), i), + Nd, Nc); + if (F2) meshDS->SetMeshElementOnShape(F2, geomFaceID); + + SMDS_MeshFace* F3 = myTool->AddFace(NodesBRD.Value(curr_base.Value(j + 2), i), + NodesBRD.Value(curr_base.Value(j + 3), i), + Ne, Nd); + if (F3) meshDS->SetMeshElementOnShape(F3, geomFaceID); + + SMDS_MeshFace* F4 = myTool->AddFace(NodesBRD.Value(curr_base.Value(j + 3), i), + NodesBRD.Value(curr_base.Value(j + 4), i), + Nb, Ne); + if (F4) meshDS->SetMeshElementOnShape(F4, geomFaceID); + + SMDS_MeshFace* F5 = myTool->AddFace(Nc, Nd, Na, + NodesBRD.Value(next_base.Value(next_base_len - 2), i + 1)); + if (F5) meshDS->SetMeshElementOnShape(F5, geomFaceID); + + SMDS_MeshFace* F6 = myTool->AddFace(Nd, Ne, Nb, Na); + if (F6) meshDS->SetMeshElementOnShape(F6, geomFaceID); + + j += 4; + + // not reduced middle elements + if (icol < nb_col) { + if (remainder > 0 && icol == nb_col - 1 && i > remainder / 2) + // pass middle elements before stopped short "column" + break; + + int free_add = free_middle; + if (remainder > 0 && icol == nb_col - 1) + // next "column" is short + free_add -= (nr - 1) - (remainder / 2); + + for (int imiddle = 1; imiddle <= free_add; imiddle++) { + // f (i + 1, j + imiddle) + const SMDS_MeshNode* Nf; + double u,v; + next_base.SetValue(++next_base_len, curr_base.Value(j + imiddle)); + if (i + 1 == nr) { // top + Nf = uv_et[next_base_len - 1].node; + NodesBRD.SetValue(next_base.Value(next_base_len), i + 1, Nf); + u = uv_et[next_base_len - 1].u; + v = uv_et[next_base_len - 1].v; + } + else if (j + imiddle == curr_base_len) { // right + Nf = NodesBRD.Value(next_base.Value(next_base_len), i + 1); + u = uv_er[i].u; + v = uv_er[i].v; + } + else { + { + double rel = double(next_base_len - 1) * double(nt - 1) / double(nb_next - 1) + 1; + int nearest_node_j = (int)rel; + rel -= nearest_node_j; + int ij = (i + 1 - 1) * nt + (nearest_node_j - 1); + double u1 = quad->uv_grid[ij].u; + double v1 = quad->uv_grid[ij].v; + double u2 = quad->uv_grid[ij + 1].u; + double v2 = quad->uv_grid[ij + 1].v; + double duj = (u2 - u1) * rel; + double dvj = (v2 - v1) * rel; + u = u1 + duj; + v = v1 + dvj; + } + gp_Pnt P = S->Value(u,v); + SMDS_MeshNode* Nf1 = meshDS->AddNode(P.X(), P.Y(), P.Z()); + meshDS->SetNodeOnFace(Nf1, geomFaceID, u, v); + NodesBRD.SetValue(next_base.Value(next_base_len), i + 1, Nf1); + Nf = Nf1; + } + next_par_u.SetValue(next_base_len, u); + next_par_v.SetValue(next_base_len, v); + SMDS_MeshFace* F1 = myTool->AddFace(NodesBRD.Value(curr_base.Value(j - 1 + imiddle), i), + NodesBRD.Value(curr_base.Value(j + imiddle), i), + NodesBRD.Value(next_base.Value(next_base_len), i + 1), + NodesBRD.Value(next_base.Value(next_base_len - 1), i + 1)); + if (F1) meshDS->SetMeshElementOnShape(F1, geomFaceID); + } + j += free_add; + } + } + + // not reduced right elements + for (; j < curr_base_len; j++) { + // f (i + 1, j + 1) + const SMDS_MeshNode* Nf; + double u,v; + next_base.SetValue(++next_base_len, curr_base.Value(j + 1)); + if (i + 1 == nr) { // top + Nf = uv_et[next_base_len - 1].node; + NodesBRD.SetValue(next_base.Value(next_base_len), i + 1, Nf); + u = uv_et[next_base_len - 1].u; + v = uv_et[next_base_len - 1].v; + } + else if (j + 1 == curr_base_len) { // right + Nf = NodesBRD.Value(next_base.Value(next_base_len), i + 1); + u = uv_er[i].u; + v = uv_er[i].v; + } + else { + { + double rel = double(next_base_len - 1) * double(nt - 1) / double(nb_next - 1) + 1; + int nearest_node_j = (int)rel; + rel -= nearest_node_j; + int ij = (i + 1 - 1) * nt + (nearest_node_j - 1); + double u1 = quad->uv_grid[ij].u; + double v1 = quad->uv_grid[ij].v; + double u2 = quad->uv_grid[ij + 1].u; + double v2 = quad->uv_grid[ij + 1].v; + double duj = (u2 - u1) * rel; + double dvj = (v2 - v1) * rel; + u = u1 + duj; + v = v1 + dvj; + } + gp_Pnt P = S->Value(u,v); + SMDS_MeshNode* Nf1 = meshDS->AddNode(P.X(), P.Y(), P.Z()); + meshDS->SetNodeOnFace(Nf1, geomFaceID, u, v); + NodesBRD.SetValue(next_base.Value(next_base_len), i + 1, Nf1); + Nf = Nf1; + } + next_par_u.SetValue(next_base_len, u); + next_par_v.SetValue(next_base_len, v); + SMDS_MeshFace* F1 = myTool->AddFace(NodesBRD.Value(curr_base.Value(j), i), + NodesBRD.Value(curr_base.Value(j + 1), i), + NodesBRD.Value(next_base.Value(next_base_len), i + 1), + NodesBRD.Value(next_base.Value(next_base_len - 1), i + 1)); + if (F1) meshDS->SetMeshElementOnShape(F1, geomFaceID); + } + + curr_base_len = next_base_len; + curr_base = next_base; + curr_par_u = next_par_u; + curr_par_v = next_par_v; + next_base_len = 0; + } + } // end "linear" simple reduce + } // end Simple Reduce implementation + + bool isOk = true; + return isOk; +} diff --git a/src/StdMeshers/StdMeshers_Quadrangle_2D.hxx b/src/StdMeshers/StdMeshers_Quadrangle_2D.hxx index 74c64f6f0..56741ec76 100644 --- a/src/StdMeshers/StdMeshers_Quadrangle_2D.hxx +++ b/src/StdMeshers/StdMeshers_Quadrangle_2D.hxx @@ -19,19 +19,20 @@ // // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // - // SMESH SMESH : implementaion of SMESH idl descriptions // File : StdMeshers_Quadrangle_2D.hxx // Moved here from SMESH_Quadrangle_2D.hxx // Author : Paul RASCLE, EDF // Module : SMESH // $Header$ -// + #ifndef _SMESH_QUADRANGLE_2D_HXX_ #define _SMESH_QUADRANGLE_2D_HXX_ #include "SMESH_StdMeshers.hxx" +#include "StdMeshers_QuadrangleParams.hxx" + #include "SMESH_2D_Algo.hxx" #include "Utils_SALOME_Exception.hxx" @@ -120,6 +121,10 @@ protected: const TopoDS_Face& F, const TopoDS_Edge& E, double first, double last, int nb_segm); + bool ComputeReduced (SMESH_Mesh& aMesh, + const TopoDS_Shape& aShape, + FaceQuadStruct* quad); + // true if QuadranglePreference hypothesis is assigned that forces // construction of quadrangles if the number of nodes on opposite edges // is not the same in the case where the global number of nodes on edges @@ -130,6 +135,8 @@ protected: int myTriaVertexID; + StdMeshers_QuadType myQuadType; + SMESH_MesherHelper* myTool; // tool for working with quadratic elements }; diff --git a/src/StdMeshers/StdMeshers_Regular_1D.cxx b/src/StdMeshers/StdMeshers_Regular_1D.cxx index 827399030..6771e53ed 100644 --- a/src/StdMeshers/StdMeshers_Regular_1D.cxx +++ b/src/StdMeshers/StdMeshers_Regular_1D.cxx @@ -731,6 +731,9 @@ bool StdMeshers_Regular_1D::computeInternalParameters(SMESH_Mesh & theMesh, double a1 = _value[ BEG_LENGTH_IND ]; double an = _value[ END_LENGTH_IND ]; double q = ( theLength - a1 ) / ( theLength - an ); + if ( q < theLength/1e6 || 1.01*theLength < a1 + an) + return error ( SMESH_Comment("Invalid segment lengths (")< numeric_limits::min() ? ( 1+( an-a1 )/q ) : ( 1+theLength/a1 )); @@ -941,6 +947,25 @@ bool StdMeshers_Regular_1D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape & t if (!idFirst || !idLast) return error( COMPERR_BAD_INPUT_MESH, "No node on vertex"); + // remove elements created by e.g. patern mapping (PAL21999) + // CLEAN event is incorrectly ptopagated seemingly due to Propagation hyp + // so TEMPORARY solution is to clean the submesh manually + //theMesh.GetSubMesh(theShape)->ComputeStateEngine( SMESH_subMesh::CLEAN ); + if (SMESHDS_SubMesh * subMeshDS = meshDS->MeshElements(theShape)) + { + SMDS_ElemIteratorPtr ite = subMeshDS->GetElements(); + while (ite->more()) + meshDS->RemoveFreeElement(ite->next(), subMeshDS); + SMDS_NodeIteratorPtr itn = subMeshDS->GetNodes(); + while (itn->more()) { + const SMDS_MeshNode * node = itn->next(); + if ( node->NbInverseElements() == 0 ) + meshDS->RemoveFreeNode(node, subMeshDS); + else + meshDS->RemoveNode(node); + } + } + if (!Curve.IsNull()) { list< double > params; @@ -982,7 +1007,6 @@ bool StdMeshers_Regular_1D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape & t parLast = f; } */ - for (list::iterator itU = params.begin(); itU != params.end(); itU++) { double param = *itU; gp_Pnt P = Curve->Value(param); diff --git a/src/StdMeshersGUI/Makefile.am b/src/StdMeshersGUI/Makefile.am index e47134592..9d9875d14 100644 --- a/src/StdMeshersGUI/Makefile.am +++ b/src/StdMeshersGUI/Makefile.am @@ -16,13 +16,12 @@ # # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com # - # SMESH StdMeshersGUI : GUI for StdMeshers plugin # File : Makefile.in # Author : Julia DOROVSKIKH # Modified by : Alexander BORODIN (OCN) - autotools usage # Module : SMESH -# + include $(top_srcdir)/adm_local/unix/make_common_starter.am # header files @@ -33,12 +32,14 @@ salomeinclude_HEADERS = \ StdMeshersGUI_DistrTable.h \ StdMeshersGUI_NbSegmentsCreator.h \ StdMeshersGUI_ObjectReferenceParamWdg.h \ + StdMeshersGUI_QuadrangleParamWdg.h \ StdMeshersGUI_LayerDistributionParamWdg.h \ StdMeshersGUI_FixedPointsParamWdg.h \ StdMeshersGUI_SubShapeSelectorWdg.h # Libraries targets lib_LTLIBRARIES = libStdMeshersGUI.la + dist_libStdMeshersGUI_la_SOURCES = \ StdMeshersGUI.cxx \ StdMeshersGUI_StdHypothesisCreator.cxx \ @@ -46,6 +47,7 @@ dist_libStdMeshersGUI_la_SOURCES = \ StdMeshersGUI_DistrTable.cxx \ StdMeshersGUI_NbSegmentsCreator.cxx \ StdMeshersGUI_ObjectReferenceParamWdg.cxx \ + StdMeshersGUI_QuadrangleParamWdg.cxx \ StdMeshersGUI_LayerDistributionParamWdg.cxx \ StdMeshersGUI_FixedPointsParamWdg.cxx \ StdMeshersGUI_SubShapeSelectorWdg.cxx @@ -56,6 +58,7 @@ MOC_FILES = \ StdMeshersGUI_DistrTable_moc.cxx \ StdMeshersGUI_NbSegmentsCreator_moc.cxx \ StdMeshersGUI_ObjectReferenceParamWdg_moc.cxx \ + StdMeshersGUI_QuadrangleParamWdg_moc.cxx \ StdMeshersGUI_LayerDistributionParamWdg_moc.cxx \ StdMeshersGUI_FixedPointsParamWdg_moc.cxx \ StdMeshersGUI_SubShapeSelectorWdg_moc.cxx diff --git a/src/StdMeshersGUI/StdMeshersGUI_NbSegmentsCreator.h b/src/StdMeshersGUI/StdMeshersGUI_NbSegmentsCreator.h index f50b19433..a66a82552 100644 --- a/src/StdMeshersGUI/StdMeshersGUI_NbSegmentsCreator.h +++ b/src/StdMeshersGUI/StdMeshersGUI_NbSegmentsCreator.h @@ -92,7 +92,7 @@ private: QLabel *myLScale, *myLTable, *myLExpr, *myInfo; QGridLayout* myGroupLayout; int myTableRow, myPreviewRow; - QRadioButton* myCutNeg; + //QRadioButton* myCutNeg; QGroupBox* myReversedEdgesBox; StdMeshersGUI_SubShapeSelectorWdg* myDirectionWidget; diff --git a/src/StdMeshersGUI/StdMeshersGUI_QuadrangleParamWdg.cxx b/src/StdMeshersGUI/StdMeshersGUI_QuadrangleParamWdg.cxx new file mode 100644 index 000000000..ccb38c670 --- /dev/null +++ b/src/StdMeshersGUI/StdMeshersGUI_QuadrangleParamWdg.cxx @@ -0,0 +1,100 @@ +// Copyright (C) 2007-2010 CEA/DEN, EDF R&D, OPEN CASCADE +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// +// File : StdMeshersGUI_QuadrangleParamWdg.cxx +// Author : Open CASCADE S.A.S. (jfa) +// SMESH includes + +#include "StdMeshersGUI_QuadrangleParamWdg.h" + +#include "SMESHGUI.h" + +#include "SUIT_ResourceMgr.h" + +// Qt includes +#include +#include +#include +#include + +// IDL includes +#include +#include CORBA_CLIENT_HEADER(SMESH_BasicHypothesis) + +#define SPACING 6 +#define MARGIN 0 + +//================================================================================ +// function : Constructor +// purpose : +//================================================================================ +StdMeshersGUI_QuadrangleParamWdg::StdMeshersGUI_QuadrangleParamWdg (QWidget * parent) + : QWidget(parent), + myType(0) +{ + myType = new QButtonGroup (this); + + QGridLayout* typeLay = new QGridLayout( this ); + + typeLay->setMargin(MARGIN); + typeLay->setSpacing(SPACING); + + QString aTypeKey ("SMESH_QUAD_TYPE_%1"); + QString aPictKey ("ICON_StdMeshers_Quadrangle_Params_%1"); + + int itype = 0; + for (; itype < int(StdMeshers::QUAD_NB_TYPES); itype++) { + QRadioButton* rbi = new QRadioButton (tr(aTypeKey.arg(itype).toLatin1()), this); + QPixmap pmi (SMESHGUI::resourceMgr()->loadPixmap("SMESH", tr(aPictKey.arg(itype).toLatin1()))); + QLabel* pli = new QLabel (this); + pli->setPixmap(pmi); + typeLay->addWidget(rbi, itype, 0, 1, 1); + typeLay->addWidget(pli, itype, 1, 1, 1); + myType->addButton(rbi, itype); + } + myType->button(0)->setChecked(true); + + setLayout(typeLay); + setMinimumWidth(300); +} + +//================================================================================ +// function : Destructor +// purpose : +//================================================================================ +StdMeshersGUI_QuadrangleParamWdg::~StdMeshersGUI_QuadrangleParamWdg() +{ +} + +//================================================================================= +// function : SetType +// purpose : +//================================================================================= +void StdMeshersGUI_QuadrangleParamWdg::SetType (int theType) +{ + myType->button(theType)->setChecked(true); +} + +//================================================================================= +// function : GetType +// purpose : +//================================================================================= +int StdMeshersGUI_QuadrangleParamWdg::GetType() +{ + return myType->checkedId(); +} diff --git a/src/StdMeshersGUI/StdMeshersGUI_QuadrangleParamWdg.h b/src/StdMeshersGUI/StdMeshersGUI_QuadrangleParamWdg.h new file mode 100644 index 000000000..2d5abdc45 --- /dev/null +++ b/src/StdMeshersGUI/StdMeshersGUI_QuadrangleParamWdg.h @@ -0,0 +1,49 @@ +// Copyright (C) 2007-2010 CEA/DEN, EDF R&D, OPEN CASCADE +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// +// File : StdMeshersGUI_QuadrangleParamWdg.h +// Author : Open CASCADE S.A.S. (jfa) + +#ifndef STDMESHERSGUI_QUADRANGLEPARAMWDG_H +#define STDMESHERSGUI_QUADRANGLEPARAMWDG_H + +// SMESH includes +#include "SMESH_StdMeshersGUI.hxx" + +// Qt includes +#include + +class QButtonGroup; + +class STDMESHERSGUI_EXPORT StdMeshersGUI_QuadrangleParamWdg : public QWidget +{ + Q_OBJECT + +public: + StdMeshersGUI_QuadrangleParamWdg (QWidget* parent = 0); + ~StdMeshersGUI_QuadrangleParamWdg(); + + void SetType (int theType); + int GetType (); + +private: + // Quadranle preference, Triangle preference, Reduced + QButtonGroup* myType; +}; + +#endif // STDMESHERSGUI_QUADRANGLEPARAMWDG_H diff --git a/src/StdMeshersGUI/StdMeshersGUI_StdHypothesisCreator.cxx b/src/StdMeshersGUI/StdMeshersGUI_StdHypothesisCreator.cxx index 156f2133e..3e8d13ee2 100644 --- a/src/StdMeshersGUI/StdMeshersGUI_StdHypothesisCreator.cxx +++ b/src/StdMeshersGUI/StdMeshersGUI_StdHypothesisCreator.cxx @@ -19,23 +19,26 @@ // // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // +// File : StdMeshersGUI_StdHypothesisCreator.cxx +// Author : Alexander SOLOVYOV, Open CASCADE S.A.S. +// SMESH includes -// File : StdMeshersGUI_StdHypothesisCreator.cxx -// Author : Alexander SOLOVYOV, Open CASCADE S.A.S. -// SMESH includes -// #include "StdMeshersGUI_StdHypothesisCreator.h" #include #include #include #include + #include #include -#include "StdMeshersGUI_ObjectReferenceParamWdg.h" + +#include "StdMeshersGUI_FixedPointsParamWdg.h" #include "StdMeshersGUI_LayerDistributionParamWdg.h" +#include "StdMeshersGUI_ObjectReferenceParamWdg.h" +#include "StdMeshersGUI_QuadrangleParamWdg.h" #include "StdMeshersGUI_SubShapeSelectorWdg.h" -#include "StdMeshersGUI_FixedPointsParamWdg.h" + #include // SALOME GUI includes @@ -387,9 +390,11 @@ bool StdMeshersGUI_StdHypothesisCreator::checkParams( QString& msg ) const } else if ( hypType() == "QuadrangleParams" ) { - StdMeshersGUI_SubShapeSelectorWdg* w = - widget< StdMeshersGUI_SubShapeSelectorWdg >( 0 ); - ok = ( w->GetListSize() > 0 ); + //StdMeshersGUI_SubShapeSelectorWdg* w = + // widget< StdMeshersGUI_SubShapeSelectorWdg >( 0 ); + //ok = ( w->GetListSize() > 0 ); + //StdMeshersGUI_QuadrangleParamWdg* w = + // widget< StdMeshersGUI_QuadrangleParamWdg >( 1 ); } return ok; } @@ -608,14 +613,17 @@ QString StdMeshersGUI_StdHypothesisCreator::storeParams() const { StdMeshers::StdMeshers_QuadrangleParams_var h = StdMeshers::StdMeshers_QuadrangleParams::_narrow( hypothesis() ); - StdMeshersGUI_SubShapeSelectorWdg* w = + StdMeshersGUI_SubShapeSelectorWdg* w1 = widget< StdMeshersGUI_SubShapeSelectorWdg >( 0 ); - if (w) { - if( w->GetListSize() > 0 ) { - h->SetTriaVertex( w->GetListOfIDs()[0] ); // getlist must be called once - const char * entry = w->GetMainShapeEntry(); - h->SetObjectEntry( entry ); + StdMeshersGUI_QuadrangleParamWdg* w2 = + widget< StdMeshersGUI_QuadrangleParamWdg >( 1 ); + if (w1 && w2) { + if (w1->GetListSize() > 0) { + h->SetTriaVertex(w1->GetListOfIDs()[0]); // getlist must be called once + const char * entry = w1->GetMainShapeEntry(); + h->SetObjectEntry(entry); } + h->SetQuadType(StdMeshers::QuadType(w2->GetType())); } } } @@ -984,13 +992,13 @@ bool StdMeshersGUI_StdHypothesisCreator::stdParams( ListOfStdParams& p ) const customWidgets()->append( newObjRefParamWdg( filterForShapeOfDim( 0 ), h->GetTargetVertex( 2 ))); } - else if( hypType()=="QuadrangleParams" ) + else if (hypType() == "QuadrangleParams") { StdMeshers::StdMeshers_QuadrangleParams_var h = - StdMeshers::StdMeshers_QuadrangleParams::_narrow( hyp ); + StdMeshers::StdMeshers_QuadrangleParams::_narrow(hyp); - item.myName = tr( "SMESH_BASE_VERTEX" ); - p.append( item ); + item.myName = tr("SMESH_BASE_VERTEX"); + p.append(item); StdMeshersGUI_SubShapeSelectorWdg* aDirectionWidget = new StdMeshersGUI_SubShapeSelectorWdg(); @@ -998,21 +1006,32 @@ bool StdMeshersGUI_StdHypothesisCreator::stdParams( ListOfStdParams& p ) const aDirectionWidget->SetSubShType(TopAbs_VERTEX); QString anEntry = SMESHGUI_GenericHypothesisCreator::getShapeEntry(); QString aMainEntry = SMESHGUI_GenericHypothesisCreator::getMainShapeEntry(); - if ( anEntry == "" ) + if (anEntry == "") anEntry = h->GetObjectEntry(); - aDirectionWidget->SetGeomShapeEntry( anEntry ); - aDirectionWidget->SetMainShapeEntry( aMainEntry ); - if ( !isCreation() ) { + aDirectionWidget->SetGeomShapeEntry(anEntry); + aDirectionWidget->SetMainShapeEntry(aMainEntry); + if (!isCreation()) { SMESH::long_array_var aVec = new SMESH::long_array; int vertID = h->GetTriaVertex(); - if(vertID>0) { + if (vertID > 0) { aVec->length(1); aVec[0] = vertID; - aDirectionWidget->SetListOfIDs( aVec ); + aDirectionWidget->SetListOfIDs(aVec); } } - aDirectionWidget->showPreview( true ); - customWidgets()->append ( aDirectionWidget ); + aDirectionWidget->showPreview(true); + + item.myName = tr("SMESH_QUAD_TYPE"); + p.append(item); + + StdMeshersGUI_QuadrangleParamWdg* aTypeWidget = + new StdMeshersGUI_QuadrangleParamWdg(); + if (!isCreation()) { + aTypeWidget->SetType(int(h->GetQuadType())); + } + + customWidgets()->append(aDirectionWidget); + customWidgets()->append(aTypeWidget); } else res = false; @@ -1217,6 +1236,13 @@ bool StdMeshersGUI_StdHypothesisCreator::getParamFromCustomWidget( StdParam & pa param.myValue = w->GetValue(); return true; } + if ( widget->inherits( "StdMeshersGUI_QuadrangleParamWdg" )) + { + //const StdMeshersGUI_QuadrangleParamWdg * w = + // static_cast( widget ); + param.myValue = "QuadType"; + return true; + } if ( widget->inherits( "StdMeshersGUI_FixedPointsParamWdg" )) { const StdMeshersGUI_FixedPointsParamWdg * w = diff --git a/src/StdMeshersGUI/StdMeshers_images.ts b/src/StdMeshersGUI/StdMeshers_images.ts index da9130846..927a4c09b 100644 --- a/src/StdMeshersGUI/StdMeshers_images.ts +++ b/src/StdMeshersGUI/StdMeshers_images.ts @@ -89,6 +89,10 @@ ICON_DLG_PROJECTION_SOURCE_3D mesh_hypo_source_3d.png + + ICON_DLG_QUADRANGLE_PARAMS + mesh_hypo_length.png + ICON_DLG_SEGMENT_LENGTH_AROUND_VERTEX mesh_hypo_length.png @@ -241,9 +245,28 @@ ICON_SMESH_TREE_HYPO_StartEndLength mesh_tree_hypo_length.png + + + StdMeshersGUI_QuadrangleParamWdg - ICON_DLG_QUADRANGLE_PARAMS - mesh_hypo_length.png + ICON_StdMeshers_Quadrangle_Params_0 + mesh_quadrangle_standard.png + + + ICON_StdMeshers_Quadrangle_Params_1 + mesh_quadrangle_triapref.png + + + ICON_StdMeshers_Quadrangle_Params_2 + mesh_quadrangle_quadpref.png + + + ICON_StdMeshers_Quadrangle_Params_3 + mesh_quadrangle_quadpref_reversed.png + + + ICON_StdMeshers_Quadrangle_Params_4 + mesh_quadrangle_reduced.png diff --git a/src/StdMeshersGUI/StdMeshers_msg_en.ts b/src/StdMeshersGUI/StdMeshers_msg_en.ts index 228cc7a58..c04916750 100644 --- a/src/StdMeshersGUI/StdMeshers_msg_en.ts +++ b/src/StdMeshersGUI/StdMeshers_msg_en.ts @@ -339,6 +339,33 @@ SMESH_QUADRANGLE_PARAMS_TITLE Hypothesis Construction + + SMESH_QUAD_TYPE + Type + + + + StdMeshersGUI_QuadrangleParamWdg + + SMESH_QUAD_TYPE_0 + Standard + + + SMESH_QUAD_TYPE_1 + Triangle preference + + + SMESH_QUAD_TYPE_2 + Quadrangle preference + + + SMESH_QUAD_TYPE_3 + Quadrangle preference (reversed) + + + SMESH_QUAD_TYPE_4 + Reduced + StdMeshersGUI_LayerDistributionParamWdg diff --git a/src/StdMeshers_I/StdMeshers_QuadrangleParams_i.cxx b/src/StdMeshers_I/StdMeshers_QuadrangleParams_i.cxx index 612ccc9ee..85295c055 100644 --- a/src/StdMeshers_I/StdMeshers_QuadrangleParams_i.cxx +++ b/src/StdMeshers_I/StdMeshers_QuadrangleParams_i.cxx @@ -16,13 +16,11 @@ // // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // - // SMESH SMESH_I : idl implementation based on 'SMESH' unit's calsses // File : StdMeshers_QuadrangleParams_i.cxx // Author : Sergey KUUL, OCC // Module : SMESH -// $Header$ -// + #include "StdMeshers_QuadrangleParams_i.hxx" #include "SMESH_Gen_i.hxx" #include "SMESH_Gen.hxx" @@ -94,6 +92,21 @@ void StdMeshers_QuadrangleParams_i::SetTriaVertex(CORBA::Long vertID) << vertID << " )"; } +//============================================================================= +/*! + * StdMeshers_QuadrangleParams_i::GetTriaVertex + * + * Get base vertex for triangles + */ +//============================================================================= + +CORBA::Long StdMeshers_QuadrangleParams_i::GetTriaVertex() +{ + MESSAGE( "StdMeshers_QuadrangleParams_i::GetTriaVertex" ); + ASSERT( myBaseImpl ); + return this->GetImpl()->GetTriaVertex(); +} + //============================================================================= /*! * StdMeshers_QuadrangleParams_i::SetObjectEntry @@ -143,17 +156,65 @@ char* StdMeshers_QuadrangleParams_i::GetObjectEntry() //============================================================================= /*! - * StdMeshers_QuadrangleParams_i::GetTriaVertex + * StdMeshers_QuadrangleParams_i::SetQuadType * - * Get base vertex for triangles + * Set the type of quadrangulation */ //============================================================================= +void StdMeshers_QuadrangleParams_i::SetQuadType(StdMeshers::QuadType type) +{ + //static char* quadTypes[5] = {"StdMeshers.QUAD_STANDARD", + // "StdMeshers.QUAD_TRIANGLE_PREF", + // "StdMeshers.QUAD_QUADRANGLE_PREF", + // "StdMeshers.QUAD_QUADRANGLE_PREF_REVERSED", + // "StdMeshers.QUAD_REDUCED"}; -CORBA::Long StdMeshers_QuadrangleParams_i::GetTriaVertex() + MESSAGE("StdMeshers_QuadrangleParams_i::SetQuadType"); + ASSERT(myBaseImpl); + + if (int(type) >= int(StdMeshers::QUAD_NB_TYPES)) { + THROW_SALOME_CORBA_EXCEPTION("Bad type of quadrangulation", SALOME::BAD_PARAM); + } + + try { + this->GetImpl()->SetQuadType(StdMeshers_QuadType(int(type))); + } + catch (SALOME_Exception& S_ex) { + THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM); + } + + // Update Python script + const char* quadType; + switch (type) { + case StdMeshers::QUAD_STANDARD: + quadType = "StdMeshers.QUAD_STANDARD"; break; + case StdMeshers::QUAD_TRIANGLE_PREF: + quadType = "StdMeshers.QUAD_TRIANGLE_PREF"; break; + case StdMeshers::QUAD_QUADRANGLE_PREF: + quadType = "StdMeshers.QUAD_QUADRANGLE_PREF"; break; + case StdMeshers::QUAD_QUADRANGLE_PREF_REVERSED: + quadType = "StdMeshers.QUAD_QUADRANGLE_PREF_REVERSED"; break; + case StdMeshers::QUAD_REDUCED: + quadType = "StdMeshers.QUAD_REDUCED"; break; + default: + quadType = "UNKNOWN"; + } + SMESH::TPythonDump() << _this() << ".SetQuadType( " << quadType << " )"; + //SMESH::TPythonDump() << _this() << ".SetQuadType( " << quadTypes[int(type)] << " )"; +} + +//============================================================================= +/*! + * StdMeshers_QuadrangleParams_i::GetQuadType + * + * Get the type of quadrangulation + */ +//============================================================================= +StdMeshers::QuadType StdMeshers_QuadrangleParams_i::GetQuadType() { - MESSAGE( "StdMeshers_QuadrangleParams_i::GetTriaVertex" ); - ASSERT( myBaseImpl ); - return this->GetImpl()->GetTriaVertex(); + MESSAGE("StdMeshers_QuadrangleParams_i::GetQuadType"); + ASSERT(myBaseImpl); + return StdMeshers::QuadType(int(this->GetImpl()->GetQuadType())); } //============================================================================= @@ -183,4 +244,3 @@ CORBA::Boolean StdMeshers_QuadrangleParams_i::IsDimSupported( SMESH::Dimension t { return type == SMESH::DIM_2D; } - diff --git a/src/StdMeshers_I/StdMeshers_QuadrangleParams_i.hxx b/src/StdMeshers_I/StdMeshers_QuadrangleParams_i.hxx index fa695107d..062af680d 100644 --- a/src/StdMeshers_I/StdMeshers_QuadrangleParams_i.hxx +++ b/src/StdMeshers_I/StdMeshers_QuadrangleParams_i.hxx @@ -16,13 +16,12 @@ // // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // - -// SMESH SMESH_I : idl implementation based on 'SMESH' unit's calsses +// SMESH SMESH_I : idl implementation based on 'SMESH' unit's classes // File : StdMeshers_QuadrangleParams_i.hxx // Author : Sergey KUUL, OCC // Module : SMESH // $Header$ -// + #ifndef _SMESH_QUADRANGLEPARAMS_I_HXX_ #define _SMESH_QUADRANGLEPARAMS_I_HXX_ @@ -43,9 +42,9 @@ class STDMESHERS_I_EXPORT StdMeshers_QuadrangleParams_i: { public: // Constructor - StdMeshers_QuadrangleParams_i( PortableServer::POA_ptr thePOA, + StdMeshers_QuadrangleParams_i (PortableServer::POA_ptr thePOA, int theStudyId, - ::SMESH_Gen* theGenImpl ); + ::SMESH_Gen* theGenImpl); // Destructor virtual ~StdMeshers_QuadrangleParams_i(); @@ -56,18 +55,24 @@ public: // Get length //CORBA::Double GetLength(CORBA::Boolean theIsStart); - //Set base vertex for triangles - void SetTriaVertex(CORBA::Long vertID); + // Set base vertex for triangles + void SetTriaVertex (CORBA::Long vertID); - //Get base vertex for triangles + // Get base vertex for triangles CORBA::Long GetTriaVertex(); - //Set the Entry of the Object - void SetObjectEntry(const char* theEntry); + // Set the Entry of the Object + void SetObjectEntry (const char* theEntry); - //Get Object Entry + // Get Object Entry char* GetObjectEntry(); + // Set the type of quadrangulation + void SetQuadType (StdMeshers::QuadType type); + + // Get the type of quadrangulation + StdMeshers::QuadType GetQuadType(); + // Get implementation ::StdMeshers_QuadrangleParams* GetImpl();