From f5016d85b7b4b88623723027a1585c6414c4dc66 Mon Sep 17 00:00:00 2001 From: vsr Date: Mon, 8 Oct 2012 11:56:59 +0000 Subject: [PATCH] Merge from V6_main (04/10/2012) --- configure.ac | 1 + doc/salome/gui/SMESH/Makefile.am | 31 +- doc/salome/gui/SMESH/collect_mesh_methods.py | 118 ++ doc/salome/gui/SMESH/doxyfile_py.in | 25 +- .../images/choose_geom_selection_way.png | Bin 0 -> 3548 bytes doc/salome/gui/SMESH/images/colors_size.png | Bin 20715 -> 37426 bytes .../SMESH/images/find_geom_by_mesh_elem.png | Bin 0 -> 13112 bytes .../gui/SMESH/images/point_marker_widget1.png | Bin 4405 -> 2376 bytes .../gui/SMESH/images/point_marker_widget2.png | Bin 4322 -> 2700 bytes doc/salome/gui/SMESH/images/show_bad_mesh.png | Bin 0 -> 36496 bytes doc/salome/gui/SMESH/input/about_meshes.doc | 8 +- doc/salome/gui/SMESH/input/colors_size.doc | 72 +- .../gui/SMESH/input/constructing_meshes.doc | 26 + .../SMESH/input/constructing_submeshes.doc | 34 +- .../gui/SMESH/input/cutting_quadrangles.doc | 13 +- .../input/importing_exporting_meshes.doc | 8 +- doc/salome/gui/SMESH/input/point_marker.doc | 12 +- .../gui/SMESH/input/smeshpy_interface.doc | 47 +- .../gui/SMESH/input/tui_cartesian_algo.doc | 6 +- .../SMESH/input/tui_defining_hypotheses.doc | 73 +- .../gui/SMESH/input/tui_grouping_elements.doc | 8 +- .../gui/SMESH/input/tui_quality_controls.doc | 4 +- .../SMESH/input/uniting_set_of_triangles.doc | 11 +- idl/SMESH_Gen.idl | 10 +- idl/SMESH_Hypothesis.idl | 44 +- idl/SMESH_Mesh.idl | 4 +- idl/SMESH_MeshEditor.idl | 74 +- resources/SalomeApp.xml.in | 5 +- resources/StdMeshers.xml | 30 +- src/Controls/SMESH_Controls.cxx | 41 +- src/Driver/Driver_Mesh.cxx | 25 +- src/Driver/Driver_Mesh.h | 19 +- src/Driver/Makefile.am | 2 + src/DriverCGNS/DriverCGNS_Write.cxx | 2 +- src/DriverDAT/Makefile.am | 1 + src/DriverGMF/DriverGMF_Read.cxx | 357 +++++ .../DriverGMF_Read.hxx} | 42 +- src/DriverGMF/DriverGMF_Write.cxx | 317 ++++ .../DriverGMF_Write.hxx} | 45 +- src/DriverGMF/Makefile.am | 50 + .../SMESH_DriverGMF.hxx} | 28 +- src/DriverGMF/libmesh5.c | 1346 +++++++++++++++++ src/DriverGMF/libmesh5.h | 155 ++ src/DriverMED/DriverMED_R_SMESHDS_Mesh.cxx | 2 +- src/DriverMED/DriverMED_W_SMESHDS_Mesh.cxx | 2 +- src/DriverMED/Makefile.am | 1 + src/DriverUNV/Makefile.am | 1 + src/DriverUNV/UNV164_Structure.cxx | 2 +- src/Makefile.am | 3 +- src/OBJECT/Makefile.am | 7 +- src/OBJECT/SMESH_Actor.cxx | 157 +- src/OBJECT/SMESH_Actor.h | 10 +- src/OBJECT/SMESH_ActorDef.h | 17 +- src/OBJECT/SMESH_DeviceActor.cxx | 8 +- src/OBJECT/SMESH_DeviceActor.h | 4 +- src/OBJECT/SMESH_Object.cxx | 28 +- src/OBJECT/SMESH_SVTKActor.cxx | 184 +++ src/OBJECT/SMESH_SVTKActor.h | 82 + src/SMDS/SMDS_Downward.hxx | 38 +- src/SMDS/SMDS_MeshNode.hxx | 2 +- src/SMDS/SMDS_UnstructuredGrid.cxx | 24 +- src/SMDS/SMDS_UnstructuredGrid.hxx | 2 +- src/SMDS/SMDS_VolumeTool.cxx | 39 + src/SMDS/SMDS_VolumeTool.hxx | 3 + src/SMESH/Makefile.am | 12 +- src/SMESH/SMESH_0D_Algo.cxx | 53 - src/SMESH/SMESH_1D_Algo.cxx | 58 - src/SMESH/SMESH_1D_Algo.hxx | 44 - src/SMESH/SMESH_2D_Algo.cxx | 97 -- src/SMESH/SMESH_3D_Algo.cxx | 60 - src/SMESH/SMESH_Algo.cxx | 82 +- src/SMESH/SMESH_Algo.hxx | 32 +- src/SMESH/SMESH_Gen.cxx | 256 +++- src/SMESH/SMESH_Gen.hxx | 10 +- src/SMESH/SMESH_Group.cxx | 16 +- src/SMESH/SMESH_Group.hxx | 2 +- src/SMESH/SMESH_Hypothesis.cxx | 108 +- src/SMESH/SMESH_Hypothesis.hxx | 26 +- src/SMESH/SMESH_Mesh.cxx | 116 +- src/SMESH/SMESH_Mesh.hxx | 31 +- src/SMESH/SMESH_MeshEditor.cxx | 851 +++++++++-- src/SMESH/SMESH_MeshEditor.hxx | 44 +- src/SMESH/SMESH_MesherHelper.cxx | 591 ++++++-- src/SMESH/SMESH_MesherHelper.hxx | 6 +- src/SMESH/SMESH_subMesh.cxx | 63 +- src/SMESH/SMESH_subMesh.hxx | 11 +- src/SMESH/SMESH_subMeshEventListener.hxx | 16 +- src/SMESHClient/Makefile.am | 1 + src/SMESHDS/SMESHDS_Document.hxx | 34 +- src/SMESHDS/SMESHDS_Hypothesis.hxx | 13 +- src/SMESHGUI/Makefile.am | 10 +- src/SMESHGUI/SMESHGUI.cxx | 553 +++---- src/SMESHGUI/SMESHGUI_AddMeshElementDlg.cxx | 4 +- .../SMESHGUI_AddQuadraticElementDlg.cxx | 4 +- src/SMESHGUI/SMESHGUI_ClippingDlg.cxx | 13 +- src/SMESHGUI/SMESHGUI_ClippingDlg.h | 1 + src/SMESHGUI/SMESHGUI_ComputeDlg.cxx | 37 +- src/SMESHGUI/SMESHGUI_ConvToQuadOp.cxx | 69 +- src/SMESHGUI/SMESHGUI_ConvToQuadOp.h | 3 + .../SMESHGUI_CreatePolyhedralVolumeDlg.cxx | 4 +- src/SMESHGUI/SMESHGUI_ExtrusionDlg.cxx | 86 +- src/SMESHGUI/SMESHGUI_ExtrusionDlg.h | 4 +- src/SMESHGUI/SMESHGUI_FilterDlg.cxx | 12 +- src/SMESHGUI/SMESHGUI_FilterDlg.h | 4 +- src/SMESHGUI/SMESHGUI_GroupDlg.cxx | 16 +- src/SMESHGUI/SMESHGUI_GroupOnShapeDlg.cxx | 6 +- src/SMESHGUI/SMESHGUI_Hypotheses.cxx | 8 +- src/SMESHGUI/SMESHGUI_HypothesesUtils.cxx | 8 +- src/SMESHGUI/SMESHGUI_MeshInfosBox.cxx | 9 + src/SMESHGUI/SMESHGUI_NodesDlg.cxx | 4 +- .../SMESHGUI_Preferences_ColorDlg.cxx | 570 ------- src/SMESHGUI/SMESHGUI_Preferences_ColorDlg.h | 110 -- src/SMESHGUI/SMESHGUI_PropertiesDlg.cxx | 649 ++++++++ src/SMESHGUI/SMESHGUI_PropertiesDlg.h | 143 ++ src/SMESHGUI/SMESHGUI_VTKUtils.cxx | 19 +- src/SMESHGUI/SMESHGUI_XmlHandler.cxx | 3 +- src/SMESHGUI/SMESH_msg_en.ts | 221 ++- src/SMESHGUI/SMESH_msg_fr.ts | 172 ++- src/SMESHUtils/SMESH_ComputeError.hxx | 60 +- src/SMESH_I/Makefile.am | 1 + src/SMESH_I/SMESH_2smeshpy.cxx | 129 +- src/SMESH_I/SMESH_2smeshpy.hxx | 6 +- src/SMESH_I/SMESH_DumpPython.cxx | 4 +- src/SMESH_I/SMESH_Gen_i.cxx | 56 +- src/SMESH_I/SMESH_Gen_i.hxx | 9 +- src/SMESH_I/SMESH_Hypothesis_i.cxx | 184 +-- src/SMESH_I/SMESH_Hypothesis_i.hxx | 18 +- src/SMESH_I/SMESH_MeshEditor_i.cxx | 245 ++- src/SMESH_I/SMESH_MeshEditor_i.hxx | 81 +- src/SMESH_I/SMESH_MeshPartDS.hxx | 70 + src/SMESH_I/SMESH_Mesh_i.cxx | 356 +++-- src/SMESH_I/SMESH_Mesh_i.hxx | 7 +- src/SMESH_I/SMESH_PreMeshInfo.cxx | 14 +- src/SMESH_SWIG/Makefile.am | 3 +- src/SMESH_SWIG/StdMeshersDC.py | 430 ++++-- src/SMESH_SWIG/smesh.py | 68 +- src/SMESH_SWIG/smeshDC.py | 359 +---- src/SMESH_SWIG/smesh_algorithm.py | 322 ++++ src/SMESH_SWIG_WITHIHM/libSMESH_Swig.cxx | 41 + src/SMESH_SWIG_WITHIHM/libSMESH_Swig.h | 2 + src/SMESH_SWIG_WITHIHM/libSMESH_Swig.i | 1 + src/StdMeshers/StdMeshers_Cartesian_3D.cxx | 6 +- src/StdMeshers/StdMeshers_Cartesian_3D.hxx | 2 +- .../StdMeshers_CompositeHexa_3D.hxx | 2 +- src/StdMeshers/StdMeshers_HexaFromSkin_3D.hxx | 2 +- src/StdMeshers/StdMeshers_Hexa_3D.hxx | 2 +- src/StdMeshers/StdMeshers_Import_1D.cxx | 18 +- src/StdMeshers/StdMeshers_Import_1D.hxx | 2 +- src/StdMeshers/StdMeshers_Import_1D2D.hxx | 2 +- src/StdMeshers/StdMeshers_MEFISTO_2D.cxx | 3 +- src/StdMeshers/StdMeshers_MEFISTO_2D.hxx | 3 +- src/StdMeshers/StdMeshers_Penta_3D.hxx | 10 +- src/StdMeshers/StdMeshers_Prism_3D.hxx | 15 +- src/StdMeshers/StdMeshers_ProjectionUtils.cxx | 5 +- src/StdMeshers/StdMeshers_Projection_1D.hxx | 2 +- src/StdMeshers/StdMeshers_Projection_1D2D.cxx | 1 + src/StdMeshers/StdMeshers_Projection_2D.cxx | 4 +- src/StdMeshers/StdMeshers_Projection_2D.hxx | 2 +- src/StdMeshers/StdMeshers_Projection_3D.cxx | 6 +- src/StdMeshers/StdMeshers_Projection_3D.hxx | 2 +- .../StdMeshers_QuadToTriaAdaptor.cxx | 58 +- src/StdMeshers/StdMeshers_Quadrangle_2D.hxx | 2 +- src/StdMeshers/StdMeshers_RadialPrism_3D.hxx | 2 +- .../StdMeshers_RadialQuadrangle_1D2D.cxx | 5 +- .../StdMeshers_RadialQuadrangle_1D2D.hxx | 2 +- src/StdMeshers/StdMeshers_Regular_1D.cxx | 40 +- src/StdMeshers/StdMeshers_Regular_1D.hxx | 2 +- .../StdMeshers_SegmentAroundVertex_0D.hxx | 2 +- .../StdMeshers_UseExisting_1D2D.hxx | 3 +- src/StdMeshers/StdMeshers_ViscousLayers.cxx | 68 +- .../StdMeshersGUI_CartesianParamCreator.cxx | 2 +- .../StdMeshersGUI_StdHypothesisCreator.cxx | 2 +- .../StdMeshersGUI_SubShapeSelectorWdg.cxx | 6 +- 173 files changed, 8669 insertions(+), 3165 deletions(-) create mode 100755 doc/salome/gui/SMESH/collect_mesh_methods.py create mode 100644 doc/salome/gui/SMESH/images/choose_geom_selection_way.png create mode 100644 doc/salome/gui/SMESH/images/find_geom_by_mesh_elem.png create mode 100644 doc/salome/gui/SMESH/images/show_bad_mesh.png create mode 100644 src/DriverGMF/DriverGMF_Read.cxx rename src/{SMESH/SMESH_3D_Algo.hxx => DriverGMF/DriverGMF_Read.hxx} (56%) create mode 100644 src/DriverGMF/DriverGMF_Write.cxx rename src/{SMESH/SMESH_2D_Algo.hxx => DriverGMF/DriverGMF_Write.hxx} (59%) create mode 100644 src/DriverGMF/Makefile.am rename src/{SMESH/SMESH_0D_Algo.hxx => DriverGMF/SMESH_DriverGMF.hxx} (72%) mode change 100644 => 100755 create mode 100644 src/DriverGMF/libmesh5.c create mode 100644 src/DriverGMF/libmesh5.h create mode 100644 src/OBJECT/SMESH_SVTKActor.cxx create mode 100644 src/OBJECT/SMESH_SVTKActor.h delete mode 100644 src/SMESH/SMESH_0D_Algo.cxx delete mode 100644 src/SMESH/SMESH_1D_Algo.cxx delete mode 100644 src/SMESH/SMESH_1D_Algo.hxx delete mode 100644 src/SMESH/SMESH_2D_Algo.cxx delete mode 100644 src/SMESH/SMESH_3D_Algo.cxx delete mode 100644 src/SMESHGUI/SMESHGUI_Preferences_ColorDlg.cxx delete mode 100644 src/SMESHGUI/SMESHGUI_Preferences_ColorDlg.h create mode 100644 src/SMESHGUI/SMESHGUI_PropertiesDlg.cxx create mode 100644 src/SMESHGUI/SMESHGUI_PropertiesDlg.h create mode 100644 src/SMESH_I/SMESH_MeshPartDS.hxx create mode 100644 src/SMESH_SWIG/smesh_algorithm.py diff --git a/configure.ac b/configure.ac index 202786736..51899e35e 100644 --- a/configure.ac +++ b/configure.ac @@ -553,6 +553,7 @@ AC_OUTPUT([ \ src/DriverMED/Makefile \ src/DriverSTL/Makefile \ src/DriverUNV/Makefile \ + src/DriverGMF/Makefile \ src/DriverCGNS/Makefile \ src/MEFISTO2/Makefile \ src/OBJECT/Makefile \ diff --git a/doc/salome/gui/SMESH/Makefile.am b/doc/salome/gui/SMESH/Makefile.am index cc3ddb251..5b3adb2fb 100755 --- a/doc/salome/gui/SMESH/Makefile.am +++ b/doc/salome/gui/SMESH/Makefile.am @@ -26,25 +26,26 @@ include $(top_srcdir)/adm_local/unix/make_common_starter.am EXTRA_DIST += images input static/footer.html static/doxygen.css +dist_salomescript_PYTHON = collect_mesh_methods.py + guidocdir = $(docdir)/gui/SMESH guidoc_DATA = images/head.png +DOC_PYTHONPATH=$(prefix)/bin/salome:$(prefix)/lib/python$(PYTHON_VERSION)/site-packages/salome:$(MED_ROOT_DIR)/lib/python$(PYTHON_VERSION)/site-packages/salome:$(GEOM_ROOT_DIR)/bin/salome:$(GEOM_ROOT_DIR)/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:$(OMNIORB_ROOT)/lib64/python$(PYTHON_VERSION)/site-packages +DOC_SMESH_MeshersList=StdMeshers + +# to have smesh.py in the documentation instead of smeshDC.py +# we create dummy smesh.py from the smeshDC.py +smesh.py: ../../../../src/SMESH_SWIG/smeshDC.py + @awk '/^class Mesh:/ { mesh_found=1 } // { if (mesh_found) {print $$0; next} } /^ +(def|#)/ { match( $$0, /^ +/); print substr( $$0, 1+RLENGTH ); next } /^class smeshDC/ { next } //' \ + $< > $@ + +tmp/smesh.py: $(top_srcdir)/src/SMESH_SWIG/StdMeshersDC.py $(srcdir)/collect_mesh_methods.py + @mkdir -p tmp && PYTHONPATH=$(DOC_PYTHONPATH):${PYTHONPATH} SMESH_MeshersList=$(DOC_SMESH_MeshersList) $(PYTHON) $(srcdir)/collect_mesh_methods.py -o $@ StdMeshers -usr_docs: doxyfile_py doxyfile - echo "===========================================" ; \ - echo "Replacing smeshDC by smesh" ; \ - echo "===========================================" ; \ - awk '/^class Mesh:/ { mesh_found=1 } // { if (mesh_found) {print $$0; next} } /^ +(def|#)/ { match( $$0, /^ +/); print substr( $$0, 1+RLENGTH ); next } /^class smeshDC/ { next } //' \ - $(top_srcdir)/src/SMESH_SWIG/smeshDC.py > ./smesh.py ; \ - echo "===========================================" ; \ - echo "Generating Python interface documentation"; \ - echo "===========================================" ; \ - $(DOXYGEN) doxyfile_py ; \ - echo "===========================================" ; \ - echo "Generating GUI documentation" ; \ - echo "===========================================" ; \ - $(DOXYGEN) doxyfile ; \ - rm -f ./smesh.py +usr_docs: doxyfile_py doxyfile smesh.py tmp/smesh.py + @$(DOXYGEN) doxyfile_py ; \ + $(DOXYGEN) doxyfile docs: usr_docs diff --git a/doc/salome/gui/SMESH/collect_mesh_methods.py b/doc/salome/gui/SMESH/collect_mesh_methods.py new file mode 100755 index 000000000..24fd31880 --- /dev/null +++ b/doc/salome/gui/SMESH/collect_mesh_methods.py @@ -0,0 +1,118 @@ +#!/usr/bin/env python +################################################################################# +# +# File: collect_mesh_methods.py +# Author: Vadim SANDLER, Open CASCADE S.A.S (vadim.sandler@opencascade.com) +# +################################################################################# +# +# Extraction of the meshing algorithm classes +# dynamically added by the plug-in to the Mesh +# class. +# +# This script is intended for internal usage - only +# for generatation of the extra developer documentation for +# the meshing plug-in(s). +# +# Usage: +# collect_mesh_methods.py +# where +# is a name of the plug-in module +# +# Notes: +# - the script is supposed to be run in correct environment +# i.e. PYTHONPATH, SMESH_MeshersList and other important +# variables are set properly; otherwise the script will fail. +# +################################################################################ + +import sys + +def main(plugin, dummymeshhelp = True, output_file = "smesh.py"): + plugin_module = plugin + "DC" + try: + mod = __import__(plugin_module) + methods = {} + for attr in dir( mod ): + if attr.startswith( '_' ): continue + algo = getattr( mod, attr ) + if type( algo ).__name__ == 'classobj' and hasattr( algo, "meshMethod" ): + method = getattr( algo, "meshMethod" ) + if method not in methods: methods[ method ] = [] + methods[ method ].append( algo ) + pass + pass + if methods: + output = [] + if dummymeshhelp: + output.append( "## @package smesh" ) + output.append( "# Documentation of the methods dynamically added by the " + plugin + " meshing plug-in to the Mesh class." ) + output.append( "" ) + pass + output.append( "## This class allows defining and managing a mesh." ) + output.append( "#" ) + if dummymeshhelp: + # Add dummy Mesh help + # This is supposed to be done when generating documentation for meshing plug-ins + output.append( "# @note The documentation below does not provide complete description of class @b %Mesh" ) + output.append( "# from @b %smesh.py package. This documentation provides only information about" ) + output.append( "# the methods dynamically added to the %Mesh class by the " + plugin + " plugin" ) + output.append( "# For more details on the %Mesh class, please refer to the SALOME %Mesh module" ) + output.append( "# documentation." ) + pass + else: + # Extend documentation for Mesh class with information about dynamically added methods. + # This is supposed to be done only when building documentation for SMESH module + output.append( "# @note Some methods are dynamically added to the @b %Mesh class in runtime by meshing " ) + output.append( "# plug-in modules. If you fail to find help on some methods in the documentation of SMESH module, " ) + output.append( "# try to look into the documentation for the meshing plug-ins." ) + pass + output.append( "class Mesh:" ) + for method in methods: + docHelper = "" + for algo in methods[ method ]: + if hasattr( algo, "docHelper" ): docHelper = getattr( algo, "docHelper" ) + if docHelper: break + pass + if not docHelper: docHelper = "Creates new algorithm." + output.append( " ## %s" % docHelper ) + output.append( " #" ) + output.append( " # This method is dynamically added to %Mesh class by the meshing plug-in(s). " ) + output.append( " #" ) + output.append( " # If the optional @a geom_shape parameter is not set, this algorithm is global (applied to whole mesh)." ) + output.append( " # Otherwise, this algorithm defines a submesh based on @a geom_shape subshape." ) + output.append( " # @param algo_type type of algorithm to be created; allowed values are specified by classes implemented by plug-in (see below)" ) + output.append( " # @param geom_shape if defined, the subshape to be meshed (GEOM_Object)" ) + output.append( " # @return An instance of Mesh_Algorithm sub-class according to the specified @a algo_type, see " ) + output.append( " # %s" % ", ".join( [ "%s.%s" % ( plugin_module, algo.__name__ ) for algo in methods[ method ] ] ) ) + output.append( " def %s(algo_type, geom_shape=0):" % method ) + output.append( " pass" ) + pass + f = open(output_file, "w") + for line in output: f.write( line + "\n" ) + f.close() + pass + pass + except Exception, e: + print e + pass + pass + +if __name__ == "__main__": + import optparse + parser = optparse.OptionParser(usage="%prog [options] plugin") + h = "Output file (smesh.py by default)" + parser.add_option("-o", "--output", dest="output", + action="store", default=None, metavar="file", + help=h) + h = "If this option is True, dummy help for Mesh class is added. " + h += "This option should be False (default) when building documentation for SMESH module " + h += "and True when building documentation for meshing plug-ins." + parser.add_option("-d", "--dummy-mesh-help", dest="dummymeshhelp", + action="store_true", default=False, + help=h) + (options, args) = parser.parse_args() + + if len( args ) < 1: sys.exit("Plugin name is not specified") + main( args[0], options.dummymeshhelp, options.output ) + pass diff --git a/doc/salome/gui/SMESH/doxyfile_py.in b/doc/salome/gui/SMESH/doxyfile_py.in index 19e21b96e..da25d092b 100755 --- a/doc/salome/gui/SMESH/doxyfile_py.in +++ b/doc/salome/gui/SMESH/doxyfile_py.in @@ -99,7 +99,10 @@ EXAMPLE_RECURSIVE = NO #--------------------------------------------------------------------------- #Input related options #--------------------------------------------------------------------------- -INPUT = smesh.py @top_srcdir@/src/SMESH_SWIG/StdMeshersDC.py +INPUT = smesh.py \ + @top_srcdir@/src/SMESH_SWIG/smesh_algorithm.py \ + @top_srcdir@/src/SMESH_SWIG/StdMeshersDC.py \ + tmp/smesh.py FILE_PATTERNS = IMAGE_PATH = @srcdir@/images RECURSIVE = NO @@ -132,24 +135,24 @@ GENERATE_RTF = NO #--------------------------------------------------------------------------- CLASS_DIAGRAMS = NO HIDE_UNDOC_RELATIONS = NO -HAVE_DOT = NO -CLASS_GRAPH = NO +HAVE_DOT = YES +CLASS_GRAPH = YES COLLABORATION_GRAPH = NO GROUP_GRAPHS = NO UML_LOOK = NO -TEMPLATE_RELATIONS = NO -INCLUDE_GRAPH = NO -INCLUDED_BY_GRAPH = NO +TEMPLATE_RELATIONS = YES +INCLUDE_GRAPH = YES +INCLUDED_BY_GRAPH = YES CALL_GRAPH = NO -GRAPHICAL_HIERARCHY = NO -DIRECTORY_GRAPH = NO -DOT_IMAGE_FORMAT = jpg +GRAPHICAL_HIERARCHY = YES +DIRECTORY_GRAPH = YES +DOT_IMAGE_FORMAT = png DOT_FONTNAME = Arial DOT_PATH = DOTFILE_DIRS = MAX_DOT_GRAPH_WIDTH = 1024 -MAX_DOT_GRAPH_HEIGHT = 1200 -MAX_DOT_GRAPH_DEPTH = 0 +MAX_DOT_GRAPH_HEIGHT = 1024 +MAX_DOT_GRAPH_DEPTH = 1000 DOT_TRANSPARENT = NO DOT_MULTI_TARGETS = NO GENERATE_LEGEND = NO diff --git a/doc/salome/gui/SMESH/images/choose_geom_selection_way.png b/doc/salome/gui/SMESH/images/choose_geom_selection_way.png new file mode 100644 index 0000000000000000000000000000000000000000..ffee00d53322b628576b51f08e8ee3304e3cb73e GIT binary patch literal 3548 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 IU%mVP0J@`io&W#< literal 20715 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 diff --git a/doc/salome/gui/SMESH/images/find_geom_by_mesh_elem.png b/doc/salome/gui/SMESH/images/find_geom_by_mesh_elem.png new file mode 100644 index 0000000000000000000000000000000000000000..d71495e734b50e856c30dbd0af2f5805b7c09dac GIT binary patch literal 13112 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 literal 4405 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 D>9mWV diff --git a/doc/salome/gui/SMESH/images/point_marker_widget2.png b/doc/salome/gui/SMESH/images/point_marker_widget2.png index dbb81b40e5c958d24445a250c540fc82b959a277..d44f3888fb2b59a0d422598a2ef2a0abb3d481f7 100755 GIT binary patch literal 2700 zcmaJ@hd&$I7f*~Dt?@zCrgrhDRZrC@A<_^}jcUyrjZN*8QdP9%nXN4}<}>?@P*J0( zRjaikV#H`PC8{Ao=r8Xd_}%+C_ndn^pL_55o_jv$^L_Of49vqV#ti@fcp#RbyG(t; z6jja(%+)sIO$So}!|#Gk0Zo$s*~7)2m4z23-j4c<)tMWpp{fVv zZhwXhBG#_?3%{FHaiXsW=ULuUJHjaLW_sop1wr5KRR1$a3J$>p_}8m03b_K>Xiiu2TefE$# zKj#Y)OQOlk|8LB&vn2An%J6eCjeZ@o%UF-=c`D-#bYp8(E27868Mq!02(-+J82733 z4Gvb+)r~YAc6lGB05;ZFdHz$4Yu=Q)o@J7A`XbK<*Gf$=dP6-rO7l8UWw0^~hc{px z8+h(z>xs(BN@T1=EAG~Jk3T@tlfTZNt7@e+lq;uw(>1rPj)*OR)%>a4Ynm6#=H^E- zxi!}xBg;xVmF~8Qa>OVTYKZbVRpQTAvs@e;yzg5$%w4;3=BV_k8}aMHhxwHiqkuZ~ z`|m}Ogxho&+s3P#DCsk@T;`8L(Lz(|KO>|xba^dz9U5JycZK;@n~ub_ir&)|Y(!+_ z!&Y33|2MlhR#ap+H?xom|jkdudNYucE1LTcvy3>oqiO}3Xbc4K6h9vf&DTA||k z%j@dWSUGt4#l;N}N-4kQ4NIL5nwpwy8;u3>)m_ou-6g0!DS3$LR~;)=D-Z~T^y|*Z z;9ZHO86HG!T94gItE09%R8>_KOgxg6lVirE4WA4>XCOR1J*(SELkdG3F25IldQ~#6 z`Vc|JPfv8FqajNA*Koh$<_}3{iiDH=UB%p2daH4{Xtb<6#B-s^b#rU$?bn_CgM*@O zOiWYlew!Zo#G3 zXAE0ZwKAkQ2m}Ji+?;vU^iIU!r%z!F`eWk8MolBBEI;0;jwX~Z)VfC_D>g?YkQ+OE z0|UJ&D<1%hyHUgqqW&=s0?5hD866oZKd@4GQi@7Slp>2Xu9H+d4XI{Q0Gt zNsxdXMQ?$SWi;H!=jU`@XPm`t9kteNjadA$VK+)vnZ?d=~f)FAK%xp8V@x$XD`+Zk)nz!3@I=X@e7J4!RBo3?96ZpW0naz zrIQ&jSjnHaxAQ*R!Xs##_-gCo+J=V8>go$g{U-MILM>`c>?mZP;SBOlM8%BdQi=|5 zLTJG*0$7q`BkhqxGOC)l0%TR-FWOI+}{p;64Q(oyqOl$)|`3I^K zs+z?UZ5Yg#+1Ww3lChkkVhYGkHVRuhKktYMS%pR0=K6A}`% zw6vzlhcO6*?Y(>8(9r!hgVYoF_So2%Z7*d#RT_0`1{ii;V)p2fBA;3;Apff_gX5@p zc~*z#ex5$!V6!c~)@#V~->m%nZ|^ONi;JNMgg$fF6#>8Z)+?R#_@WTog}@wILg2qn zwZEI{6;-t)QV z>1j&$X9bAB@$s>*FRP-7VdBJAchD%|k7TSBg+yAL{l_kFx%2UZbW}lsWn|>xOA5rw zs$}_#q{lis83eM}-^@@NT`e^Bt$;$I_j}_Fnbn}?-XlT6X3H5Fp+1<$BKDf6u8wQ* zrY2qd`-;<()i0t-2q!0zQyPV4MeT$W!o$K|rll3NAor@9nlcIsL@>dGo0Xf9k&#|S zugN<*Z>y@3r>CcTrZ5J_J2hq3#r~$#>1(^Y)*c=*moHyt#tR5|M_>JT7#pUHPurecStH9O3&hahu?j3PpFOSGVd|hMX7PFRz@p$nMZZ`h@D(P1= zQ1fWk!J(m_hYRj}*mxJ0<<8)wo<=eWhr|6C!D}j;iv4ZTQ+J;B@uTUKcS-RX$C2H> zCvf}CqlhPxA2QsuI=ow`JyqIGU_Fsb%oax6+Ddk7F8dPDI^eTa6yhHfic3lwJ7ij) z<~ZihoAX*)wCv5RIy&-?e|^hEq4q?zb^myy(L-lRA9~&}qQ>dkS2tIGz0j)r{Dl0u zP&+j_U6|J(-v5D0p2|fEFj;dNJoO>5ysU;)i`SA!f5<2do@zTk(!moFE*)nNzJ)l%^MEi*x1naJ$p`IH_OmYIFDPQpNgBE2UQ=D zqMvB(EtD8W=e?k_St$w%rzf|5o6I1mh%)nZQnB;7)S#pJ$9!;b(wskg-@-yZkNAx> zIMvKnNJr;MSFELuLQY8uvVZv5_>Sl9QagZte9TkJ#&dxcG71q%@B%UW?AxnXACg-% zhodJ8VyT56Lx~n(u${ZR@!Byc?yaA_=-JpC)xecDQ4I|ZBL>OrAwfq_vhQwC|7+im zcY_MEutetX{)|V|eAO=pM~Cm8=r+0b-Y5@=YF_;<)-}HMap|GtlOLK#ByHD-XCot) zQ!mJ%rvZ=c(Wj@Uc1No%w($7=S(Heyii+ys!hK54#(VG494^B=q8kk>UvY7-r_V5( zb7tt3rq}4yR9QCu>__X=-F?sh7?IYAWr1VCBdX0q>q88a2bo|x1w~Clqp!9zmeH>W nGW^Sgm#dLi{vXM*nD`AmFuxw283~qWQbhp790qDK^?3e2H(g1P literal 4322 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 C25de6 diff --git a/doc/salome/gui/SMESH/images/show_bad_mesh.png b/doc/salome/gui/SMESH/images/show_bad_mesh.png new file mode 100644 index 0000000000000000000000000000000000000000..17dfb38ad8171103586769d4cf197b39ca1e1ea6 GIT binary patch literal 36496 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 literal 0 HcmV?d00001 diff --git a/doc/salome/gui/SMESH/input/about_meshes.doc b/doc/salome/gui/SMESH/input/about_meshes.doc index 7474e0f62..411fc30b5 100644 --- a/doc/salome/gui/SMESH/input/about_meshes.doc +++ b/doc/salome/gui/SMESH/input/about_meshes.doc @@ -5,14 +5,16 @@ \n \b MESH represents a discretization of a geometrical CAD model into a set of entities with a simple topology. -Meshes are stored in DAT, MED, UNV, STL, CGNS and SAUVE formats and can be +Meshes are stored in DAT, MED, UNV, STL, CGNS, GMF and SAUVE formats and can be \subpage importing_exporting_meshes_page "imported from and exported to" the file in these formats. It is possible to \subpage constructing_meshes_page "construct meshes" on the basis of geometrical shapes produced in the GEOM module. -It is also possible to \subpage constructing_submeshes_page "mesh on a part of the geometrical object", -for example, a face, with different meshing parameters than the whole mesh. +It is also possible to \subpage constructing_submeshes_page "construct +mesh on a part of the geometrical object", for example, a face, with +different meshing parameters than the whole mesh. + Several created meshes can be \subpage building_compounds_page "combined into another mesh". diff --git a/doc/salome/gui/SMESH/input/colors_size.doc b/doc/salome/gui/SMESH/input/colors_size.doc index f953b37c6..c0953ff09 100644 --- a/doc/salome/gui/SMESH/input/colors_size.doc +++ b/doc/salome/gui/SMESH/input/colors_size.doc @@ -4,34 +4,48 @@ \image html colors_size.png -Using this dialog you can define the following set of mesh visualization -parameters: -
    -
  • Elements
  • -
      -
    • Surface color - surface color of elements (seen in Shading mode).
    • -
    • Back surface color - interior surface color of elements. Use slider to select this color -generated on base of the Surface color by changing its brightness and saturation.
    • -
    • Outline color - color of element borders.
    • -
    • Wireframe color - color of element borders in wireframe mode.
    • -
    • 0D slements - color of 0D elements.
    • -
    • Size of 0D slements - size of 0D elements.
    • -
    • Line width - width of lines (edges and borders of elements).
    • -
    • Shrink coef. - relative space of elements compared to gaps between - them in shrink mode.
    • -
    -
  • Nodes
  • -
      -
    • Color - color of nodes.
    • -
    • Marker - group of options allowing to change the representation of - points (see \subpage point_marker_page "Point Marker" page).
    • -
    -
  • Orientation of faces
  • -
      -
    • Color - color of orientation vertors.
    • -
    • Scale - size of orientation vectors.
    • -
    • 3D vectors - allows to choose between 2D planar and 3D vectors.
    • -
    -
+Using this dialog you can customize different properties of the mesh visualization +parameters. + +The GUI elements in the "Properties" dialog box are grouped according +to the entity types of mesh data. If some data entities are not +present in the mesh object, the corresponding GUI elements are not +shown. + +- \b Nodes: + - \b Color - color of nodes. + - \b Type and \b Scale - these options allow changing of the nodes + representation (see \subpage point_marker_page "Point Marker" page + for more details). +- Edges / wireframe: + - \b Color - color of element borders in wireframe mode. + - \b Width - width of lines (edges and borders of elements + in wireframe mode). +- \b Faces: + - \b Front - surface color of face elements (seen in shading mode). + - \b Back - backside surface color of face elements. Use slider to + select this color generated on base of the \b Face color by + changing its brightness and saturation. +- \b Volumes: + - \b Normal - surface color of normal volume elements (seen in shading mode). + - \b Reversed - surface color of volume elements. Use slider to + select this color generated on base of the \b Normal color by + changing its brightness and saturation. +- \b Outlines: + - \b Color - color of element borders in shading mode. + - \b Width - width of outlines (borders of elements + in shading mode). +- 0D elements: + - \b Color - color of 0D elements. + - \b Size - size of 0D elements. +- \b Balls: + - \b Color - color of discrete ball elements. + - \b Size - size of discrete ball elements. +- Orientation vectors: + - \b Color - color of orientation vectors. + - \b Scale - size of orientation vectors. + - 3D vectors - allows to choose between 2D planar and 3D vectors. +- Shrink coef. - relative space of elements compared to gaps between + them in shrink mode. */ diff --git a/doc/salome/gui/SMESH/input/constructing_meshes.doc b/doc/salome/gui/SMESH/input/constructing_meshes.doc index adf63c6a1..23349d0c1 100644 --- a/doc/salome/gui/SMESH/input/constructing_meshes.doc +++ b/doc/salome/gui/SMESH/input/constructing_meshes.doc @@ -34,6 +34,27 @@ written in Python. \subpage about_hypo_page "hypotheses" which will be used at computation of this mesh. + "Create mesh" dialog box contains several tab pages titled \b 3D, + \b 2D, \b 1D and \b 0D. The title of each page reflects the + dimension of the CAD model (geometry) the algorithms listed on + this page affect to. For example, \b 3D page lists algorithms + that affect 3D geometrical objects (solids). + + \note + - Some page(s) can be disabled - if the source geometrical + object does not include shapes (sub-shapes) of the corresponding + dimension(s). For example, if input object is a geometrical face, + \b 3D page is disabled. + - Some algorithms affect on geometry of several dimensions, + i.e. "1D-2D" or "1D-2D-3D". If such algorithm is selected by the + user, dialog box pages related to the corresponding lower level + dimensions are disabled. + - \b 0D page does not refer to the 0D elements, but to 0D + geometry (vertices). Mesh module does not provide algorithms that + produce 0D elements. Currently \b 0D page provides only one + algorithm "Segments around vertex" that allows specyfing required + size of mesh edges about some selected vertex(vertices). + For example, you need to mesh a 3D object. First, type the name for your mesh in the \b Name box, by default, @@ -284,6 +305,11 @@ or/and hidden by other mesh elements, to see them it can be helpful to switch the mesh to Wireframe visualization mode or to switch off visualization of faces and volumes (if any). +\image html show_bad_mesh.png +Too close nodes causing meshing failure are shown in magenta using Show + bad Mesh button +

+ \anchor use_existing_anchor

"Use existing edges" and "Use existing faces" algorithms

diff --git a/doc/salome/gui/SMESH/input/constructing_submeshes.doc b/doc/salome/gui/SMESH/input/constructing_submeshes.doc index f300d6f50..9f6254cb2 100644 --- a/doc/salome/gui/SMESH/input/constructing_submeshes.doc +++ b/doc/salome/gui/SMESH/input/constructing_submeshes.doc @@ -36,12 +36,15 @@ at computation of this sub-mesh From the \b Mesh menu select Create Sub-mesh or click "Create Sum-mesh" button in the toolbar. -\image html image33.gif -
"Create Sub-mesh" button
+
+ \image html image33.gif + "Create Sub-mesh" button +
\par The following dialog box will appear: +\par \image html createmesh-inv2.png \par @@ -50,6 +53,33 @@ Geometry (e.g. a face if the parent mesh has been built on box) of the sub-mesh. You can define algorithms and hypotheses in the same way as in \ref constructing_meshes_page "Create mesh" menu. +\par +If the parent mesh is already computed, then you can define +\b Geometry by picking mesh elements computed on a sub-shape of interest +in the 3D Viewer, i.e. you don't have to extract this sub-shape +previously in Geometry module. To start element selection, press \a +Selection button to the right of \b Geometry label. If this button is +already down, then click it to release and then click it again. The +following pop-up menu to choose a way of geometry definition will +appear. + +\par +\image html choose_geom_selection_way.png + +\par +There the first item enables selecting the sub-shape in the Object +Browser, the second one makes appear the following dialog. + +\par +\image html find_geom_by_mesh_elem.png + +\par +In this dialog, Element Type defines kind of element to pick in the +Viewer. Instead of picking an element in the Viewer, you can type its +ID in Element ID field. Geometry name allow you +define a name of the sub-shape with which it will be published in the Study. + + \par In the Object Browser the structure of the new sub-mesh will be displayed as follows: diff --git a/doc/salome/gui/SMESH/input/cutting_quadrangles.doc b/doc/salome/gui/SMESH/input/cutting_quadrangles.doc index cbc412855..2865835a5 100644 --- a/doc/salome/gui/SMESH/input/cutting_quadrangles.doc +++ b/doc/salome/gui/SMESH/input/cutting_quadrangles.doc @@ -8,7 +8,7 @@ corners. To cut quadrangles:
    -
  1. Display a mesh or a submesh in the 3D viewer.
  2. +
  3. Display a mesh or a sub-mesh in the 3D viewer.
  4. In the \b Modification menu select the Cutting of quadrangles item or click "Cutting of quadrangles" button in the toolbar. @@ -29,7 +29,7 @@ selected element or elements from the list click \b Remove button. Sort list button allows to sort the list of IDs. \b Filter button allows to apply a definite filter to the selection of quadrangles.
  5. Apply to all radio button allows to modify the orientation of all -quadrangles of the currently displayed mesh or submesh.
  6. +quadrangles of the currently displayed mesh or sub-mesh.
  7. \b Preview - provides a preview of cutting in the viewer.
  8. @@ -39,12 +39,11 @@ quadrangles of the currently displayed mesh or submesh.
  9. Use diagonal 1-3 and Use diagonal 2-4 allows to specify the opposite corners which will be connected by the cutting edge.
  10. -
  11. Use numeric factor - allows to apply the operation only to -those objects which meet the chosen criterion (from the list of -Quality Controls, i.e. Skew, Warping, Minimum Angle, etc.)
  12. +
  13. Use numeric factor - allows to chose a quality criterion + optimization of which will be used to select the cutting edge.
  14. -
  15. Select from - allows to choose a submesh or an existing +
  16. Select from - allows to choose a sub-mesh or an existing group whose quadrangle elements will be automatically added to the list.
  17. @@ -60,4 +59,4 @@ list.
    See Also a sample TUI Script of a \ref tui_cutting_quadrangles "Cutting Quadrangles" operation. -*/ \ No newline at end of file +*/ diff --git a/doc/salome/gui/SMESH/input/importing_exporting_meshes.doc b/doc/salome/gui/SMESH/input/importing_exporting_meshes.doc index 52ff261e3..7c8eeb790 100644 --- a/doc/salome/gui/SMESH/input/importing_exporting_meshes.doc +++ b/doc/salome/gui/SMESH/input/importing_exporting_meshes.doc @@ -3,15 +3,15 @@ \page importing_exporting_meshes_page Importing and exporting meshes \n In MESH there is a functionality allowing importation/exportation -of meshes from/to \b MED, \b UNV (I-DEAS 10), \b DAT (Nastran), \b STL -and \b CGNS format files. You can also export a group as a whole mesh. +of meshes from/to \b MED, \b UNV (I-DEAS 10), \b DAT (simple ascii format), \b STL, +\b GMF and \b CGNS format files. You can also export a group as a whole mesh. To import a mesh:
    1. From the \b File menu choose the \b Import item, from its sub-menu -select the corresponding format (MED, UNV, DAT, STL and CGNS) of the file containing +select the corresponding format (MED, UNV, STL, GMF and CGNS) of the file containing your mesh.
    2. In the standard Search File dialog box find the file for importation. It is possible to select multiple files to be imported all at once.
    3. @@ -26,7 +26,7 @@ importation. It is possible to select multiple files to be imported all at once.
      1. Select the object you wish to export.
      2. From the \b File menu choose the \b Export item, from its sub-menu -select the format (MED, UNV, DAT, STL and CGNS) of the file which will +select the format (MED, UNV, DAT, STL, GMF and CGNS) of the file which will contain your exported mesh.
      3. In the standard Search File select a location for the exported file and enter its name.
      4. diff --git a/doc/salome/gui/SMESH/input/point_marker.doc b/doc/salome/gui/SMESH/input/point_marker.doc index 40c2b932b..0a7b88e3b 100644 --- a/doc/salome/gui/SMESH/input/point_marker.doc +++ b/doc/salome/gui/SMESH/input/point_marker.doc @@ -33,14 +33,14 @@ lines in the file. Note that missing symbols are replaced by "0". Here is a texture file sample:
        -00111100
        -00111100
         11111111
        +10000001
        +10011001
        +10111101
        +10111101
        +10011001
        +10000001
         11111111
        -11111111
        -11111111
        -00111100
        -00111100
         
        \image html point_marker_widget2.png diff --git a/doc/salome/gui/SMESH/input/smeshpy_interface.doc b/doc/salome/gui/SMESH/input/smeshpy_interface.doc index e725ef99c..29ff056b7 100644 --- a/doc/salome/gui/SMESH/input/smeshpy_interface.doc +++ b/doc/salome/gui/SMESH/input/smeshpy_interface.doc @@ -2,44 +2,37 @@ \page smeshpy_interface_page Python interface -Python package smesh defines several classes, destined for easy and -clear mesh creation and edition. +Python API for SALOME %Mesh module defines several classes that can +be used for easy mesh creation and edition. -Documentation for smesh package is available in two forms: - -The
        structured -documentation for smesh package, where all methods and +Documentation for SALOME %Mesh module Python API is available in two forms: +- Structured documentation, where all methods and classes are grouped by their functionality, like it is done in the GUI documentation -and the \ref smeshDC "linear documentation for smesh package" -grouped only by classes, declared in the smesh.py file. - -The main page of the \ref smeshDC "linear documentation for smesh package" -contains a list of data structures and a list of -functions, provided by the package smesh.py. The first item in -the list of data structures (\ref smeshDC::smeshDC "class smesh") -also represents documentation for the methods of the package smesh.py itself. +- Linear documentation grouped only by classes, declared +in the \ref smesh and StdMeshersDC Python packages. -The package smesh.py provides an interface to create and handle -meshes. Use it to create an empty mesh or to import it from the data file. +Python package \ref smesh provides an interface to create and handle +meshes. It can be used to create an empty mesh or to import mesh from the data file. -Once a mesh has been created, it is possible to manage it via its own -methods, described at \ref smeshDC::Mesh "class Mesh" documentation -(it is also accessible by the second item "class Mesh" in the list of data structures). +As soon as mesh is created, it is possible to manage it via its own +methods, described in \ref smesh.Mesh "class Mesh" documentation. -Class \b Mesh allows assigning algorithms to a mesh. -Please note, that some algorithms, included in the standard SALOME -distribution are always available: +Class \ref smesh.Mesh "Mesh" allows assigning algorithms to a mesh. +Please note that some algorithms, included in the standard SALOME +distribution are always available. Python package \ref StdMeshersDC +provides an interface for standard meshing algorithms included into +the SALOME %Mesh module distribution, like: - REGULAR (1D) - COMPOSITE (1D) - MEFISTO (2D) - Quadrangle (2D) - Hexa(3D) -- etc... +- etc ... -To add hypotheses, use the interfaces, provided by the assigned -algorithms. +To add meshing hypotheses, it is possible to use the functions provided by the +algorithms interfaces. -Below you can see an example of usage of the package smesh for 3d mesh generation. +An example below demonstrates usage of the Python API for 3d mesh generation. \anchor example_3d_mesh

        Example of 3d mesh generation:

        @@ -118,7 +111,7 @@ tetra.Group(group) \endcode -Examples of Python scripts for all Mesh operations are available by +Examples of Python scripts for Mesh operations are available by the following links: - \subpage tui_creating_meshes_page diff --git a/doc/salome/gui/SMESH/input/tui_cartesian_algo.doc b/doc/salome/gui/SMESH/input/tui_cartesian_algo.doc index f1218439b..3eb7f0fe2 100644 --- a/doc/salome/gui/SMESH/input/tui_cartesian_algo.doc +++ b/doc/salome/gui/SMESH/input/tui_cartesian_algo.doc @@ -25,7 +25,7 @@ print "nb tetrahedra",mesh.NbTetras() print "nb polyhedra",mesh.NbPolyhedrons() print -# define the grid by sitting constant spacing +# define the grid by setting constant spacing cartHyp = cartAlgo.SetGrid( "10","10","10", 1000000) mesh.Compute() @@ -34,9 +34,9 @@ print "nb tetrahedra",mesh.NbTetras() print "nb polyhedra",mesh.NbPolyhedrons() -# define the grid by sitting different spacing in 2 sub-ranges of geometry +# define the grid by setting different spacing in 2 sub-ranges of geometry spaceFuns = ["5","10+10*t"] -cartAlgo.SetGrid( [spaceFuns, [0.5]], [spaceFuns, [0.5]], [spaceFuns, [0.25]], 2 ) +cartAlgo.SetGrid( [spaceFuns, [0.5]], [spaceFuns, [0.5]], [spaceFuns, [0.25]], 10 ) mesh.Compute() print "nb hexahedra",mesh.NbHexas() diff --git a/doc/salome/gui/SMESH/input/tui_defining_hypotheses.doc b/doc/salome/gui/SMESH/input/tui_defining_hypotheses.doc index e98eca6b4..d9e2b31f9 100644 --- a/doc/salome/gui/SMESH/input/tui_defining_hypotheses.doc +++ b/doc/salome/gui/SMESH/input/tui_defining_hypotheses.doc @@ -2,11 +2,48 @@ \page tui_defining_hypotheses_page Defining Hypotheses and Algorithms +This page provides example codes of \ref tui_defining_meshing_algos +"defining algorithms" and hypotheses. +
          +
        • Wire discretisation 1D algorithm +
            +
          • \ref tui_1d_arithmetic "Arithmetic 1D" hypothesis
          • +
          • \ref tui_deflection_1d "Deflection 1D and Number of Segments" hypotheses
          • +
          • \ref tui_start_and_end_length "Start and End Length" hypotheses
          • +
          • \ref tui_average_length "Local Length"
          • +
          • \ref tui_propagation "Propagation" additional hypothesis
          • +
          • \ref tui_fixed_points "Fixed Points 1D" hypothesis
          • +
          +
        • +
        • Triangle (Mefisto) 2D algorithm +
            +
          • \ref tui_max_element_area "Max Element Area" hypothesis
          • +
          • \ref tui_length_from_edges "Length from Edges" + hypothesis
          • +
          +
        • +
        • Tetrahedron (Netgen) 3D algorithm +
            +
          • \ref tui_max_element_volume "Max. Element Volume"hypothesis
          • +
          • \ref tui_viscous_layers "Viscous layers"
          • +
          +
        • +
        • \ref tui_projection "Projection Algorithms"
        • +
        • \ref tui_radial_quadrangle "Radial Quadrangle 1D2D" algorithm
        • +
        • Quadrangle (Mapping) 2D algorithm +
            +
          • \ref tui_quadrangle_parameters "Quadrangle Parameters" hypothesis
          • +
          +
        • +
        • \ref tui_import "Use Existing Elements" algorithm
        • +
        +
        +

        Defining 1D Hypotheses


        \anchor tui_1d_arithmetic -

        1D Arithmetic

        +

        Arithmetic 1D

        \code import geompy @@ -457,6 +494,40 @@ src_mesh.TranslateObject( src_mesh, MakeDirStruct( 210, 0, 0 ), Copy=False) \endcode +

        Projection 1D2D

        + +\code +# Project triangles from one meshed face to another mesh on the same box + +from smesh import * + +# Prepare geometry + +# Create a box +box = geompy.MakeBoxDXDYDZ(100, 100, 100) + +# Get geom faces to mesh with triangles in the 1ts and 2nd meshes +faces = geompy.SubShapeAll(box, geompy.ShapeType["FACE"]) +# 2 adjacent faces of the box +Face_1 = faces[2] +Face_2 = faces[0] + +geompy.addToStudy( box, 'box' ) +geompy.addToStudyInFather( box, Face_1, 'Face_1' ) +geompy.addToStudyInFather( box, Face_2, 'Face_2' ) + +# Make the source mesh with Netgem2D +src_mesh = Mesh(Face_1, "Source mesh") +src_mesh.Segment().NumberOfSegments(15) +src_mesh.Triangle() +src_mesh.Compute() + +# Mesh the target mesh using the algoritm Projection1D2D +tgt_mesh = smesh.Mesh(Face_2, "Target mesh") +tgt_mesh.Projection1D2D().SourceFace(Face_1,src_mesh) +tgt_mesh.Compute() +\endcode +
        \anchor tui_fixed_points diff --git a/doc/salome/gui/SMESH/input/tui_grouping_elements.doc b/doc/salome/gui/SMESH/input/tui_grouping_elements.doc index a163d13f5..3b769060a 100644 --- a/doc/salome/gui/SMESH/input/tui_grouping_elements.doc +++ b/doc/salome/gui/SMESH/input/tui_grouping_elements.doc @@ -98,23 +98,23 @@ critaria = [ \ ] filt = GetFilterFromCriteria( critaria ) filtGroup = mesh.GroupOnFilter( FACE, "group on filter", filt ) -print "Group on filter conatains %s elemens" % filtGroup.Size() +print "Group on filter contains %s elemens" % filtGroup.Size() # group on filter is updated if the mesh is modified hyp1D.SetStartLength( 2.5 ) hyp1D.SetEndLength( 2.5 ) mesh.Compute() -print "After mesh change, group on filter conatains %s elemens" % filtGroup.Size() +print "After mesh change, group on filter contains %s elemens" % filtGroup.Size() # set a new filter defining the group filt2 = GetFilter( FACE, FT_RangeOfIds, "1-50" ) filtGroup.SetFilter( filt2 ) -print "With a new filter, group on filter conatains %s elemens" % filtGroup.Size() +print "With a new filter, group on filter contains %s elemens" % filtGroup.Size() # group is updated at modification of the filter filt2.SetCriteria( [ GetCriterion( FACE, FT_RangeOfIds, "1-70" )]) filtIDs3 = filtGroup.GetIDs() -print "After filter modification, group on filter conatains %s elemens" % filtGroup.Size() +print "After filter modification, group on filter contains %s elemens" % filtGroup.Size() salome.sg.updateObjBrowser(1) \endcode diff --git a/doc/salome/gui/SMESH/input/tui_quality_controls.doc b/doc/salome/gui/SMESH/input/tui_quality_controls.doc index bc99172aa..2991eb521 100644 --- a/doc/salome/gui/SMESH/input/tui_quality_controls.doc +++ b/doc/salome/gui/SMESH/input/tui_quality_controls.doc @@ -164,8 +164,8 @@ mesh.RemoveElements(anIds) aBorders = mesh.GetFreeBorders() # create groups -aGroupF = mesh.CreateGroup(SMESH.FACE, "Faces with free edges") -aGroupN = mesh.CreateGroup(SMESH.NODE, "Nodes on free edges") +aGroupF = mesh.CreateEmptyGroup(smesh.FACE, "Faces with free edges") +aGroupN = mesh.CreateEmptyGroup(smesh.NODE, "Nodes on free edges") # fill groups with elements, corresponding to the criterion print "" diff --git a/doc/salome/gui/SMESH/input/uniting_set_of_triangles.doc b/doc/salome/gui/SMESH/input/uniting_set_of_triangles.doc index bcf153119..74e2ab2cd 100644 --- a/doc/salome/gui/SMESH/input/uniting_set_of_triangles.doc +++ b/doc/salome/gui/SMESH/input/uniting_set_of_triangles.doc @@ -7,7 +7,7 @@ once many triangles if they have adjacent edges. To union several triangles:
          -
        1. Display a mesh or a submesh in the 3D viewer.
        2. +
        3. Display a mesh or a sub-mesh in the 3D viewer.
        4. In the \b Modification menu select the Union of triangles item or click "Union of triangles" button in the toolbar. @@ -27,11 +27,10 @@ elements from the list click the \b Remove button. The \b Sort button allows to sort the list of IDs. The Set filter button allows to apply a definite filter to selection of triangles.
        5. Apply to all radio button allows to modify connectivity and -type of all triangles of the currently displayed mesh or submesh.
        6. -
        7. \b Criterion menu allows to apply the operation only to those -object which meet the chosen criterion (from the list of Quality -Controls, i.e. Skew, Warping, Minimum Angle, etc.)
        8. -
        9. Select from set of fields allows to choose a submesh or an +type of all triangles of the currently displayed mesh or sub-mesh.
        10. +
        11. \b Criterion menu allows to chose a quality criterion + optimization of which will be used to select triangles to unite.
        12. +
        13. Select from set of fields allows to choose a sub-mesh or an existing group whose triangle elements will be automatically added to the list.
        14. diff --git a/idl/SMESH_Gen.idl b/idl/SMESH_Gen.idl index f6e9f89ad..b8d3176f2 100644 --- a/idl/SMESH_Gen.idl +++ b/idl/SMESH_Gen.idl @@ -101,7 +101,8 @@ module SMESH COMPERR_ALGO_FAILED , // computation failed COMPERR_BAD_SHAPE , // bad geometry COMPERR_WARNING , // algo reports error but sub-mesh is computed anyway - COMPERR_CANCELED // compute canceled + COMPERR_CANCELED , // compute canceled + COMPERR_NO_MESH_ON_SHAPE // no mesh elements assigned to sub-mesh }; struct ComputeError { @@ -237,6 +238,13 @@ module SMESH out SMESH::DriverMED_ReadStatus theStatus ) raises ( SALOME::SALOME_Exception ); + /*! + * Create Mesh object importing data from given GMF file + */ + SMESH_Mesh CreateMeshesFromGMF( in string theFileName, + out SMESH::ComputeError theError) + raises ( SALOME::SALOME_Exception ); + /*! * Create a mesh by copying a part of another mesh * \param meshPart - a part of mesh to copy diff --git a/idl/SMESH_Hypothesis.idl b/idl/SMESH_Hypothesis.idl index 8d18789ba..f2e43788e 100644 --- a/idl/SMESH_Hypothesis.idl +++ b/idl/SMESH_Hypothesis.idl @@ -80,29 +80,29 @@ module SMESH * \param theParameters is a string containing the notebook variables separated by ":" symbol, * used for Hypothesis creation */ - void SetParameters (in string theParameters); - - /*! - * Return list of notebook variables used for Hypothesis creation separated by ":" symbol - */ - string GetParameters(); - - /*! - * Return list of last notebook variables used for Hypothesis creation. - */ - ListOfParameters GetLastParameters(); - - /*! - * Set list of parameters - * \param theParameters is a string containing the last notebook variables separated by ":" symbol, - * used for Hypothesis creation - */ - void SetLastParameters(in string theParameters); + // void SetParameters (in string theParameters); + + // /*! + // * Return list of notebook variables used for Hypothesis creation separated by ":" symbol + // */ + // string GetParameters(); + + // /*! + // * Return list of last notebook variables used for Hypothesis creation. + // */ + // ListOfParameters GetLastParameters(); + + // /*! + // * Set list of parameters + // * \param theParameters is a string containing the last notebook variables separated by ":" symbol, + // * used for Hypothesis creation + // */ + // void SetLastParameters(in string theParameters); - /*! - * Clear parameters list - */ - void ClearParameters(); + // /*! + // * Clear parameters list + // */ + // void ClearParameters(); /*! * Verify whether hypothesis supports given entity type diff --git a/idl/SMESH_Mesh.idl b/idl/SMESH_Mesh.idl index 409bb4e6e..b8d2b5e63 100644 --- a/idl/SMESH_Mesh.idl +++ b/idl/SMESH_Mesh.idl @@ -652,7 +652,7 @@ module SMESH string GetVersionString(in MED_VERSION version, in short nbDigits); /*! - * Export Mesh to DAT, UNV and STL Formats + * Export Mesh to different Formats * (UNV supported version is I-DEAS 10) */ void ExportDAT( in string file ) raises (SALOME::SALOME_Exception); @@ -662,6 +662,8 @@ module SMESH void ExportCGNS( in SMESH_IDSource meshPart, in string file, in boolean overwrite ) raises (SALOME::SALOME_Exception); + void ExportGMF( in SMESH_IDSource meshPart, + in string file ) raises (SALOME::SALOME_Exception); void ExportPartToDAT( in SMESH_IDSource meshPart, in string file ) raises (SALOME::SALOME_Exception); void ExportPartToUNV( in SMESH_IDSource meshPart, diff --git a/idl/SMESH_MeshEditor.idl b/idl/SMESH_MeshEditor.idl index 561c5b884..08f2b70f2 100644 --- a/idl/SMESH_MeshEditor.idl +++ b/idl/SMESH_MeshEditor.idl @@ -25,6 +25,7 @@ #define _SMESH_MESHEDITOR_IDL_ #include "SMESH_Mesh.idl" +#include "SMESH_Gen.idl" module SMESH { @@ -34,8 +35,34 @@ module SMESH * This interface makes modifications on the Mesh - removing elements and nodes etc. */ interface NumericalFunctor; + interface SMESH_MeshEditor { + /*! + * Return data of mesh edition preview which is computed provided + * that the editor was obtained trough SMESH_Mesh::GetMeshEditPreviewer() + */ + MeshPreviewStruct GetPreviewData(); + + /*! + * If during last operation of MeshEditor some nodes were + * created this method returns list of their IDs, if new nodes + * not created - returns empty list + */ + long_array GetLastCreatedNodes(); + + /*! + * If during last operation of MeshEditor some elements were + * created this method returns list of their IDs, if new elements + * not created - returns empty list + */ + long_array GetLastCreatedElems(); + + /*! + * \brief Returns description of an error/warning occured during the last operation + */ + ComputeError GetLastError(); + /*! * \brief Wrap a sequence of ids in a SMESH_IDSource * \param IDsOfElements list of mesh elements identifiers @@ -802,26 +829,6 @@ module SMESH */ boolean ChangeElemNodes(in long ide, in long_array newIDs); - /*! - * Return data of mesh edition preview which is computed provided - * that the editor was obtained trough SMESH_Mesh::GetMeshEditPreviewer() - */ - MeshPreviewStruct GetPreviewData(); - - /*! - * If during last operation of MeshEditor some nodes were - * created this method returns list of it's IDs, if new nodes - * not creared - returns empty list - */ - long_array GetLastCreatedNodes(); - - /*! - * If during last operation of MeshEditor some elements were - * created this method returns list of it's IDs, if new elements - * not creared - returns empty list - */ - long_array GetLastCreatedElems(); - /*! * \brief Creates a hole in a mesh by doubling the nodes of some particular elements * \param theNodes - identifiers of nodes to be doubled @@ -1038,6 +1045,21 @@ module SMESH in ListOfGroups theNodesNot, in GEOM::GEOM_Object theShape ); + /*! + * \brief Identify the elements that will be affected by node duplication (actual duplication is not performed). + * This method is the first step of DoubleNodeElemGroupsInRegion. + * \param theElems - list of groups of elements (edges or faces) to be replicated + * \param theNodesNot - list of groups of nodes not to replicated + * \param theShape - shape to detect affected elements (element which geometric center + * located on or inside shape). + * The replicated nodes should be associated to affected elements. + * \return groups of affected elements + * \sa DoubleNodeElemGroupsInRegion() + */ + ListOfGroups AffectedElemGroupsInRegion( in ListOfGroups theElems, + in ListOfGroups theNodesNot, + in GEOM::GEOM_Object theShape ); + /*! * \brief Generates skin mesh (containing 2D cells) from 3D mesh * The created 2D mesh elements based on nodes of free faces of boundary volumes @@ -1117,6 +1139,18 @@ module SMESH * \return TRUE if operation has been completed successfully, FALSE otherwise */ boolean CreateFlatElementsOnFacesGroups( in ListOfGroups theGroupsOfFaces ); + + /*! + * \brief identify all the elements around a geom shape, get the faces delimiting the hole + * Build groups of volume to remove, groups of faces to replace on the skin of the object, + * groups of faces to remove insidethe object, (idem edges). + * Build ordered list of nodes at the border of each group of faces to replace (to be used to build a geom subshape) + */ + void CreateHoleSkin(in double radius, + in GEOM::GEOM_Object theShape, + in string groupName, + in double_array theNodesCoords, + out array_of_long_array GroupsOfNodes) raises (SALOME::SALOME_Exception); }; }; diff --git a/resources/SalomeApp.xml.in b/resources/SalomeApp.xml.in index 0dbcc2e88..20be22917 100644 --- a/resources/SalomeApp.xml.in +++ b/resources/SalomeApp.xml.in @@ -28,12 +28,14 @@ + + - + @@ -41,6 +43,7 @@ + diff --git a/resources/StdMeshers.xml b/resources/StdMeshers.xml index 0d519fc57..b82d6a441 100644 --- a/resources/StdMeshers.xml +++ b/resources/StdMeshers.xml @@ -55,7 +55,7 @@ dim="1"/> @@ -75,18 +75,18 @@ dim="1"/> @@ -184,14 +184,14 @@ Projection_2D=Projection2D() - ProjectionSource2D=SourceFace(SetSourceFace(),SetSourceMesh(),SetVertexAssociation(1),SetVertexAssociation(2),SetVertexAssociation(3),SetVertexAssociation(4)) + ProjectionSource2D=SourceFace(SetSourceFace(),SetSourceMesh(),SetVertexAssociation(1),SetVertexAssociation(3),SetVertexAssociation(2),SetVertexAssociation(4)) @@ -329,12 +329,12 @@ dim="3"> Projection_3D=Projection3D() - ProjectionSource3D=SourceShape3D(SetSource3DShape(),SetSourceMesh(),SetVertexAssociation(1),SetVertexAssociation(2),SetVertexAssociation(3),SetVertexAssociation(4)) + ProjectionSource3D=SourceShape3D(SetSource3DShape(),SetSourceMesh(),SetVertexAssociation(1),SetVertexAssociation(3),SetVertexAssociation(2),SetVertexAssociation(4)) @@ -381,7 +381,7 @@ TFaceIt; - std::set checkedFaces, checkedNodes; - std::list faceQueue( 1, face ); + std::set< SMESH_TLink > checkedLinks; + + std::list< pair< const SMDS_MeshElement*, gp_Vec > > faceQueue; + faceQueue.push_back( make_pair( face, myNorm )); while ( !faceQueue.empty() ) { - face = faceQueue.front(); - if ( checkedFaces.insert( face ).second ) + face = faceQueue.front().first; + myNorm = faceQueue.front().second; + faceQueue.pop_front(); + + for ( int i = 0, nbN = face->NbCornerNodes(); i < nbN; ++i ) { - gp_Vec norm = getNormale( static_cast(face), &normOK ); - if (!normOK || myNorm.Angle( norm ) <= radianTol) + const SMDS_MeshNode* n1 = face->GetNode( i ); + const SMDS_MeshNode* n2 = face->GetNode(( i+1 )%nbN); + if ( !checkedLinks.insert( SMESH_TLink( n1, n2 )).second ) + continue; + SMDS_ElemIteratorPtr fIt = n1->GetInverseElementIterator(SMDSAbs_Face); + while ( fIt->more() ) { - myCoplanarIDs.insert( face->GetID() ); - std::set neighborFaces; - for ( int i = 0; i < face->NbCornerNodes(); ++i ) + const SMDS_MeshElement* f = fIt->next(); + if ( f->GetNodeIndex( n2 ) > -1 ) { - const SMDS_MeshNode* n = face->GetNode( i ); - if ( checkedNodes.insert( n ).second ) - neighborFaces.insert( TFaceIt( n->GetInverseElementIterator(SMDSAbs_Face)), - TFaceIt()); + gp_Vec norm = getNormale( static_cast(f), &normOK ); + if (!normOK || myNorm.Angle( norm ) <= radianTol) + { + myCoplanarIDs.insert( f->GetID() ); + faceQueue.push_back( make_pair( f, norm )); + } } - faceQueue.insert( faceQueue.end(), neighborFaces.begin(), neighborFaces.end() ); } } - faceQueue.pop_front(); } } } @@ -2770,7 +2777,7 @@ bool CoplanarFaces::IsSatisfy( long theElementId ) } /* - *Class : RangeOfIds + *Class : RangeOfIds *Description : Predicate for Range of Ids. * Range may be specified with two ways. * 1. Using AddToRange method diff --git a/src/Driver/Driver_Mesh.cxx b/src/Driver/Driver_Mesh.cxx index 73895176f..c04008f94 100644 --- a/src/Driver/Driver_Mesh.cxx +++ b/src/Driver/Driver_Mesh.cxx @@ -26,13 +26,16 @@ // #include "Driver_Mesh.h" +#include "SMESH_Comment.hxx" + #include using namespace std; Driver_Mesh::Driver_Mesh(): myFile(""), - myMeshId(-1) + myMeshId(-1), + myStatus( DRS_OK ) {} @@ -78,5 +81,23 @@ Driver_Mesh::Status Driver_Mesh::addMessage(const std::string& msg, #ifdef _DEBUG_ cout << msg << endl; #endif - return isFatal ? DRS_FAIL : DRS_WARN_SKIP_ELEM; + return ( myStatus = isFatal ? DRS_FAIL : DRS_WARN_SKIP_ELEM ); +} + +//================================================================================ +/*! + * \brief Return a structure containing description of errors + */ +//================================================================================ + +SMESH_ComputeErrorPtr Driver_Mesh::GetError() +{ + SMESH_Comment msg; + for ( size_t i = 0; i < myErrorMessages.size(); ++i ) + { + msg << myErrorMessages[i]; + if ( i+1 < myErrorMessages.size() ) + msg << "\n"; + } + return SMESH_ComputeError::New( myStatus == DRS_OK ? int(COMPERR_OK) : int(myStatus), msg ); } diff --git a/src/Driver/Driver_Mesh.h b/src/Driver/Driver_Mesh.h index 45861a82a..fcaea2b3e 100644 --- a/src/Driver/Driver_Mesh.h +++ b/src/Driver/Driver_Mesh.h @@ -27,6 +27,8 @@ #ifndef _INCLUDE_DRIVER_MESH #define _INCLUDE_DRIVER_MESH +#include "SMESH_ComputeError.hxx" + #include #include @@ -55,19 +57,26 @@ class MESHDRIVER_EXPORT Driver_Mesh DRS_FAIL // general failure (exception etc.) }; - virtual Status Perform() = 0; - void SetMeshId(int theMeshId); - void SetFile(const std::string& theFileName); - virtual void SetMeshName(const std::string& theMeshName); + void SetMeshId(int theMeshId); + void SetFile(const std::string& theFileName); + virtual void SetMeshName(const std::string& theMeshName); virtual std::string GetMeshName() const; + virtual void SetOption(const std::string& optionName, + const std::string& optionValue) {} + + virtual Status Perform() = 0; + + virtual SMESH_ComputeErrorPtr GetError(); + protected: std::string myFile; std::string myMeshName; - int myMeshId; + int myMeshId; Status addMessage(const std::string& msg, const bool isFatal=false); std::vector< std::string > myErrorMessages; + Status myStatus; }; #endif diff --git a/src/Driver/Makefile.am b/src/Driver/Makefile.am index 0062ee774..a088c773a 100644 --- a/src/Driver/Makefile.am +++ b/src/Driver/Makefile.am @@ -44,8 +44,10 @@ dist_libMeshDriver_la_SOURCES = \ # additionnal information to compil and link file libMeshDriver_la_CPPFLAGS = \ + $(BOOST_CPPFLAGS) \ $(CAS_CPPFLAGS) \ $(KERNEL_CXXFLAGS) \ + -I$(srcdir)/../SMESHUtils \ -I$(srcdir)/../SMESHDS libMeshDriver_la_LDFLAGS = \ diff --git a/src/DriverCGNS/DriverCGNS_Write.cxx b/src/DriverCGNS/DriverCGNS_Write.cxx index 517a56f25..edc474163 100644 --- a/src/DriverCGNS/DriverCGNS_Write.cxx +++ b/src/DriverCGNS/DriverCGNS_Write.cxx @@ -139,7 +139,7 @@ namespace } { static int ids[] = { 0,3,2,1,4,7,6,5,11,10,9,8,12,15,14,13,19,18,17,16, - 20, 24,23,22,21, 25}; + 20, 24,23,22,21, 25, 26}; interlaces[SMDSEntity_TriQuad_Hexa] = ids; cgTypes [SMDSEntity_TriQuad_Hexa] = CGNS_ENUMV( HEXA_27 ); } diff --git a/src/DriverDAT/Makefile.am b/src/DriverDAT/Makefile.am index 338bc1d17..232551eb3 100644 --- a/src/DriverDAT/Makefile.am +++ b/src/DriverDAT/Makefile.am @@ -52,6 +52,7 @@ libMeshDriverDAT_la_CPPFLAGS = \ $(BOOST_CPPFLAGS) \ -I$(srcdir)/../Driver \ -I$(srcdir)/../SMDS \ + -I$(srcdir)/../SMESHUtils \ -I$(srcdir)/../SMESHDS libMeshDriverDAT_la_LDFLAGS = \ diff --git a/src/DriverGMF/DriverGMF_Read.cxx b/src/DriverGMF/DriverGMF_Read.cxx new file mode 100644 index 000000000..332519b2e --- /dev/null +++ b/src/DriverGMF/DriverGMF_Read.cxx @@ -0,0 +1,357 @@ +// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// 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, Read 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 : DriverGMF_Read.cxx +// Created : Mon Sep 17 17:03:02 2012 +// Author : Edward AGAPOV (eap) + +#include "DriverGMF_Read.hxx" +#include "DriverGMF_Write.hxx" + +#include "SMESHDS_Group.hxx" +#include "SMESHDS_Mesh.hxx" +#include "SMESH_Comment.hxx" + +extern "C" +{ +#include "libmesh5.h" +} + +#include + +// -------------------------------------------------------------------------------- +// Closing GMF mesh at destruction +DriverGMF_MeshCloser::~DriverGMF_MeshCloser() +{ + if ( _gmfMeshID ) + GmfCloseMesh( _gmfMeshID ); +} +// -------------------------------------------------------------------------------- +DriverGMF_Read::DriverGMF_Read(): + Driver_SMESHDS_Mesh() +{ +} +// -------------------------------------------------------------------------------- +DriverGMF_Read::~DriverGMF_Read() +{ +} + +//================================================================================ +/*! + * \brief Read a GMF file + */ +//================================================================================ + +Driver_Mesh::Status DriverGMF_Read::Perform() +{ + Status status = DRS_OK; + + int dim, version; + + // open the file + int meshID = GmfOpenMesh( myFile.c_str(), GmfRead, &version, &dim ); + if ( !meshID ) + return addMessage( SMESH_Comment("Can't open for reading ") << myFile, /*fatal=*/true ); + + DriverGMF_MeshCloser aMeshCloser( meshID ); // An object closing GMF mesh at destruction + + // Read nodes + + int nbNodes = GmfStatKwd(meshID, GmfVertices); + if ( nbNodes < 1 ) + return addMessage( "No nodes in the mesh", /*fatal=*/true ); + + GmfGotoKwd(meshID, GmfVertices); + + int ref; + + const int nodeIDShift = myMesh->GetMeshInfo().NbNodes(); + if ( version != GmfFloat ) + { + double x, y, z; + for ( int i = 1; i <= nbNodes; ++i ) + { + GmfGetLin(meshID, GmfVertices, &x, &y, &z, &ref); + myMesh->AddNodeWithID( x,y,z, nodeIDShift + i); + } + } + else + { + float x, y, z; + for ( int i = 1; i <= nbNodes; ++i ) + { + GmfGetLin(meshID, GmfVertices, &x, &y, &z, &ref); + myMesh->AddNodeWithID( x,y,z, nodeIDShift + i); + } + } + + // Read elements + + int iN[28]; + + /* Read edges */ + const int edgeIDShift = myMesh->GetMeshInfo().NbElements(); + if ( int nbEdges = GmfStatKwd(meshID, GmfEdges)) + { + GmfGotoKwd(meshID, GmfEdges); + for ( int i = 1; i <= nbEdges; ++i ) + { + GmfGetLin(meshID, GmfEdges, &iN[0], &iN[1], &ref); + if ( !myMesh->AddEdgeWithID( iN[0], iN[1], edgeIDShift + i )) + status = storeBadNodeIds( "GmfEdges",i, 2, iN[0], iN[1] ); + } + } + /* Read quadratic edges */ + const int edge2IDShift = myMesh->GetMeshInfo().NbElements(); + if ( int nbEdges = GmfStatKwd(meshID, GmfEdgesP2)) + { + GmfGotoKwd(meshID, GmfEdgesP2); + for ( int i = 1; i <= nbEdges; ++i ) + { + GmfGetLin(meshID, GmfEdgesP2, &iN[0], &iN[1], &iN[2], &ref); + if ( !myMesh->AddEdgeWithID( iN[0], iN[1], iN[2], edge2IDShift + i )) + status = storeBadNodeIds( "GmfEdgesP2",i, 3, iN[0], iN[1], iN[2] ); + } + } + /* Read triangles */ + const int triaIDShift = myMesh->GetMeshInfo().NbElements(); + if ( int nbTria = GmfStatKwd(meshID, GmfTriangles)) + { + GmfGotoKwd(meshID, GmfTriangles); + for ( int i = 1; i <= nbTria; ++i ) + { + GmfGetLin(meshID, GmfTriangles, &iN[0], &iN[1], &iN[2], &ref); + if ( !myMesh->AddFaceWithID( iN[0], iN[1], iN[2], triaIDShift + i )) + status = storeBadNodeIds( "GmfTriangles",i, 3, iN[0], iN[1], iN[2] ); + } + } + /* Read quadratic triangles */ + const int tria2IDShift = myMesh->GetMeshInfo().NbElements(); + if ( int nbTria = GmfStatKwd(meshID, GmfTrianglesP2)) + { + GmfGotoKwd(meshID, GmfTrianglesP2); + for ( int i = 1; i <= nbTria; ++i ) + { + GmfGetLin(meshID, GmfTrianglesP2, + &iN[0], &iN[1], &iN[2], &iN[3], &iN[4], &iN[5], &ref); + if ( !myMesh->AddFaceWithID( iN[0],iN[1],iN[2],iN[3],iN[4],iN[5], + tria2IDShift + i )) + status = storeBadNodeIds( "GmfTrianglesP2",i, 6, iN[0],iN[1],iN[2],iN[3],iN[4],iN[5] ); + } + } + /* Read quadrangles */ + const int quadIDShift = myMesh->GetMeshInfo().NbElements(); + if ( int nbQuad = GmfStatKwd(meshID, GmfQuadrilaterals)) + { + GmfGotoKwd(meshID, GmfQuadrilaterals); + for ( int i = 1; i <= nbQuad; ++i ) + { + GmfGetLin(meshID, GmfQuadrilaterals, &iN[0], &iN[1], &iN[2], &iN[3], &ref); + if ( !myMesh->AddFaceWithID( iN[0], iN[1], iN[2], iN[3], quadIDShift + i )) + status = storeBadNodeIds( "GmfQuadrilaterals",i, 4, iN[0], iN[1],iN[2], iN[3] ); + } + } + /* Read bi-quadratic quadrangles */ + const int quad2IDShift = myMesh->GetMeshInfo().NbElements(); + if ( int nbQuad = GmfStatKwd(meshID, GmfQuadrilateralsQ2)) + { + GmfGotoKwd(meshID, GmfQuadrilateralsQ2); + for ( int i = 1; i <= nbQuad; ++i ) + { + GmfGetLin(meshID, GmfQuadrilateralsQ2, + &iN[0], &iN[1], &iN[2], &iN[3], &iN[4], &iN[5], &iN[6], &iN[7], &iN[8], &ref); + if ( !myMesh->AddFaceWithID( iN[0],iN[1],iN[2],iN[3],iN[4],iN[5],iN[6],iN[7],iN[8], + quad2IDShift + i )) + status = storeBadNodeIds( "GmfQuadrilateralsQ2",i, + 9, iN[0],iN[1],iN[2],iN[3],iN[4],iN[5],iN[6],iN[7],iN[8] ); + } + } + /* Read terahedra */ + const int tetIDShift = myMesh->GetMeshInfo().NbElements(); + if ( int nbTet = GmfStatKwd(meshID, GmfTetrahedra)) + { + GmfGotoKwd(meshID, GmfTetrahedra); + for ( int i = 1; i <= nbTet; ++i ) + { + GmfGetLin(meshID, GmfTetrahedra, &iN[0], &iN[1], &iN[2], &iN[3], &ref); + if ( !myMesh->AddVolumeWithID( iN[0], iN[2], iN[1], iN[3], tetIDShift + i )) + status = storeBadNodeIds( "GmfTetrahedra",i, 4, iN[0], iN[1],iN[2], iN[3] ); + } + } + /* Read quadratic terahedra */ + const int tet2IDShift = myMesh->GetMeshInfo().NbElements(); + if ( int nbTet = GmfStatKwd(meshID, GmfTetrahedraP2)) + { + GmfGotoKwd(meshID, GmfTetrahedraP2); + for ( int i = 1; i <= nbTet; ++i ) + { + GmfGetLin(meshID, GmfTetrahedraP2, &iN[0], &iN[1], &iN[2], + &iN[3], &iN[4], &iN[5], &iN[6], &iN[7], &iN[8], &iN[9], &ref); + if ( !myMesh->AddVolumeWithID( iN[0],iN[2],iN[1],iN[3], + iN[6],iN[5],iN[4], + iN[7],iN[9],iN[8], tet2IDShift + i )) + status = storeBadNodeIds( "GmfTetrahedraP2",i, 10, iN[0],iN[1],iN[2],iN[3], + iN[4],iN[5],iN[6],iN[7],iN[8],iN[9] ); + } + } + /* Read pyramids */ + const int pyrIDShift = myMesh->GetMeshInfo().NbElements(); + if ( int nbPyr = GmfStatKwd(meshID, GmfPyramids)) + { + GmfGotoKwd(meshID, GmfPyramids); + for ( int i = 1; i <= nbPyr; ++i ) + { + GmfGetLin(meshID, GmfPyramids, &iN[0], &iN[1], &iN[2], &iN[3], &iN[4], &ref); + if ( !myMesh->AddVolumeWithID( iN[0], iN[2], iN[1], iN[3], iN[4], pyrIDShift + i )) + status = storeBadNodeIds( "GmfPyramids",i, 5, iN[0], iN[1],iN[2], iN[3], iN[4] ); + } + } + /* Read hexahedra */ + const int hexIDShift = myMesh->GetMeshInfo().NbElements(); + if ( int nbHex = GmfStatKwd(meshID, GmfHexahedra)) + { + GmfGotoKwd(meshID, GmfHexahedra); + for ( int i = 1; i <= nbHex; ++i ) + { + GmfGetLin(meshID, GmfHexahedra, + &iN[0], &iN[1], &iN[2], &iN[3], &iN[4], &iN[5], &iN[6], &iN[7], &ref); + if ( !myMesh->AddVolumeWithID( iN[0], iN[3], iN[2], iN[1], iN[4], iN[7], iN[6], iN[5], + hexIDShift + i)) + status = storeBadNodeIds( "GmfHexahedra",i, + 8, iN[0], iN[1],iN[2], iN[3], iN[4], iN[7], iN[6], iN[5] ); + } + } + /* Read tri-quadratic hexahedra */ + const int hex2IDShift = myMesh->GetMeshInfo().NbElements(); + if ( int nbHex = GmfStatKwd(meshID, GmfHexahedraQ2)) + { + GmfGotoKwd(meshID, GmfHexahedraQ2); + for ( int i = 1; i <= nbHex; ++i ) + { + GmfGetLin(meshID, GmfHexahedraQ2, &iN[0], &iN[1], &iN[2], &iN[3], &iN[4], &iN[5], + &iN[6], &iN[7], &iN[8],&iN[9],&iN[10],&iN[11],&iN[12],&iN[13],&iN[14], + &iN[15],&iN[16],&iN[17],&iN[18],&iN[19],&iN[20],&iN[21],&iN[22],&iN[23], + &iN[24],&iN[25],&iN[26], &ref); + if ( !myMesh->AddVolumeWithID( iN[0],iN[3],iN[2],iN[1],iN[4],iN[7],iN[6],iN[5],iN[11],iN[10], + iN[9],iN[8],iN[12],iN[15],iN[14], iN[13],iN[19],iN[18],iN[17], + iN[16],iN[20],iN[24],iN[23],iN[22],iN[21], iN[25],iN[26], + hex2IDShift + i )) + status = storeBadNodeIds( "GmfHexahedraQ2",i, 27, + iN[0],iN[3],iN[2],iN[1],iN[4], iN[7],iN[6],iN[5],iN[11],iN[10], + iN[9],iN[8],iN[12],iN[15],iN[14], iN[13],iN[19],iN[18],iN[17], + iN[16],iN[20],iN[24],iN[23],iN[22],iN[21], iN[25],iN[26]); + } + } + /* Read prism */ + const int prismIDShift = myMesh->GetMeshInfo().NbElements(); + if ( int nbPrism = GmfStatKwd(meshID, GmfPrisms)) + { + GmfGotoKwd(meshID, GmfPrisms); + for ( int i = 1; i <= nbPrism; ++i ) + { + GmfGetLin(meshID, GmfPrisms, + &iN[0], &iN[1], &iN[2], &iN[3], &iN[4], &iN[5], &ref); + if ( !myMesh->AddVolumeWithID( iN[0], iN[2], iN[1], iN[3], iN[5], iN[4], prismIDShift + i)) + status = storeBadNodeIds( "GmfPrisms",i, + 6, iN[0], iN[1],iN[2], iN[3], iN[4], iN[5] ); + } + } + + // Read required entities into groups + + // get ids of existing groups + std::set< int > groupIDs; + const std::set& groups = myMesh->GetGroups(); + std::set::const_iterator grIter = groups.begin(); + for ( ; grIter != groups.end(); ++grIter ) + groupIDs.insert( (*grIter)->GetID() ); + if ( groupIDs.empty() ) groupIDs.insert( 0 ); + + const int kes[4][3] = { { GmfRequiredVertices, SMDSAbs_Node, nodeIDShift }, + { GmfRequiredEdges, SMDSAbs_Edge, edgeIDShift }, + { GmfRequiredTriangles, SMDSAbs_Face, triaIDShift }, + { GmfRequiredQuadrilaterals,SMDSAbs_Face, quadIDShift }}; + const char* names[4] = { "_required_Vertices" , + "_required_Edges" , + "_required_Triangles" , + "_required_Quadrilaterals" }; + for ( int i = 0; i < 4; ++i ) + { + int gmfKwd = kes[i][0]; + SMDSAbs_ElementType entity = (SMDSAbs_ElementType) kes[i][1]; + int shift = kes[i][2]; + if ( int nb = GmfStatKwd(meshID, gmfKwd)) + { + const int newID = *groupIDs.rbegin() + 1; + groupIDs.insert( newID ); + SMESHDS_Group* group = new SMESHDS_Group( newID, myMesh, entity ); + group->SetStoreName( names[i] ); + myMesh->AddGroup( group ); + + GmfGotoKwd(meshID, gmfKwd); + for ( int i = 0; i < nb; ++i ) + { + GmfGetLin(meshID, gmfKwd, &iN[0] ); + group->Add( shift + iN[0] ); + } + } + } + + return status; +} + +//================================================================================ +/*! + * \brief Store a message about invalid IDs of nodes + */ +//================================================================================ + +Driver_Mesh::Status DriverGMF_Read::storeBadNodeIds(const char* gmfKwd, int elemNb, int nb, ...) +{ + if ( myStatus != DRS_OK ) + return myStatus; + + SMESH_Comment msg; + + va_list VarArg; + va_start(VarArg, nb); + + for ( int i = 0; i < nb; ++i ) + { + int id = va_arg(VarArg, int ); + if ( !myMesh->FindNode( id )) + msg << " " << id; + } + va_end(VarArg); + + if ( !msg.empty() ) + { + std::string nbStr; + const char* nbNames[] = { "1-st ", "2-nd ", "3-d " }; + if ( elemNb < 3 ) nbStr = nbNames[ elemNb-1 ]; + else nbStr = SMESH_Comment(elemNb) << "-th "; + + return addMessage + ( SMESH_Comment("Wrong node IDs of ")<< nbStr << gmfKwd << ":" << msg, + /*fatal=*/false ); + } + return DRS_OK; +} diff --git a/src/SMESH/SMESH_3D_Algo.hxx b/src/DriverGMF/DriverGMF_Read.hxx similarity index 56% rename from src/SMESH/SMESH_3D_Algo.hxx rename to src/DriverGMF/DriverGMF_Read.hxx index 2b64d9eb0..a003804f0 100644 --- a/src/SMESH/SMESH_3D_Algo.hxx +++ b/src/DriverGMF/DriverGMF_Read.hxx @@ -14,32 +14,44 @@ // 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 +// License along with this library; if not, Read 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 : DriverGMF_Read.hxx +// Created : Mon Sep 17 15:36:47 2012 +// Author : Edward AGAPOV (eap) -// SMESH SMESH : implementaion of SMESH idl descriptions -// File : SMESH_3D_Algo.hxx -// Author : Paul RASCLE, EDF -// Module : SMESH -// $Header$ -// -#ifndef _SMESH_3D_ALGO_HXX_ -#define _SMESH_3D_ALGO_HXX_ -#include "SMESH_SMESH.hxx" +#ifndef __DriverGMF_Read_HXX__ +#define __DriverGMF_Read_HXX__ + +#include "SMESH_DriverGMF.hxx" -#include "SMESH_Algo.hxx" +#include "Driver_SMESHDS_Mesh.h" -class SMESH_EXPORT SMESH_3D_Algo: - public SMESH_Algo +#include +#include + +/*! + * \brief Driver reading a mesh from the GMF file. The mesh to read is selected by + * an index (counted form 0) set via SetMeshId() + */ +class MESHDriverGMF_EXPORT DriverGMF_Read : public Driver_SMESHDS_Mesh { public: - SMESH_3D_Algo(int hypId, int studyId, SMESH_Gen* gen); - virtual ~SMESH_3D_Algo(); + + DriverGMF_Read(); + ~DriverGMF_Read(); + + virtual Status Perform(); + + private: + + Status storeBadNodeIds(const char* gmfKwd, int elemNb, int nb, ...); }; + #endif diff --git a/src/DriverGMF/DriverGMF_Write.cxx b/src/DriverGMF/DriverGMF_Write.cxx new file mode 100644 index 000000000..cdddd629d --- /dev/null +++ b/src/DriverGMF/DriverGMF_Write.cxx @@ -0,0 +1,317 @@ +// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// 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 : DriverGMF_Write.cxx +// Created : Mon Sep 17 17:03:02 2012 +// Author : Edward AGAPOV (eap) + +#include "DriverGMF_Write.hxx" + +#include "SMESHDS_GroupBase.hxx" +#include "SMESHDS_Mesh.hxx" +#include "SMESH_Comment.hxx" + +extern "C" +{ +#include "libmesh5.h" +} + +#include + +#define BEGIN_ELEM_WRITE( SMDSEntity, GmfKwd, elem ) \ + elemIt = myMesh->elementEntityIterator( SMDSEntity ); \ + if ( elemIt->more() ) \ + { \ + GmfSetKwd(meshID, GmfKwd, myMesh->GetMeshInfo().NbEntities( SMDSEntity )); \ + for ( int gmfID = 1; elemIt->more(); ++gmfID ) \ + { \ + const SMDS_MeshElement* elem = elemIt->next(); \ + GmfSetLin(meshID, GmfKwd, + +#define END_ELEM_WRITE( elem ) \ + elem->getshapeId() ); \ + }} \ + +#define END_ELEM_WRITE_ADD_TO_MAP( elem, e2id ) \ + elem->getshapeId() ); \ + e2id.insert( e2id.end(), make_pair( elem, gmfID )); \ + }} \ + + +DriverGMF_Write::DriverGMF_Write(): + Driver_SMESHDS_Mesh() +{ +} +DriverGMF_Write::~DriverGMF_Write() +{ +} + +Driver_Mesh::Status DriverGMF_Write::Perform() +{ + const int dim = 3, version = 3; + + int meshID = GmfOpenMesh( myFile.c_str(), GmfWrite, version, dim ); + if ( !meshID ) + return addMessage( SMESH_Comment("Can't open for writing ") << myFile, /*fatal=*/true ); + + DriverGMF_MeshCloser aMeshCloser( meshID ); // An object closing GMF mesh at destruction + + // nodes + std::map< const SMDS_MeshNode* , int > node2IdMap; + int iN = 0, nbNodes = myMesh->NbNodes(); + GmfSetKwd( meshID, GmfVertices, nbNodes ); + double xyz[3]; + SMDS_NodeIteratorPtr nodeIt = myMesh->nodesIterator(); + while ( nodeIt->more() ) + { + const SMDS_MeshNode* n = nodeIt->next(); + n->GetXYZ( xyz ); + GmfSetLin( meshID, GmfVertices, xyz[0], xyz[1], xyz[2], n->getshapeId() ); + node2IdMap.insert( node2IdMap.end(), make_pair( n, ++iN )); + } + if ( iN != nbNodes ) + return addMessage("Wrong nb of nodes returned by nodesIterator", /*fatal=*/true); + + + SMDS_ElemIteratorPtr elemIt; + typedef std::map< const SMDS_MeshElement*, size_t, TIDCompare > TElem2IDMap; + + // edges + TElem2IDMap edge2IDMap; + BEGIN_ELEM_WRITE( SMDSEntity_Edge, GmfEdges, edge ) + node2IdMap[ edge->GetNode( 0 )], + node2IdMap[ edge->GetNode( 1 )], + END_ELEM_WRITE_ADD_TO_MAP( edge, edge2IDMap ); + + // quadratic edges + BEGIN_ELEM_WRITE( SMDSEntity_Quad_Edge, GmfEdgesP2, edge ) + node2IdMap[ edge->GetNode( 0 )], + node2IdMap[ edge->GetNode( 1 )], + node2IdMap[ edge->GetNode( 2 )], + END_ELEM_WRITE( edge ); + + // triangles + TElem2IDMap tria2IDMap; + BEGIN_ELEM_WRITE( SMDSEntity_Triangle, GmfTriangles, tria ) + node2IdMap[ tria->GetNode( 0 )], + node2IdMap[ tria->GetNode( 1 )], + node2IdMap[ tria->GetNode( 2 )], + END_ELEM_WRITE_ADD_TO_MAP( tria, tria2IDMap ); + + // quadratic triangles + BEGIN_ELEM_WRITE( SMDSEntity_Quad_Triangle, GmfTrianglesP2, tria ) + node2IdMap[ tria->GetNode( 0 )], + node2IdMap[ tria->GetNode( 1 )], + node2IdMap[ tria->GetNode( 2 )], + node2IdMap[ tria->GetNode( 3 )], + node2IdMap[ tria->GetNode( 4 )], + node2IdMap[ tria->GetNode( 5 )], + END_ELEM_WRITE( tria ); + + // quadrangles + TElem2IDMap quad2IDMap; + BEGIN_ELEM_WRITE( SMDSEntity_Quadrangle, GmfQuadrilaterals, quad ) + node2IdMap[ quad->GetNode( 0 )], + node2IdMap[ quad->GetNode( 1 )], + node2IdMap[ quad->GetNode( 2 )], + node2IdMap[ quad->GetNode( 3 )], + END_ELEM_WRITE_ADD_TO_MAP( quad, quad2IDMap ); + + // bi-quadratic quadrangles + BEGIN_ELEM_WRITE( SMDSEntity_BiQuad_Quadrangle, GmfQuadrilateralsQ2, quad ) + node2IdMap[ quad->GetNode( 0 )], + node2IdMap[ quad->GetNode( 3 )], + node2IdMap[ quad->GetNode( 2 )], + node2IdMap[ quad->GetNode( 1 )], + node2IdMap[ quad->GetNode( 7 )], + node2IdMap[ quad->GetNode( 6 )], + node2IdMap[ quad->GetNode( 5 )], + node2IdMap[ quad->GetNode( 4 )], + node2IdMap[ quad->GetNode( 8 )], + END_ELEM_WRITE( quad ); + + // terahedra + BEGIN_ELEM_WRITE( SMDSEntity_Tetra, GmfTetrahedra, tetra ) + node2IdMap[ tetra->GetNode( 0 )], + node2IdMap[ tetra->GetNode( 2 )], + node2IdMap[ tetra->GetNode( 1 )], + node2IdMap[ tetra->GetNode( 3 )], + END_ELEM_WRITE( tetra ); + + // quadratic terahedra + BEGIN_ELEM_WRITE( SMDSEntity_Quad_Tetra, GmfTetrahedraP2, tetra ) + node2IdMap[ tetra->GetNode( 0 )], + node2IdMap[ tetra->GetNode( 2 )], + node2IdMap[ tetra->GetNode( 1 )], + node2IdMap[ tetra->GetNode( 3 )], + node2IdMap[ tetra->GetNode( 6 )], + node2IdMap[ tetra->GetNode( 5 )], + node2IdMap[ tetra->GetNode( 4 )], + node2IdMap[ tetra->GetNode( 7 )], + node2IdMap[ tetra->GetNode( 9 )], + node2IdMap[ tetra->GetNode( 8 )], + END_ELEM_WRITE( tetra ); + + // pyramids + BEGIN_ELEM_WRITE( SMDSEntity_Pyramid, GmfPyramids, pyra ) + node2IdMap[ pyra->GetNode( 0 )], + node2IdMap[ pyra->GetNode( 2 )], + node2IdMap[ pyra->GetNode( 1 )], + node2IdMap[ pyra->GetNode( 3 )], + node2IdMap[ pyra->GetNode( 4 )], + END_ELEM_WRITE( pyra ); + + // hexahedra + BEGIN_ELEM_WRITE( SMDSEntity_Hexa, GmfHexahedra, hexa ) + node2IdMap[ hexa->GetNode( 0 )], + node2IdMap[ hexa->GetNode( 3 )], + node2IdMap[ hexa->GetNode( 2 )], + node2IdMap[ hexa->GetNode( 1 )], + node2IdMap[ hexa->GetNode( 4 )], + node2IdMap[ hexa->GetNode( 7 )], + node2IdMap[ hexa->GetNode( 6 )], + node2IdMap[ hexa->GetNode( 5 )], + END_ELEM_WRITE( hexa ); + + // tri-quadratic hexahedra + BEGIN_ELEM_WRITE( SMDSEntity_TriQuad_Hexa, GmfHexahedraQ2, hexa ) + node2IdMap[ hexa->GetNode( 0 )], + node2IdMap[ hexa->GetNode( 3 )], + node2IdMap[ hexa->GetNode( 2 )], + node2IdMap[ hexa->GetNode( 1 )], + node2IdMap[ hexa->GetNode( 4 )], + node2IdMap[ hexa->GetNode( 7 )], + node2IdMap[ hexa->GetNode( 6 )], + node2IdMap[ hexa->GetNode( 5 )], + node2IdMap[ hexa->GetNode( 11 )], + node2IdMap[ hexa->GetNode( 10 )], + node2IdMap[ hexa->GetNode( 9 )], + node2IdMap[ hexa->GetNode( 8 )], + node2IdMap[ hexa->GetNode( 12 )], + node2IdMap[ hexa->GetNode( 15 )], + node2IdMap[ hexa->GetNode( 14 )], + node2IdMap[ hexa->GetNode( 13 )], + node2IdMap[ hexa->GetNode( 19 )], + node2IdMap[ hexa->GetNode( 18 )], + node2IdMap[ hexa->GetNode( 17 )], + node2IdMap[ hexa->GetNode( 16 )], + node2IdMap[ hexa->GetNode( 20 )], + node2IdMap[ hexa->GetNode( 24 )], + node2IdMap[ hexa->GetNode( 23 )], + node2IdMap[ hexa->GetNode( 22 )], + node2IdMap[ hexa->GetNode( 21 )], + node2IdMap[ hexa->GetNode( 25 )], + node2IdMap[ hexa->GetNode( 26 )], + END_ELEM_WRITE( hexa ); + + // prism + BEGIN_ELEM_WRITE( SMDSEntity_Penta, GmfPrisms, prism ) + node2IdMap[ prism->GetNode( 0 )], + node2IdMap[ prism->GetNode( 2 )], + node2IdMap[ prism->GetNode( 1 )], + node2IdMap[ prism->GetNode( 3 )], + node2IdMap[ prism->GetNode( 5 )], + node2IdMap[ prism->GetNode( 4 )], + END_ELEM_WRITE( prism ); + + + // required entities + SMESH_Comment badGroups; + const std::set& groupSet = myMesh->GetGroups(); + std::set::const_iterator grIt = groupSet.begin(); + for ( ; grIt != groupSet.end(); ++grIt ) + { + const SMESHDS_GroupBase* group = *grIt; + std::string groupName = group->GetStoreName(); + std::string::size_type pos = groupName.find( "_required_" ); + if ( pos == std::string::npos ) continue; + + int gmfKwd; + SMDSAbs_EntityType smdsEntity; + std::string entity = groupName.substr( pos + strlen("_required_")); + if ( entity == "Vertices" ) { + gmfKwd = GmfRequiredVertices; + smdsEntity = SMDSEntity_Node; + } + else if ( entity == "Edges" ) { + gmfKwd = GmfRequiredEdges; + smdsEntity = SMDSEntity_Edge; + } + else if ( entity == "Triangles" ) { + gmfKwd = GmfRequiredTriangles; + smdsEntity = SMDSEntity_Triangle; + } + else if ( entity == "Quadrilaterals" ) { + gmfKwd = GmfRequiredQuadrilaterals; + smdsEntity = SMDSEntity_Quadrangle; + } + else { + addMessage( SMESH_Comment("Invalig gmf entity name: ") << entity, /*fatal=*/false ); + continue; + } + + // check elem type in the group + int nbOkElems = 0; + SMDS_ElemIteratorPtr elemIt = group->GetElements(); + while ( elemIt->more() ) + nbOkElems += ( elemIt->next()->GetEntityType() == smdsEntity ); + + if ( nbOkElems != group->Extent() && nbOkElems == 0 ) + { + badGroups << " " << groupName; + continue; + } + + // choose a TElem2IDMap + TElem2IDMap* elem2IDMap = 0; + if ( smdsEntity == SMDSEntity_Quadrangle && nbOkElems != myMesh->NbFaces() ) + elem2IDMap = & quad2IDMap; + else if ( smdsEntity == SMDSEntity_Triangle && nbOkElems != myMesh->NbFaces() ) + elem2IDMap = & tria2IDMap; + else if ( smdsEntity == SMDSEntity_Edge && nbOkElems != myMesh->NbEdges() ) + elem2IDMap = & edge2IDMap; + + // write the group + GmfSetKwd( meshID, gmfKwd, nbOkElems ); + elemIt = group->GetElements(); + if ( elem2IDMap ) + for ( ; elemIt->more(); ) + { + const SMDS_MeshElement* elem = elemIt->next(); + if ( elem->GetEntityType() == smdsEntity ) + GmfSetLin( meshID, gmfKwd, (*elem2IDMap)[ elem ] ); + } + else + for ( int gmfID = 1; elemIt->more(); ++gmfID) + { + const SMDS_MeshElement* elem = elemIt->next(); + if ( elem->GetEntityType() == smdsEntity ) + GmfSetLin( meshID, gmfKwd, gmfID ); + } + + } // loop on groups + + if ( !badGroups.empty() ) + addMessage( SMESH_Comment("Groups of elements of inappropriate geometry:") + << badGroups, /*fatal=*/false ); + + return DRS_OK; +} diff --git a/src/SMESH/SMESH_2D_Algo.hxx b/src/DriverGMF/DriverGMF_Write.hxx similarity index 59% rename from src/SMESH/SMESH_2D_Algo.hxx rename to src/DriverGMF/DriverGMF_Write.hxx index 0a2a127f3..fd0918d09 100644 --- a/src/SMESH/SMESH_2D_Algo.hxx +++ b/src/DriverGMF/DriverGMF_Write.hxx @@ -19,32 +19,41 @@ // // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // +// File : DriverGMF_Write.hxx +// Created : Mon Sep 17 15:36:47 2012 +// Author : Edward AGAPOV (eap) -// SMESH SMESH : implementaion of SMESH idl descriptions -// File : SMESH_2D_Algo.hxx -// Author : Paul RASCLE, EDF -// Module : SMESH -// $Header$ -// -#ifndef _SMESH_2D_ALGO_HXX_ -#define _SMESH_2D_ALGO_HXX_ -#include "SMESH_SMESH.hxx" +#ifndef __DriverGMF_Write_HXX__ +#define __DriverGMF_Write_HXX__ + +#include "SMESH_DriverGMF.hxx" -#include "SMESH_Algo.hxx" -#include "SMESH_subMesh.hxx" -#include "TopoDS_Wire.hxx" +#include "Driver_SMESHDS_Mesh.h" +#include "SMDSAbs_ElementType.hxx" -class SMESH_EXPORT SMESH_2D_Algo: - public SMESH_Algo +/*! + * \brief Driver Writing a mesh into a GMF file. + */ +class MESHDriverGMF_EXPORT DriverGMF_Write : public Driver_SMESHDS_Mesh { public: - SMESH_2D_Algo(int hypId, int studyId, SMESH_Gen* gen); - virtual ~SMESH_2D_Algo(); - int NumberOfWires(const TopoDS_Shape& S); - int NumberOfPoints(SMESH_Mesh& aMesh,const TopoDS_Wire& W); + DriverGMF_Write(); + ~DriverGMF_Write(); + + virtual Status Perform(); +}; +/*! + * \brief An object closing GMF mesh at destruction + */ +struct DriverGMF_MeshCloser +{ + int _gmfMeshID; + DriverGMF_MeshCloser( const int gmfMeshID ): _gmfMeshID(gmfMeshID) {} + ~DriverGMF_MeshCloser(); }; + #endif diff --git a/src/DriverGMF/Makefile.am b/src/DriverGMF/Makefile.am new file mode 100644 index 000000000..895c83a2f --- /dev/null +++ b/src/DriverGMF/Makefile.am @@ -0,0 +1,50 @@ +# Copyright (C) 2007-2012 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 +# + +include $(top_srcdir)/adm_local/unix/make_common_starter.am + +# header files +salomeinclude_HEADERS = \ + DriverGMF_Read.hxx \ + DriverGMF_Write.hxx \ + SMESH_DriverGMF.hxx \ + libmesh5.h + +# Libraries targets +lib_LTLIBRARIES = libMeshDriverGMF.la +dist_libMeshDriverGMF_la_SOURCES = \ + DriverGMF_Read.cxx \ + DriverGMF_Write.cxx \ + libmesh5.c + +# additionnal information to compil and link file +libMeshDriverGMF_la_CPPFLAGS = \ + $(KERNEL_CXXFLAGS) \ + $(CAS_CPPFLAGS) \ + $(VTK_INCLUDES) \ + $(BOOST_CPPFLAGS) \ + -I$(srcdir)/../Driver \ + -I$(srcdir)/../SMESHUtils \ + -I$(srcdir)/../SMDS \ + -I$(srcdir)/../SMESHDS + +libMeshDriverGMF_la_LDFLAGS = \ + $(BOOST_LIBS) \ + ../Driver/libMeshDriver.la \ + ../SMESHUtils/libSMESHUtils.la diff --git a/src/SMESH/SMESH_0D_Algo.hxx b/src/DriverGMF/SMESH_DriverGMF.hxx old mode 100644 new mode 100755 similarity index 72% rename from src/SMESH/SMESH_0D_Algo.hxx rename to src/DriverGMF/SMESH_DriverGMF.hxx index d7ba782d8..dd901a3a2 --- a/src/SMESH/SMESH_0D_Algo.hxx +++ b/src/DriverGMF/SMESH_DriverGMF.hxx @@ -20,23 +20,21 @@ // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // -// SMESH SMESH : implementaion of SMESH idl descriptions -// File : SMESH_0D_Algo.hxx +// File : SMESH_DriverGMF.hxx +// Author : Alexander A. BORODIN // Module : SMESH -// $Header$ // -#ifndef _SMESH_0D_ALGO_HXX_ -#define _SMESH_0D_ALGO_HXX_ +#ifndef _SMESH_DriverGMF_HXX_ +#define _SMESH_DriverGMF_HXX_ -#include "SMESH_SMESH.hxx" - -#include "SMESH_Algo.hxx" - -class SMESH_EXPORT SMESH_0D_Algo: public SMESH_Algo -{ -public: - SMESH_0D_Algo(int hypId, int studyId, SMESH_Gen* gen); - virtual ~SMESH_0D_Algo(); -}; +#ifdef WNT + #if defined MESHDriverGMF_EXPORTS || defined MeshDriverGMF_EXPORTS + #define MESHDriverGMF_EXPORT __declspec( dllexport ) + #else + #define MESHDriverGMF_EXPORT __declspec( dllimport ) + #endif +#else + #define MESHDriverGMF_EXPORT +#endif #endif diff --git a/src/DriverGMF/libmesh5.c b/src/DriverGMF/libmesh5.c new file mode 100644 index 000000000..b16c39c93 --- /dev/null +++ b/src/DriverGMF/libmesh5.c @@ -0,0 +1,1346 @@ + + +/*----------------------------------------------------------*/ +/* */ +/* LIBMESH V 5.46 */ +/* */ +/*----------------------------------------------------------*/ +/* */ +/* Description: handle .meshb file format I/O */ +/* Author: Loic MARECHAL */ +/* Creation date: feb 16 2007 */ +/* Last modification: apr 03 2012 */ +/* */ +/*----------------------------------------------------------*/ + + +/*----------------------------------------------------------*/ +/* Includes */ +/*----------------------------------------------------------*/ + +#include +#include +#include +#include +#include +#include +#include +#include "libmesh5.h" + + +/*----------------------------------------------------------*/ +/* Defines */ +/*----------------------------------------------------------*/ + +#define Asc 1 +#define Bin 2 +#define MshFil 4 +#define SolFil 8 +#define MaxMsh 100 +#define InfKwd 1 +#define RegKwd 2 +#define SolKwd 3 +#define WrdSiz 4 +#define BufSiz 10000 + + +/*----------------------------------------------------------*/ +/* Structures */ +/*----------------------------------------------------------*/ + +typedef struct +{ + int typ, SolSiz, NmbWrd, NmbLin, NmbTyp, TypTab[ GmfMaxTyp ]; + long pos; + char fmt[ GmfMaxTyp*9 ]; +}KwdSct; + +typedef struct +{ + int dim, ver, mod, typ, cod, pos; + long NexKwdPos, siz; + KwdSct KwdTab[ GmfMaxKwd + 1 ]; + FILE *hdl; + int *IntBuf; + float *FltBuf; + unsigned char *buf; + char FilNam[ GmfStrSiz ]; + double DblBuf[1000/8]; + unsigned char blk[ BufSiz + 1000 ]; +}GmfMshSct; + + +/*----------------------------------------------------------*/ +/* Global variables */ +/*----------------------------------------------------------*/ + +static int GmfIniFlg=0; +static GmfMshSct *GmfMshTab[ MaxMsh + 1 ]; +static const char *GmfKwdFmt[ GmfMaxKwd + 1 ][4] = +{ {"Reserved", "", "", ""}, + {"MeshVersionFormatted", "", "", "i"}, + {"Reserved", "", "", ""}, + {"Dimension", "", "", "i"}, + {"Vertices", "Vertex", "i", "dri"}, + {"Edges", "Edge", "i", "iii"}, + {"Triangles", "Triangle", "i", "iiii"}, + {"Quadrilaterals", "Quadrilateral", "i", "iiiii"}, + {"Tetrahedra", "Tetrahedron", "i", "iiiii"}, + {"Prisms", "Prism", "i", "iiiiiii"}, + {"Hexahedra", "Hexahedron", "i", "iiiiiiiii"}, + {"IterationsAll", "IterationAll","","i"}, + {"TimesAll", "TimeAll","","r"}, + {"Corners", "Corner", "i", "i"}, + {"Ridges", "Ridge", "i", "i"}, + {"RequiredVertices", "RequiredVertex", "i", "i"}, + {"RequiredEdges", "RequiredEdge", "i", "i"}, + {"RequiredTriangles", "RequiredTriangle", "i", "i"}, + {"RequiredQuadrilaterals", "RequiredQuadrilateral", "i", "i"}, + {"TangentAtEdgeVertices", "TangentAtEdgeVertex", "i", "iii"}, + {"NormalAtVertices", "NormalAtVertex", "i", "ii"}, + {"NormalAtTriangleVertices", "NormalAtTriangleVertex", "i", "iii"}, + {"NormalAtQuadrilateralVertices", "NormalAtQuadrilateralVertex", "i", "iiii"}, + {"AngleOfCornerBound", "", "", "r"}, + {"TrianglesP2", "TriangleP2", "i", "iiiiiii"}, + {"EdgesP2", "EdgeP2", "i", "iiii"}, + {"SolAtPyramids", "SolAtPyramid", "i", "sr"}, + {"QuadrilateralsQ2", "QuadrilateralQ2", "i", "iiiiiiiiii"}, + {"ISolAtPyramids", "ISolAtPyramid", "i", "iiiii"}, + {"SubDomainFromGeom", "SubDomainFromGeom", "i", "iiii"}, + {"TetrahedraP2", "TetrahedronP2", "i", "iiiiiiiiiii"}, + {"Fault_NearTri", "Fault_NearTri", "i", "i"}, + {"Fault_Inter", "Fault_Inter", "i", "i"}, + {"HexahedraQ2", "HexahedronQ2", "i", "iiiiiiiiiiiiiiiiiiiiiiiiiiii"}, + {"ExtraVerticesAtEdges", "ExtraVerticesAtEdge", "i", "in"}, + {"ExtraVerticesAtTriangles", "ExtraVerticesAtTriangle", "i", "in"}, + {"ExtraVerticesAtQuadrilaterals", "ExtraVerticesAtQuadrilateral", "i", "in"}, + {"ExtraVerticesAtTetrahedra", "ExtraVerticesAtTetrahedron", "i", "in"}, + {"ExtraVerticesAtPrisms", "ExtraVerticesAtPrism", "i", "in"}, + {"ExtraVerticesAtHexahedra", "ExtraVerticesAtHexahedron", "i", "in"}, + {"VerticesOnGeometricVertices", "VertexOnGeometricVertex", "i", "iir"}, + {"VerticesOnGeometricEdges", "VertexOnGeometricEdge", "i", "iirr"}, + {"VerticesOnGeometricTriangles", "VertexOnGeometricTriangle", "i", "iirrr"}, + {"VerticesOnGeometricQuadrilaterals", "VertexOnGeometricQuadrilateral", "i", "iirrr"}, + {"EdgesOnGeometricEdges", "EdgeOnGeometricEdge", "i", "iir"}, + {"Fault_FreeEdge", "Fault_FreeEdge", "i", "i"}, + {"Polyhedra", "Polyhedron", "i", "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii"}, + {"Polygons", "Polygon", "", "iiiiiiiii"}, + {"Fault_Overlap", "Fault_Overlap", "i", "i"}, + {"Pyramids", "Pyramid", "i", "iiiiii"}, + {"BoundingBox", "", "", "drdr"}, + {"Body","i", "drdrdrdr"}, + {"PrivateTable", "PrivateTable", "i", "i"}, + {"Fault_BadShape", "Fault_BadShape", "i", "i"}, + {"End", "", "", ""}, + {"TrianglesOnGeometricTriangles", "TriangleOnGeometricTriangle", "i", "iir"}, + {"TrianglesOnGeometricQuadrilaterals", "TriangleOnGeometricQuadrilateral", "i", "iir"}, + {"QuadrilateralsOnGeometricTriangles", "QuadrilateralOnGeometricTriangle", "i", "iir"}, + {"QuadrilateralsOnGeometricQuadrilaterals", "QuadrilateralOnGeometricQuadrilateral", "i", "iir"}, + {"Tangents", "Tangent", "i", "dr"}, + {"Normals", "Normal", "i", "dr"}, + {"TangentAtVertices", "TangentAtVertex", "i", "ii"}, + {"SolAtVertices", "SolAtVertex", "i", "sr"}, + {"SolAtEdges", "SolAtEdge", "i", "sr"}, + {"SolAtTriangles", "SolAtTriangle", "i", "sr"}, + {"SolAtQuadrilaterals", "SolAtQuadrilateral", "i", "sr"}, + {"SolAtTetrahedra", "SolAtTetrahedron", "i", "sr"}, + {"SolAtPrisms", "SolAtPrism", "i", "sr"}, + {"SolAtHexahedra", "SolAtHexahedron", "i", "sr"}, + {"DSolAtVertices", "DSolAtVertex", "i", "sr"}, + {"ISolAtVertices", "ISolAtVertex", "i", "i"}, + {"ISolAtEdges", "ISolAtEdge", "i", "ii"}, + {"ISolAtTriangles", "ISolAtTriangle", "i", "iii"}, + {"ISolAtQuadrilaterals", "ISolAtQuadrilateral", "i", "iiii"}, + {"ISolAtTetrahedra", "ISolAtTetrahedron", "i", "iiii"}, + {"ISolAtPrisms", "ISolAtPrism", "i", "iiiiii"}, + {"ISolAtHexahedra", "ISolAtHexahedron", "i", "iiiiiiii"}, + {"Iterations", "","","i"}, + {"Time", "","","r"}, + {"Fault_SmallTri", "Fault_SmallTri","i","i"}, + {"CoarseHexahedra", "CoarseHexahedron", "i", "i"} + }; + + +/*----------------------------------------------------------*/ +/* Prototypes of local procedures */ +/*----------------------------------------------------------*/ + +static void ScaWrd(GmfMshSct *, unsigned char *); +static void ScaDblWrd(GmfMshSct *, unsigned char *); +static void ScaBlk(GmfMshSct *, unsigned char *, int); +static long GetPos(GmfMshSct *); +static void RecWrd(GmfMshSct *, unsigned char *); +static void RecDblWrd(GmfMshSct *, unsigned char *); +static void RecBlk(GmfMshSct *, unsigned char *, int); +static void SetPos(GmfMshSct *, long); +static int ScaKwdTab(GmfMshSct *); +static void ExpFmt(GmfMshSct *, int); +static void ScaKwdHdr(GmfMshSct *, int); + + +/*----------------------------------------------------------*/ +/* Open a mesh file in read or write mod */ +/*----------------------------------------------------------*/ + +int GmfOpenMesh(const char *FilNam, int mod, ...) +{ + int i, KwdCod, res, *PtrVer, *PtrDim, MshIdx=0; + char str[ GmfStrSiz ]; + va_list VarArg; + GmfMshSct *msh; + char *ptr; + int k; + + if(!GmfIniFlg) + { + for(i=0;i<=MaxMsh;i++) + GmfMshTab[i] = NULL; + + GmfIniFlg = 1; + } + + /*---------------------*/ + /* MESH STRUCTURE INIT */ + /*---------------------*/ + + for(i=1;i<=MaxMsh;i++) + if(!GmfMshTab[i]) + { + MshIdx = i; + break; + } + + if( !MshIdx || !(msh = calloc(1, sizeof(GmfMshSct))) ) + return(0); + + /* Copy the FilNam into the structure */ + + if(strlen(FilNam) + 7 >= GmfStrSiz) + { + free (msh); + return(0); + } + + strcpy(msh->FilNam, FilNam); + + /* Store the opening mod (read or write) and guess the filetype (binary or ascii) depending on the extension */ + + msh->mod = mod; + msh->buf = (unsigned char *)msh->DblBuf; + msh->FltBuf = (float *)msh->DblBuf; + msh->IntBuf = (int *)msh->DblBuf; + + k = strlen(msh->FilNam) - 6; + if(k < 0) + k = 0; + ptr = msh->FilNam+k; + if(strstr(ptr, ".meshb")) + msh->typ |= (Bin | MshFil); + else if(strstr(ptr, ".mesh")) + msh->typ |= (Asc | MshFil); + else if(strstr(ptr, ".solb")) + msh->typ |= (Bin | SolFil); + else if(strstr(ptr, ".sol")) + msh->typ |= (Asc | SolFil); + else { + free (msh); + return(0); + } + + /* Open the file in the required mod and initialyse the mesh structure */ + + if(msh->mod == GmfRead) + { + + /*-----------------------*/ + /* OPEN FILE FOR READING */ + /*-----------------------*/ + + va_start(VarArg, mod); + PtrVer = va_arg(VarArg, int *); + PtrDim = va_arg(VarArg, int *); + va_end(VarArg); + + /* Create the name string and open the file */ + + if(!(msh->hdl = fopen(msh->FilNam, "rb"))) + { + free (msh); + return(0); + } + + /* Read the endian coding tag, the mesh version and the mesh dimension (mandatory kwd) */ + + if(msh->typ & Bin) + { + fread((unsigned char *)&msh->cod, WrdSiz, 1, msh->hdl); + + if( (msh->cod != 1) && (msh->cod != 16777216) ) + { + free (msh); + return(0); + } + + ScaWrd(msh, (unsigned char *)&msh->ver); + + if( (msh->ver < 1) || (msh->ver > 3) ) + { + free (msh); + return(0); + } + + if( (msh->ver == 3) && (sizeof(long) == 4) ) + { + free (msh); + return(0); + } + + ScaWrd(msh, (unsigned char *)&KwdCod); + + if(KwdCod != GmfDimension) + { + free (msh); + return(0); + } + + GetPos(msh); + ScaWrd(msh, (unsigned char *)&msh->dim); + } + else + { + do + { + res = fscanf(msh->hdl, "%s", str); + }while( (res != EOF) && strcmp(str, "MeshVersionFormatted") ); + + if(res == EOF) + { + free (msh); + return(0); + } + + fscanf(msh->hdl, "%d", &msh->ver); + + if( (msh->ver < 1) || (msh->ver > 3) ) + { + free (msh); + return(0); + } + + do + { + res = fscanf(msh->hdl, "%s", str); + }while( (res != EOF) && strcmp(str, "Dimension") ); + + if(res == EOF) + { + free (msh); + return(0); + } + + fscanf(msh->hdl, "%d", &msh->dim); + } + + if( (msh->dim != 2) && (msh->dim != 3) ) + { + free (msh); + return(0); + } + + (*PtrVer) = msh->ver; + (*PtrDim) = msh->dim; + + /*------------*/ + /* KW READING */ + /*------------*/ + + /* Read the list of kw present in the file */ + + if(!ScaKwdTab(msh)) + { + free (msh); + return(0); + } + + GmfMshTab[ MshIdx ] = msh; + + return(MshIdx); + } + else if(msh->mod == GmfWrite) + { + + /*-----------------------*/ + /* OPEN FILE FOR WRITING */ + /*-----------------------*/ + + msh->cod = 1; + + /* Check if the user provided a valid version number and dimension */ + + va_start(VarArg, mod); + msh->ver = va_arg(VarArg, int); + msh->dim = va_arg(VarArg, int); + va_end(VarArg); + + if( (msh->ver < 1) || (msh->ver > 3) ) + { + free (msh); + return(0); + } + + if( (msh->ver == 3) && (sizeof(long) == 4) ) + { + free (msh); + return(0); + } + + if( (msh->dim != 2) && (msh->dim != 3) ) + { + free (msh); + return(0); + } + + /* Create the mesh file */ + + if(!(msh->hdl = fopen(msh->FilNam, "wb"))) + { + free (msh); + return(0); + } + + GmfMshTab[ MshIdx ] = msh; + + + /*------------*/ + /* KW WRITING */ + /*------------*/ + + /* Write the mesh version and dimension */ + + if(msh->typ & Asc) + { + fprintf(msh->hdl, "%s %d\n\n", GmfKwdFmt[ GmfVersionFormatted ][0], msh->ver); + fprintf(msh->hdl, "%s %d\n", GmfKwdFmt[ GmfDimension ][0], msh->dim); + } + else + { + RecWrd(msh, (unsigned char *)&msh->cod); + RecWrd(msh, (unsigned char *)&msh->ver); + GmfSetKwd(MshIdx, GmfDimension, 0); + RecWrd(msh, (unsigned char *)&msh->dim); + } + + return(MshIdx); + } + else + { + free (msh); + return(0); + } +} + + +/*----------------------------------------------------------*/ +/* Close a meshfile in the right way */ +/*----------------------------------------------------------*/ + +int GmfCloseMesh(int MshIdx) +{ + int res = 1; + GmfMshSct *msh; + + if( (MshIdx < 1) || (MshIdx > MaxMsh) ) + return(0); + + msh = GmfMshTab[ MshIdx ]; + RecBlk(msh, msh->buf, 0); + + /* In write down the "End" kw in write mode */ + + if(msh->mod == GmfWrite){ + if(msh->typ & Asc) + fprintf(msh->hdl, "\n%s\n", GmfKwdFmt[ GmfEnd ][0]); + else + GmfSetKwd(MshIdx, GmfEnd, 0); + } + /* Close the file and free the mesh structure */ + + if(fclose(msh->hdl)) + res = 0; + + free(msh); + GmfMshTab[ MshIdx ] = NULL; + + return(res); +} + + +/*----------------------------------------------------------*/ +/* Read the number of lines and set the position to this kwd*/ +/*----------------------------------------------------------*/ + +int GmfStatKwd(int MshIdx, int KwdCod, ...) +{ + int i, *PtrNmbTyp, *PtrSolSiz, *TypTab; + GmfMshSct *msh; + KwdSct *kwd; + va_list VarArg; + + if( (MshIdx < 1) || (MshIdx > MaxMsh) ) + return(0); + + msh = GmfMshTab[ MshIdx ]; + + if( (KwdCod < 1) || (KwdCod > GmfMaxKwd) ) + return(0); + + kwd = &msh->KwdTab[ KwdCod ]; + + if(!kwd->NmbLin) + return(0); + + /* Read further arguments if this kw is a sol */ + + if(kwd->typ == SolKwd) + { + va_start(VarArg, KwdCod); + + PtrNmbTyp = va_arg(VarArg, int *); + *PtrNmbTyp = kwd->NmbTyp; + + PtrSolSiz = va_arg(VarArg, int *); + *PtrSolSiz = kwd->SolSiz; + + TypTab = va_arg(VarArg, int *); + + for(i=0;iNmbTyp;i++) + TypTab[i] = kwd->TypTab[i]; + + va_end(VarArg); + } + + return(kwd->NmbLin); +} + + +/*----------------------------------------------------------*/ +/* Set the current file position to a given kwd */ +/*----------------------------------------------------------*/ + +int GmfGotoKwd(int MshIdx, int KwdCod) +{ + GmfMshSct *msh; + KwdSct *kwd; + + if( (MshIdx < 1) || (MshIdx > MaxMsh) ) + return(0); + + msh = GmfMshTab[ MshIdx ]; + + if( (KwdCod < 1) || (KwdCod > GmfMaxKwd) ) + return(0); + + kwd = &msh->KwdTab[ KwdCod ]; + + if(!kwd->NmbLin) + return(0); + + return(fseek(msh->hdl, kwd->pos, SEEK_SET)); +} + + +/*----------------------------------------------------------*/ +/* Write the kwd and set the number of lines */ +/*----------------------------------------------------------*/ + +int GmfSetKwd(int MshIdx, int KwdCod, ...) +{ + int i, NmbLin=0, *TypTab; + long CurPos; + va_list VarArg; + GmfMshSct *msh; + KwdSct *kwd; + + if( (MshIdx < 1) || (MshIdx > MaxMsh) ) + return(0); + + msh = GmfMshTab[ MshIdx ]; + RecBlk(msh, msh->buf, 0); + + if( (KwdCod < 1) || (KwdCod > GmfMaxKwd) ) + return(0); + + kwd = &msh->KwdTab[ KwdCod ]; + + /* Read further arguments if this kw has a header */ + + if(strlen(GmfKwdFmt[ KwdCod ][2])) + { + va_start(VarArg, KwdCod); + NmbLin = va_arg(VarArg, int); + + if(!strcmp(GmfKwdFmt[ KwdCod ][3], "sr")) + { + kwd->NmbTyp = va_arg(VarArg, int); + TypTab = va_arg(VarArg, int *); + + for(i=0;iNmbTyp;i++) + kwd->TypTab[i] = TypTab[i]; + } + + va_end(VarArg); + } + + /* Setup the kwd info */ + + ExpFmt(msh, KwdCod); + + if(!kwd->typ) + return(0); + else if(kwd->typ == InfKwd) + kwd->NmbLin = 1; + else + kwd->NmbLin = NmbLin; + + /* Store the next kwd position in binary file */ + + if( (msh->typ & Bin) && msh->NexKwdPos ) + { + CurPos = ftell(msh->hdl); + fseek(msh->hdl, msh->NexKwdPos, SEEK_SET); + SetPos(msh, CurPos); + fseek(msh->hdl, CurPos, SEEK_SET); + } + + /* Write the header */ + + if(msh->typ & Asc) + { + fprintf(msh->hdl, "\n%s\n", GmfKwdFmt[ KwdCod ][0]); + + if(kwd->typ != InfKwd) + fprintf(msh->hdl, "%d\n", kwd->NmbLin); + + /* In case of solution field, write the extended header */ + + if(kwd->typ == SolKwd) + { + fprintf(msh->hdl, "%d ", kwd->NmbTyp); + + for(i=0;iNmbTyp;i++) + fprintf(msh->hdl, "%d ", kwd->TypTab[i]); + + fprintf(msh->hdl, "\n\n"); + } + } + else + { + RecWrd(msh, (unsigned char *)&KwdCod); + msh->NexKwdPos = ftell(msh->hdl); + SetPos(msh, 0); + + if(kwd->typ != InfKwd) + RecWrd(msh, (unsigned char *)&kwd->NmbLin); + + /* In case of solution field, write the extended header at once */ + + if(kwd->typ == SolKwd) + { + RecWrd(msh, (unsigned char *)&kwd->NmbTyp); + + for(i=0;iNmbTyp;i++) + RecWrd(msh, (unsigned char *)&kwd->TypTab[i]); + } + } + + /* Reset write buffer position */ + msh->pos = 0; + + /* Estimate the total file size and check whether it crosses the 2GB threshold */ + + msh->siz += kwd->NmbLin * kwd->NmbWrd * WrdSiz; + + if(msh->siz > 2E9) + return(0); + else + return(kwd->NmbLin); +} + + +/*----------------------------------------------------------*/ +/* Read a full line from the current kwd */ +/*----------------------------------------------------------*/ + +void GmfGetLin(int MshIdx, int KwdCod, ...) +{ + int i, j; + float *FltSolTab; + double *DblSolTab; + va_list VarArg; + GmfMshSct *msh = GmfMshTab[ MshIdx ]; + KwdSct *kwd = &msh->KwdTab[ KwdCod ]; + + /* Start decoding the arguments */ + + va_start(VarArg, KwdCod); + + if(kwd->typ != SolKwd) + { + int k, nb_repeat = 0; + + if(msh->ver == 1) + { + if(msh->typ & Asc) + { + for(i=0;iSolSiz;i++) + if(kwd->fmt[i] == 'r') + fscanf(msh->hdl, "%f", va_arg(VarArg, float *)); + else if(kwd->fmt[i] == 'n') { + fscanf(msh->hdl, "%d", &nb_repeat); + *(va_arg(VarArg, int *)) = nb_repeat; + for(k=0;khdl, "%d", va_arg(VarArg, int *)); + } + else + fscanf(msh->hdl, "%d", va_arg(VarArg, int *)); + } + else + { + for(i=0;iSolSiz;i++) + if(kwd->fmt[i] == 'r') + ScaWrd(msh, (unsigned char *)va_arg(VarArg, float *)); + else if(kwd->fmt[i] == 'n') { + ScaWrd(msh, (unsigned char *)&nb_repeat); + *(va_arg(VarArg, int *)) = nb_repeat; + for(k=0;ktyp & Asc) + { + for(i=0;iSolSiz;i++) + if(kwd->fmt[i] == 'r') + fscanf(msh->hdl, "%lf", va_arg(VarArg, double *)); + else if(kwd->fmt[i] == 'n') { + fscanf(msh->hdl, "%d", &nb_repeat); + *(va_arg(VarArg, int *)) = nb_repeat; + for(k=0;khdl, "%d", va_arg(VarArg, int *)); + } + else + fscanf(msh->hdl, "%d", va_arg(VarArg, int *)); + } + else + for(i=0;iSolSiz;i++) + if(kwd->fmt[i] == 'r') + ScaDblWrd(msh, (unsigned char *)va_arg(VarArg, double *)); + else if(kwd->fmt[i] == 'n') { + ScaWrd(msh, (unsigned char *)&nb_repeat); + *(va_arg(VarArg, int *)) = nb_repeat; + for(k=0;kver == 1) + { + FltSolTab = va_arg(VarArg, float *); + + if(msh->typ & Asc) + for(j=0;jSolSiz;j++) + fscanf(msh->hdl, "%f", &FltSolTab[j]); + else + ScaBlk(msh, (unsigned char *)FltSolTab, kwd->NmbWrd); + } + else + { + DblSolTab = va_arg(VarArg, double *); + + if(msh->typ & Asc) + for(j=0;jSolSiz;j++) + fscanf(msh->hdl, "%lf", &DblSolTab[j]); + else + for(j=0;jSolSiz;j++) + ScaDblWrd(msh, (unsigned char *)&DblSolTab[j]); + } + } + + va_end(VarArg); +} + + +/*----------------------------------------------------------*/ +/* Write a full line from the current kwd */ +/*----------------------------------------------------------*/ + +void GmfSetLin(int MshIdx, int KwdCod, ...) +{ + int i, j, pos, *IntBuf; + float *FltSolTab; + double *DblSolTab, *DblBuf; + va_list VarArg; + GmfMshSct *msh = GmfMshTab[ MshIdx ]; + KwdSct *kwd = &msh->KwdTab[ KwdCod ]; + + /* Start decoding the arguments */ + + va_start(VarArg, KwdCod); + + if(kwd->typ != SolKwd) + { + int k, nb_repeat = 0; + + if(msh->ver == 1) + { + if(msh->typ & Asc) + { + for(i=0;iSolSiz;i++) + if(kwd->fmt[i] == 'r') + fprintf(msh->hdl, "%g ", (float)va_arg(VarArg, double)); + else if(kwd->fmt[i] == 'n') { + nb_repeat = va_arg(VarArg, int); + fprintf(msh->hdl, "%d ", nb_repeat); + for(k=0;khdl, "%d ", va_arg(VarArg, int)); + } + else + fprintf(msh->hdl, "%d ", va_arg(VarArg, int)); + } + else + { + int size_of_block = kwd->SolSiz; + for(i=0;iSolSiz;i++) + if(kwd->fmt[i] == 'r') + msh->FltBuf[i] = va_arg(VarArg, double); + else if(kwd->fmt[i] == 'n') { + nb_repeat = va_arg(VarArg, int); + msh->FltBuf[i] = nb_repeat; + for(k=0;kIntBuf[i+1+k] = va_arg(VarArg, int); + size_of_block ++; + } + } + else + msh->IntBuf[i] = va_arg(VarArg, int); + + RecBlk(msh, msh->buf, size_of_block); + } + } + else + { + if(msh->typ & Asc) + { + for(i=0;iSolSiz;i++) + if(kwd->fmt[i] == 'r') + fprintf(msh->hdl, "%.15lg ", va_arg(VarArg, double)); + else if(kwd->fmt[i] == 'n') { + nb_repeat = va_arg(VarArg, int); + fprintf(msh->hdl, "%d ", nb_repeat); + for(k=0;khdl, "%d ", va_arg(VarArg, int)); + } + else + fprintf(msh->hdl, "%d ", va_arg(VarArg, int)); + } + else + { + pos = 0; + + for(i=0;iSolSiz;i++) + if(kwd->fmt[i] == 'r') + { + DblBuf = (double *)&msh->buf[ pos ]; + *DblBuf = va_arg(VarArg, double); + pos += 8; + } + else if(kwd->fmt[i] == 'n') + { + IntBuf = (int *)&msh->buf[ pos ]; + nb_repeat = va_arg(VarArg, int); + *IntBuf = nb_repeat; + pos += 4; + for(k=0;kbuf[ pos ]; + *IntBuf = va_arg(VarArg, int); + pos += 4; + } + } + else + { + IntBuf = (int *)&msh->buf[ pos ]; + *IntBuf = va_arg(VarArg, int); + pos += 4; + } + RecBlk(msh, msh->buf, pos/4); + } + } + } + else + { + if(msh->ver == 1) + { + FltSolTab = va_arg(VarArg, float *); + + if(msh->typ & Asc) + for(j=0;jSolSiz;j++) + fprintf(msh->hdl, "%g ", FltSolTab[j]); + else + RecBlk(msh, (unsigned char *)FltSolTab, kwd->NmbWrd); + } + else + { + DblSolTab = va_arg(VarArg, double *); + + if(msh->typ & Asc) + for(j=0;jSolSiz;j++) + fprintf(msh->hdl, "%.15lg ", DblSolTab[j]); + else + RecBlk(msh, (unsigned char *)DblSolTab, kwd->NmbWrd); + } + } + + va_end(VarArg); + + if(msh->typ & Asc) + fprintf(msh->hdl, "\n"); +} + + +/*----------------------------------------------------------*/ +/* Private procedure for transmesh : copy a whole line */ +/*----------------------------------------------------------*/ + +void GmfCpyLin(int InpIdx, int OutIdx, int KwdCod) +{ + double d; + float f; + int i, a; + GmfMshSct *InpMsh = GmfMshTab[ InpIdx ], *OutMsh = GmfMshTab[ OutIdx ]; + KwdSct *kwd = &InpMsh->KwdTab[ KwdCod ]; + + for(i=0;iSolSiz;i++) + { + if(kwd->fmt[i] == 'r') + { + if(InpMsh->ver == 1) + { + if(InpMsh->typ & Asc) + fscanf(InpMsh->hdl, "%f", &f); + else + ScaWrd(InpMsh, (unsigned char *)&f); + + d = f; + } + else + { + if(InpMsh->typ & Asc) + fscanf(InpMsh->hdl, "%lf", &d); + else + ScaDblWrd(InpMsh, (unsigned char *)&d); + + f = (float)d; + } + + if(OutMsh->ver == 1) + if(OutMsh->typ & Asc) + fprintf(OutMsh->hdl, "%g ", f); + else + RecWrd(OutMsh, (unsigned char *)&f); + else + if(OutMsh->typ & Asc) + fprintf(OutMsh->hdl, "%.15g ", d); + else + RecDblWrd(OutMsh, (unsigned char *)&d); + } + else if(kwd->fmt[i] == 'n') + { + int k, nb_repeat = 0; + + if(InpMsh->typ & Asc) + fscanf(InpMsh->hdl, "%d", &a); + else + ScaWrd(InpMsh, (unsigned char *)&a); + + nb_repeat = a; + + if(OutMsh->typ & Asc) + fprintf(OutMsh->hdl, "%d ", a); + else + RecWrd(OutMsh, (unsigned char *)&a); + + for(k=0;ktyp & Asc) + fscanf(InpMsh->hdl, "%d", &a); + else + ScaWrd(InpMsh, (unsigned char *)&a); + + if(OutMsh->typ & Asc) + fprintf(OutMsh->hdl, "%d ", a); + else + RecWrd(OutMsh, (unsigned char *)&a); + } + } + else + { + if(InpMsh->typ & Asc) + fscanf(InpMsh->hdl, "%d", &a); + else + ScaWrd(InpMsh, (unsigned char *)&a); + + if(OutMsh->typ & Asc) + fprintf(OutMsh->hdl, "%d ", a); + else + RecWrd(OutMsh, (unsigned char *)&a); + } + } + + if(OutMsh->typ & Asc) + fprintf(OutMsh->hdl, "\n"); +} + + +/*----------------------------------------------------------*/ +/* Find every kw present in a meshfile */ +/*----------------------------------------------------------*/ + +static int ScaKwdTab(GmfMshSct *msh) +{ + int KwdCod; + long NexPos, CurPos, EndPos; + char str[ GmfStrSiz ]; + + if(msh->typ & Asc) + { + /* Scan each string in the file until the end */ + + while(fscanf(msh->hdl, "%s", str) != EOF) + { + /* Fast test in order to reject quickly the numeric values */ + + if(isalpha(str[0])) + { + /* Search which kwd code this string is associated with, + then get its header and save the curent position in file (just before the data) */ + + for(KwdCod=1; KwdCod<= GmfMaxKwd; KwdCod++) + if(!strcmp(str, GmfKwdFmt[ KwdCod ][0])) + { + ScaKwdHdr(msh, KwdCod); + break; + } + } + else if(str[0] == '#') + while(fgetc(msh->hdl) != '\n'); + } + } + else + { + /* Get file size */ + + CurPos = ftell(msh->hdl); + fseek(msh->hdl, 0, SEEK_END); + EndPos = ftell(msh->hdl); + fseek(msh->hdl, CurPos, SEEK_SET); + + /* Jump through kwd positions in the file */ + + do + { + /* Get the kwd code and the next kwd position */ + + ScaWrd(msh, (unsigned char *)&KwdCod); + NexPos = GetPos(msh); + + if(NexPos > EndPos) + return(0); + + /* Check if this kwd belongs to this mesh version */ + + if( (KwdCod >= 1) && (KwdCod <= GmfMaxKwd) ) + ScaKwdHdr(msh, KwdCod); + + /* Go to the next kwd */ + + if(NexPos) + fseek(msh->hdl, NexPos, SEEK_SET); + }while(NexPos && (KwdCod != GmfEnd)); + } + + return(1); +} + + +/*----------------------------------------------------------*/ +/* Read and setup the keyword's header */ +/*----------------------------------------------------------*/ + +static void ScaKwdHdr(GmfMshSct *msh, int KwdCod) +{ + int i; + KwdSct *kwd = &msh->KwdTab[ KwdCod ]; + + if(!strcmp("i", GmfKwdFmt[ KwdCod ][2])) + { + if(msh->typ & Asc) + fscanf(msh->hdl, "%d", &kwd->NmbLin); + else + ScaWrd(msh, (unsigned char *)&kwd->NmbLin); + } + else + kwd->NmbLin = 1; + + if(!strcmp("sr", GmfKwdFmt[ KwdCod ][3])) + { + if(msh->typ & Asc) + { + fscanf(msh->hdl, "%d", &kwd->NmbTyp); + + for(i=0;iNmbTyp;i++) + fscanf(msh->hdl, "%d", &kwd->TypTab[i]); + } + else + { + ScaWrd(msh, (unsigned char *)&kwd->NmbTyp); + + for(i=0;iNmbTyp;i++) + ScaWrd(msh, (unsigned char *)&kwd->TypTab[i]); + } + } + + ExpFmt(msh, KwdCod); + kwd->pos = ftell(msh->hdl); +} + + +/*----------------------------------------------------------*/ +/* Expand the compacted format and compute the line size */ +/*----------------------------------------------------------*/ + +static void ExpFmt(GmfMshSct *msh, int KwdCod) +{ + int i, j, TmpSiz=0; + char chr; + const char *InpFmt = GmfKwdFmt[ KwdCod ][3]; + KwdSct *kwd = &msh->KwdTab[ KwdCod ]; + + /* Set the kwd's type */ + + if(!strlen(GmfKwdFmt[ KwdCod ][2])) + kwd->typ = InfKwd; + else if(!strcmp(InpFmt, "sr")) + kwd->typ = SolKwd; + else + kwd->typ = RegKwd; + + /* Get the solution-field's size */ + + if(kwd->typ == SolKwd) + for(i=0;iNmbTyp;i++) + switch(kwd->TypTab[i]) + { + case GmfSca : TmpSiz += 1; break; + case GmfVec : TmpSiz += msh->dim; break; + case GmfSymMat : TmpSiz += (msh->dim * (msh->dim+1)) / 2; break; + case GmfMat : TmpSiz += msh->dim * msh->dim; break; + } + + /* Scan each character from the format string */ + + i = kwd->SolSiz = kwd->NmbWrd = 0; + + while(i < strlen(InpFmt)) + { + chr = InpFmt[ i++ ]; + + if(chr == 'd') + { + chr = InpFmt[i++]; + + for(j=0;jdim;j++) + kwd->fmt[ kwd->SolSiz++ ] = chr; + } + else if(chr == 's') + { + chr = InpFmt[i++]; + + for(j=0;jfmt[ kwd->SolSiz++ ] = chr; + } + else + kwd->fmt[ kwd->SolSiz++ ] = chr; + } + + for(i=0;iSolSiz;i++) + if(kwd->fmt[i] == 'i') + kwd->NmbWrd++; + else if(msh->ver >= 2) + kwd->NmbWrd += 2; + else + kwd->NmbWrd++; +} + + +/*----------------------------------------------------------*/ +/* Read a four bytes word from a mesh file */ +/*----------------------------------------------------------*/ + +static void ScaWrd(GmfMshSct *msh, unsigned char *wrd) +{ + unsigned char swp; + + fread(wrd, WrdSiz, 1, msh->hdl); + + if(msh->cod == 1) + return; + + swp = wrd[3]; + wrd[3] = wrd[0]; + wrd[0] = swp; + + swp = wrd[2]; + wrd[2] = wrd[1]; + wrd[1] = swp; +} + + +/*----------------------------------------------------------*/ +/* Read an eight bytes word from a mesh file */ +/*----------------------------------------------------------*/ + +static void ScaDblWrd(GmfMshSct *msh, unsigned char *wrd) +{ + int i; + unsigned char swp; + + fread(wrd, WrdSiz, 2, msh->hdl); + + if(msh->cod == 1) + return; + + for(i=0;i<4;i++) + { + swp = wrd[7-i]; + wrd[7-i] = wrd[i]; + wrd[i] = swp; + } +} + + +/*----------------------------------------------------------*/ +/* Read ablock of four bytes word from a mesh file */ +/*----------------------------------------------------------*/ + +static void ScaBlk(GmfMshSct *msh, unsigned char *blk, int siz) +{ + int i, j; + unsigned char swp, *wrd; + + fread(blk, WrdSiz, siz, msh->hdl); + + if(msh->cod == 1) + return; + + for(i=0;iver >= 3) + ScaDblWrd(msh, (unsigned char*)&pos); + else + { + ScaWrd(msh, (unsigned char*)&IntVal); + pos = IntVal; + } + + return(pos); +} + + +/*----------------------------------------------------------*/ +/* Write a four bytes word to a mesh file */ +/*----------------------------------------------------------*/ + +static void RecWrd(GmfMshSct *msh, unsigned char *wrd) +{ + fwrite(wrd, WrdSiz, 1, msh->hdl); +} + + +/*----------------------------------------------------------*/ +/* Write an eight bytes word to a mesh file */ +/*----------------------------------------------------------*/ + +static void RecDblWrd(GmfMshSct *msh, unsigned char *wrd) +{ + fwrite(wrd, WrdSiz, 2, msh->hdl); +} + + +/*----------------------------------------------------------*/ +/* Write a block of four bytes word to a mesh file */ +/*----------------------------------------------------------*/ + +static void RecBlk(GmfMshSct *msh, unsigned char *blk, int siz) +{ + /* Copy this line-block into the main mesh buffer */ + + if(siz) + { + memcpy(&msh->blk[ msh->pos ], blk, siz * WrdSiz); + msh->pos += siz * WrdSiz; + } + + /* When the buffer is full or this procedure is called with a 0 size, flush the cache on disk */ + + if( (msh->pos > BufSiz) || (!siz && msh->pos) ) + { + fwrite(msh->blk, 1, msh->pos, msh->hdl); + msh->pos = 0; + } +} + + +/*----------------------------------------------------------*/ +/* Write a 4 or 8 bytes position in a mesh file */ +/*----------------------------------------------------------*/ + +static void SetPos(GmfMshSct *msh, long pos) +{ + int IntVal; + + if(msh->ver >= 3) + RecDblWrd(msh, (unsigned char*)&pos); + else + { + IntVal = pos; + RecWrd(msh, (unsigned char*)&IntVal); + } +} diff --git a/src/DriverGMF/libmesh5.h b/src/DriverGMF/libmesh5.h new file mode 100644 index 000000000..66579574d --- /dev/null +++ b/src/DriverGMF/libmesh5.h @@ -0,0 +1,155 @@ + + +/*----------------------------------------------------------*/ +/* */ +/* LIBMESH V 5.46 */ +/* */ +/*----------------------------------------------------------*/ +/* */ +/* Description: handle .meshb file format I/O */ +/* Author: Loic MARECHAL */ +/* Creation date: feb 16 2007 */ +/* Last modification: dec 09 2011 */ +/* */ +/*----------------------------------------------------------*/ + + +/*----------------------------------------------------------*/ +/* Defines */ +/*----------------------------------------------------------*/ + +#include "SMESH_DriverGMF.hxx" + +#define GmfStrSiz 1024 +#define GmfMaxTyp 1000 +#define GmfMaxKwd 80 +#define GmfMshVer 1 +#define GmfRead 1 +#define GmfWrite 2 +#define GmfSca 1 +#define GmfVec 2 +#define GmfSymMat 3 +#define GmfMat 4 +#define GmfFloat 1 +#define GmfDouble 2 + +enum GmfKwdCod +{ + GmfReserved1, \ + GmfVersionFormatted, \ + GmfReserved2, \ + GmfDimension, \ + GmfVertices, \ + GmfEdges, \ + GmfTriangles, \ + GmfQuadrilaterals, \ + GmfTetrahedra, \ + GmfPrisms, \ + GmfHexahedra, \ + GmfIterationsAll, \ + GmfTimesAll, \ + GmfCorners, \ + GmfRidges, \ + GmfRequiredVertices, \ + GmfRequiredEdges, \ + GmfRequiredTriangles, \ + GmfRequiredQuadrilaterals, \ + GmfTangentAtEdgeVertices, \ + GmfNormalAtVertices, \ + GmfNormalAtTriangleVertices, \ + GmfNormalAtQuadrilateralVertices, \ + GmfAngleOfCornerBound, \ + GmfTrianglesP2, \ + GmfEdgesP2, \ + GmfSolAtPyramids, \ + GmfQuadrilateralsQ2, \ + GmfISolAtPyramids, \ + GmfSubDomainFromGeom, \ + GmfTetrahedraP2, \ + GmfFault_NearTri, \ + GmfFault_Inter, \ + GmfHexahedraQ2, \ + GmfExtraVerticesAtEdges, \ + GmfExtraVerticesAtTriangles, \ + GmfExtraVerticesAtQuadrilaterals, \ + GmfExtraVerticesAtTetrahedra, \ + GmfExtraVerticesAtPrisms, \ + GmfExtraVerticesAtHexahedra, \ + GmfVerticesOnGeometricVertices, \ + GmfVerticesOnGeometricEdges, \ + GmfVerticesOnGeometricTriangles, \ + GmfVerticesOnGeometricQuadrilaterals, \ + GmfEdgesOnGeometricEdges, \ + GmfFault_FreeEdge, \ + GmfPolyhedra, \ + GmfPolygons, \ + GmfFault_Overlap, \ + GmfPyramids, \ + GmfBoundingBox, \ + GmfBody, \ + GmfPrivateTable, \ + GmfFault_BadShape, \ + GmfEnd, \ + GmfTrianglesOnGeometricTriangles, \ + GmfTrianglesOnGeometricQuadrilaterals, \ + GmfQuadrilateralsOnGeometricTriangles, \ + GmfQuadrilateralsOnGeometricQuadrilaterals, \ + GmfTangents, \ + GmfNormals, \ + GmfTangentAtVertices, \ + GmfSolAtVertices, \ + GmfSolAtEdges, \ + GmfSolAtTriangles, \ + GmfSolAtQuadrilaterals, \ + GmfSolAtTetrahedra, \ + GmfSolAtPrisms, \ + GmfSolAtHexahedra, \ + GmfDSolAtVertices, \ + GmfISolAtVertices, \ + GmfISolAtEdges, \ + GmfISolAtTriangles, \ + GmfISolAtQuadrilaterals, \ + GmfISolAtTetrahedra, \ + GmfISolAtPrisms, \ + GmfISolAtHexahedra, \ + GmfIterations, \ + GmfTime, \ + GmfFault_SmallTri, \ + GmfCoarseHexahedra +}; + + +/*----------------------------------------------------------*/ +/* External procedures */ +/*----------------------------------------------------------*/ + +MESHDriverGMF_EXPORT extern int GmfOpenMesh(const char *, int, ...); +MESHDriverGMF_EXPORT extern int GmfCloseMesh(int); +MESHDriverGMF_EXPORT extern int GmfStatKwd(int, int, ...); +MESHDriverGMF_EXPORT extern int GmfGotoKwd(int, int); +MESHDriverGMF_EXPORT extern int GmfSetKwd(int, int, ...); +MESHDriverGMF_EXPORT extern void GmfGetLin(int, int, ...); +MESHDriverGMF_EXPORT extern void GmfSetLin(int, int, ...); + + +/*----------------------------------------------------------*/ +/* Fortran 77 API */ +/*----------------------------------------------------------*/ + +#if defined(F77_NO_UNDER_SCORE) +#define call(x) x +#else +#define call(x) x ## _ +#endif + + +/*----------------------------------------------------------*/ +/* Transmesh private API */ +/*----------------------------------------------------------*/ + +#ifdef TRANSMESH + +MESHDriverGMF_EXPORT extern char *GmfKwdFmt[ GmfMaxKwd + 1 ][4]; +MESHDriverGMF_EXPORT extern int GmfCpyLin(int, int, int); + +#endif diff --git a/src/DriverMED/DriverMED_R_SMESHDS_Mesh.cxx b/src/DriverMED/DriverMED_R_SMESHDS_Mesh.cxx index a60b77ca9..35caa0286 100644 --- a/src/DriverMED/DriverMED_R_SMESHDS_Mesh.cxx +++ b/src/DriverMED/DriverMED_R_SMESHDS_Mesh.cxx @@ -205,7 +205,7 @@ DriverMED_R_SMESHDS_Mesh aNodeIds.resize( aNbBalls ); for(TInt iBall = 0; iBall < aNbBalls && anIsNodeNum; iBall++) { - aNodeIds[iBall] = aNodeInfo->GetElemNum(iBall); + aNodeIds[iBall] = aNodeInfo->GetElemNum( (*aBallInfo->myConn)[ iBall ]-1 ); anIsNodeNum = myMesh->FindNode( aNodeIds[iBall] ) ? eVRAI : eFAUX; } } diff --git a/src/DriverMED/DriverMED_W_SMESHDS_Mesh.cxx b/src/DriverMED/DriverMED_W_SMESHDS_Mesh.cxx index 39b03f2d6..9d1bf4adf 100644 --- a/src/DriverMED/DriverMED_W_SMESHDS_Mesh.cxx +++ b/src/DriverMED/DriverMED_W_SMESHDS_Mesh.cxx @@ -411,7 +411,7 @@ Driver_Mesh::Status DriverMED_W_SMESHDS_Mesh::Perform() if (myDoGroupOfFaces && nbFaces) myFacesDefaultFamilyId = REST_FACES_FAMILY; if (myDoGroupOfVolumes && nbVolumes) myVolumesDefaultFamilyId = REST_VOLUMES_FAMILY; if (myDoGroupOf0DElems && nb0DElements) my0DElementsDefaultFamilyId = REST_0DELEM_FAMILY; - if (myDoGroupOfVolumes && nbVolumes) myBallsDefaultFamilyId = REST_BALL_FAMILY; + if (myDoGroupOfBalls && nbBalls) myBallsDefaultFamilyId = REST_BALL_FAMILY; MESSAGE("Perform - aFamilyInfo"); //cout << " DriverMED_Family::MakeFamilies() " << endl; diff --git a/src/DriverMED/Makefile.am b/src/DriverMED/Makefile.am index 0e6d83571..7fbced58b 100644 --- a/src/DriverMED/Makefile.am +++ b/src/DriverMED/Makefile.am @@ -55,6 +55,7 @@ libMeshDriverMED_la_CPPFLAGS = \ $(BOOST_CPPFLAGS) \ -I$(srcdir)/../Driver \ -I$(srcdir)/../SMDS \ + -I$(srcdir)/../SMESHUtils \ -I$(srcdir)/../SMESHDS libMeshDriverMED_la_LDFLAGS = \ diff --git a/src/DriverUNV/Makefile.am b/src/DriverUNV/Makefile.am index 0e05ad761..c66dea1bc 100644 --- a/src/DriverUNV/Makefile.am +++ b/src/DriverUNV/Makefile.am @@ -67,6 +67,7 @@ libMeshDriverUNV_la_CPPFLAGS = \ $(BOOST_CPPFLAGS) \ -I$(srcdir)/../Driver \ -I$(srcdir)/../SMDS \ + -I$(srcdir)/../SMESHUtils \ -I$(srcdir)/../SMESHDS libMeshDriverUNV_la_LDFLAGS = \ diff --git a/src/DriverUNV/UNV164_Structure.cxx b/src/DriverUNV/UNV164_Structure.cxx index 0fff1bdc5..a48520cdb 100644 --- a/src/DriverUNV/UNV164_Structure.cxx +++ b/src/DriverUNV/UNV164_Structure.cxx @@ -62,7 +62,7 @@ void UNV164::Write(std::ofstream& out_stream) EXCEPTION(runtime_error,"ERROR: Output file not good."); out_stream<<" -1" << endl; - out_stream<<" "<<_label_dataset << endl; + out_stream<<" "<<_label_dataset << endl; out_stream<<" 1 SI: Meter (newton) 2" << endl; out_stream<<" 1.0000000000000000E+0 1.0000000000000000E+0 1.0000000000000000E+0" << endl; diff --git a/src/Makefile.am b/src/Makefile.am index b969674a1..5276980b9 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -21,7 +21,6 @@ # Author : Patrick GOLDBRONN (CEA) # Modified by : Alexander BORODIN (OCN) - autotools usage # Module : SMESH -# $Header$ # include $(top_srcdir)/adm_local/unix/make_common_starter.am @@ -39,6 +38,7 @@ SUBDIRS = \ DriverDAT \ DriverUNV \ DriverSTL \ + DriverGMF \ $(DriverCGNS_SUDIR) \ SMESH \ SMESH_I \ @@ -61,5 +61,6 @@ if SMESH_ENABLE_GUI endif DIST_SUBDIRS = SMDS SMESHDS Controls Driver DriverMED DriverDAT DriverUNV DriverSTL DriverCGNS \ + DriverGMF \ SMESHUtils SMESH SMESH_I SMESHClient SMESH_SWIG MEFISTO2 StdMeshers StdMeshers_I OBJECT \ SMESHFiltersSelection SMESHGUI PluginUtils SMESH_SWIG_WITHIHM StdMeshersGUI SMESH_PY Tools diff --git a/src/OBJECT/Makefile.am b/src/OBJECT/Makefile.am index 31cb50d27..59cf1400c 100644 --- a/src/OBJECT/Makefile.am +++ b/src/OBJECT/Makefile.am @@ -37,7 +37,9 @@ salomeinclude_HEADERS = \ SMESH_FaceOrientationFilter.h \ SMESH_ScalarBarActor.h \ SMESH_NodeLabelActor.h \ - SMESH_CellLabelActor.h + SMESH_CellLabelActor.h \ + SMESH_SVTKActor.h + # Libraries targets @@ -52,7 +54,8 @@ dist_libSMESHObject_la_SOURCES = \ SMESH_FaceOrientationFilter.cxx \ SMESH_ScalarBarActor.cxx \ SMESH_NodeLabelActor.cxx \ - SMESH_CellLabelActor.cxx + SMESH_CellLabelActor.cxx \ + SMESH_SVTKActor.cxx libSMESHObject_la_CPPFLAGS = \ $(QT_INCLUDES) \ diff --git a/src/OBJECT/SMESH_Actor.cxx b/src/OBJECT/SMESH_Actor.cxx index 4daba11f8..1463f03fe 100644 --- a/src/OBJECT/SMESH_Actor.cxx +++ b/src/OBJECT/SMESH_Actor.cxx @@ -37,6 +37,7 @@ #include "VTKViewer_ExtractUnstructuredGrid.h" #include "VTKViewer_FramedTextActor.h" #include "SALOME_InteractiveObject.hxx" +#include "SMESH_SVTKActor.h" #include "SUIT_Session.h" #include "SUIT_ResourceMgr.h" @@ -127,6 +128,12 @@ SMESH_ActorDef::SMESH_ActorDef() myIsPointsVisible = false; myIsEntityModeCache = false; + myHighlightActor = SMESH_SVTKActor::New(); + myHighlightActor->Initialize(); + + myPreHighlightActor = SMESH_SVTKActor::New(); + myPreHighlightActor->Initialize(); + myIsShrinkable = false; myIsShrunk = false; @@ -141,6 +148,7 @@ SMESH_ActorDef::SMESH_ActorDef() vtkFloatingPointType aElem0DSize = SMESH::GetFloat("SMESH:elem0d_size",5); vtkFloatingPointType aBallElemSize = SMESH::GetFloat("SMESH:ball_elem_size",10); vtkFloatingPointType aLineWidth = SMESH::GetFloat("SMESH:element_width",1); + vtkFloatingPointType aOutlineWidth = SMESH::GetFloat("SMESH:outline_width",1); vtkMatrix4x4 *aMatrix = vtkMatrix4x4::New(); VTKViewer_ExtractUnstructuredGrid* aFilter = NULL; @@ -159,6 +167,15 @@ SMESH_ActorDef::SMESH_ActorDef() bfc = Qtx::mainColorToSecondary(ffc, delta); myBackSurfaceProp->SetColor( bfc.red() / 255. , bfc.green() / 255. , bfc.blue() / 255. ); + myNormalVProp = vtkProperty::New(); + SMESH::GetColor( "SMESH", "volume_color", ffc, delta, "255,0,170|-100" ); + myNormalVProp->SetColor( ffc.redF(), ffc.greenF(), ffc.blueF() ); + myDeltaVBrightness = delta; + + myReversedVProp = vtkProperty::New(); + bfc = Qtx::mainColorToSecondary(ffc, delta); + myReversedVProp->SetColor( bfc.red() / 255. , bfc.green() / 255. , bfc.blue() / 255. ); + my2DActor = SMESH_CellLabelActor::New(); my2DActor->SetStoreGemetryMapping(true); my2DActor->SetUserMatrix(aMatrix); @@ -201,8 +218,8 @@ SMESH_ActorDef::SMESH_ActorDef() my3DActor->SetStoreGemetryMapping(true); my3DActor->SetUserMatrix(aMatrix); my3DActor->PickableOff(); - my3DActor->SetProperty(mySurfaceProp); - my3DActor->SetBackfaceProperty(myBackSurfaceProp); + my3DActor->SetProperty(myNormalVProp); + my3DActor->SetBackfaceProperty(myReversedVProp); my3DActor->SetRepresentation(SMESH_DeviceActor::eSurface); my3DActor->SetCoincident3DAllowed(true); aFilter = my3DActor->GetExtractUnstructuredGrid(); @@ -224,11 +241,19 @@ SMESH_ActorDef::SMESH_ActorDef() aFilter->RegisterCellsWithType(VTK_POLYHEDRON); //#endif + my3DExtProp = vtkProperty::New(); + my3DExtProp->DeepCopy(myNormalVProp); + SMESH::GetColor( "SMESH", "volume_color", anRGB[0], anRGB[1], anRGB[2], QColor( 255, 0, 170 ) ); + anRGB[0] = 1 - anRGB[0]; + anRGB[1] = 1 - anRGB[1]; + anRGB[2] = 1 - anRGB[2]; + my3DExtProp->SetColor(anRGB[0],anRGB[1],anRGB[2]); + my3DExtActor = SMESH_DeviceActor::New(); my3DExtActor->SetUserMatrix(aMatrix); my3DExtActor->PickableOff(); - my3DExtActor->SetProperty(my2DExtProp); - my3DExtActor->SetBackfaceProperty(my2DExtProp); + my3DExtActor->SetProperty(my3DExtProp); + my3DExtActor->SetBackfaceProperty(my3DExtProp); my3DExtActor->SetRepresentation(SMESH_DeviceActor::eSurface); my3DExtActor->SetCoincident3DAllowed(true); aFilter = my3DExtActor->GetExtractUnstructuredGrid(); @@ -318,7 +343,7 @@ SMESH_ActorDef::SMESH_ActorDef() //Definition 0D device of the actor (ball elements) //----------------------------------------------- myBallProp = vtkProperty::New(); - SMESH::GetColor( "SMESH", "ball_elem_color", anRGB[0], anRGB[1], anRGB[2], QColor( 0, 255, 0 ) ); + SMESH::GetColor( "SMESH", "ball_elem_color", anRGB[0], anRGB[1], anRGB[2], QColor( 0, 85, 255 ) ); myBallProp->SetColor(anRGB[0],anRGB[1],anRGB[2]); myBallProp->SetPointSize(aBallElemSize); @@ -330,9 +355,7 @@ SMESH_ActorDef::SMESH_ActorDef() myBallActor->SetProperty(myBallProp); myBallActor->SetRepresentation(SMESH_DeviceActor::eSurface); aFilter = myBallActor->GetExtractUnstructuredGrid(); - //aFilter->SetModeOfExtraction(VTKViewer_ExtractUnstructuredGrid::ePoints); aFilter->SetModeOfChanging(VTKViewer_ExtractUnstructuredGrid::eAdding); - aFilter->RegisterCellsWithType(VTK_VERTEX); aFilter->RegisterCellsWithType(VTK_POLY_VERTEX); //my0DExtProp = vtkProperty::New(); @@ -410,14 +433,18 @@ SMESH_ActorDef::SMESH_ActorDef() myHighlightProp->SetLineWidth(aLineWidth); myHighlightProp->SetRepresentation(1); + myBallHighlightProp = vtkProperty::New(); + myBallHighlightProp->DeepCopy(myHighlightProp); + myBallHighlightProp->SetPointSize(aBallElemSize); + + myOutLineProp = vtkProperty::New(); myOutLineProp->SetAmbient(1.0); myOutLineProp->SetDiffuse(0.0); myOutLineProp->SetSpecular(0.0); SMESH::GetColor( "SMESH", "outline_color", anRGB[0], anRGB[1], anRGB[2], QColor( 0, 70, 0 ) ); myOutLineProp->SetColor(anRGB[0],anRGB[1],anRGB[2]); - myOutLineProp->SetPointSize(aElem0DSize); // ?? - myOutLineProp->SetLineWidth(aLineWidth); + myOutLineProp->SetLineWidth(aOutlineWidth); myOutLineProp->SetRepresentation(1); myPreselectProp = vtkProperty::New(); @@ -430,6 +457,10 @@ SMESH_ActorDef::SMESH_ActorDef() myPreselectProp->SetLineWidth(aLineWidth); myPreselectProp->SetRepresentation(1); + myBallPreselectProp = vtkProperty::New(); + myBallPreselectProp->DeepCopy(myPreselectProp); + myBallPreselectProp->SetPointSize(aBallElemSize); + myHighlitableActor = SMESH_DeviceActor::New(); myHighlitableActor->SetUserMatrix(aMatrix); myHighlitableActor->PickableOff(); @@ -490,7 +521,7 @@ SMESH_ActorDef::SMESH_ActorDef() my2DActor->SetQuadraticArcAngle(aQuadraticAngle); // Set colors of the name actor - SMESH::GetColor( "SMESH", "fill_color", anRGB[0], anRGB[1], anRGB[2], QColor( 0, 170, 255 ) ); + SMESH::GetColor( "SMESH", "default_grp_color", anRGB[0], anRGB[1], anRGB[2], QColor( 0, 170, 255 ) ); myNameActor->SetBackgroundColor(anRGB[0], anRGB[1], anRGB[2]); SMESH::GetColor( "SMESH", "group_name_color", anRGB[0], anRGB[1], anRGB[2], QColor( 255, 255, 255 ) ); myNameActor->SetForegroundColor(anRGB[0], anRGB[1], anRGB[2]); @@ -499,6 +530,8 @@ SMESH_ActorDef::SMESH_ActorDef() my2dHistogram = 0; #endif + SetBallSize(aBallElemSize); + Set0DSize(aElem0DSize); } @@ -518,6 +551,8 @@ SMESH_ActorDef::~SMESH_ActorDef() mySurfaceProp->Delete(); myBackSurfaceProp->Delete(); + myNormalVProp->Delete(); + myReversedVProp->Delete(); myOutLineProp->Delete(); myEdgeProp->Delete(); @@ -544,6 +579,7 @@ SMESH_ActorDef::~SMESH_ActorDef() my2DExtProp->Delete(); my2DExtActor->Delete(); my3DActor->Delete(); + my3DExtProp->Delete(); my3DExtActor->Delete(); myNodeActor->Delete(); @@ -555,6 +591,9 @@ SMESH_ActorDef::~SMESH_ActorDef() myImplicitBoolean->Delete(); myTimeStamp->Delete(); + myBallHighlightProp->Delete(); + myBallPreselectProp->Delete(); + } void SMESH_ActorDef::Delete() @@ -639,15 +678,15 @@ bool SMESH_ActorDef::GetFacesOriented() return myIsFacesOriented; } -void SMESH_ActorDef::SetFacesOrientationColor(vtkFloatingPointType theColor[3]) +void SMESH_ActorDef::SetFacesOrientationColor(vtkFloatingPointType r,vtkFloatingPointType g,vtkFloatingPointType b) { - my2DActor->SetFacesOrientationColor( theColor ); - my3DActor->SetFacesOrientationColor( theColor ); + my2DActor->SetFacesOrientationColor( r, g, b ); + my3DActor->SetFacesOrientationColor( r, g, b ); } -void SMESH_ActorDef::GetFacesOrientationColor(vtkFloatingPointType theColor[3]) +void SMESH_ActorDef::GetFacesOrientationColor(vtkFloatingPointType& r,vtkFloatingPointType& g,vtkFloatingPointType& b) { - my3DActor->GetFacesOrientationColor( theColor ); + my3DActor->GetFacesOrientationColor( r, g, b ); } void SMESH_ActorDef::SetFacesOrientationScale(vtkFloatingPointType theScale) @@ -957,6 +996,9 @@ SetControlMode(eControl theMode, void SMESH_ActorDef::AddToRender(vtkRenderer* theRenderer){ + + //myHighlightActor->AddToRender(theRenderer); + theRenderer->AddActor(myBaseActor); theRenderer->AddActor(myNodeExtActor); theRenderer->AddActor(my1DExtActor); @@ -1053,6 +1095,7 @@ bool SMESH_ActorDef::Init(TVisualObjPtr theVisualObj, my2DActor->GetPolygonOffsetParameters(aFactor,aUnits); my2DActor->SetPolygonOffsetParameters(aFactor,aUnits*0.75); my2DExtActor->SetPolygonOffsetParameters(aFactor,aUnits*0.5); + my3DActor->SetPolygonOffsetParameters(2*aFactor,aUnits); SUIT_ResourceMgr* mgr = SUIT_Session::session()->resourceMgr(); if( !mgr ) @@ -1307,10 +1350,10 @@ void SMESH_ActorDef::SetVisibility(int theMode, bool theIsUpdateRepersentation){ myNodeActor->VisibilityOn(); } - if(myEntityMode & e0DElements){ + if(myEntityMode & e0DElements && GetRepresentation() != ePoint ){ my0DActor->VisibilityOn(); } - if(myEntityMode & eBallElem){ + if(myEntityMode & eBallElem && GetRepresentation() != ePoint ){ myBallActor->VisibilityOn(); } @@ -1492,6 +1535,8 @@ void SMESH_ActorDef::SetRepresentation (int theMode) int aNbEdges = myVisualObj->GetNbEntities(SMDSAbs_Edge); int aNbFaces = myVisualObj->GetNbEntities(SMDSAbs_Face); int aNbVolumes = myVisualObj->GetNbEntities(SMDSAbs_Volume); + int aNb0Ds = myVisualObj->GetNbEntities(SMDSAbs_0DElement); + int aNbBalls = myVisualObj->GetNbEntities(SMDSAbs_Ball); if (theMode < 0) { myRepresentation = eSurface; @@ -1503,10 +1548,10 @@ void SMESH_ActorDef::SetRepresentation (int theMode) } else { switch (theMode) { case eEdge: - if (!aNbFaces && !aNbVolumes && !aNbEdges) return; + if (!aNbFaces && !aNbVolumes && !aNbEdges && !aNb0Ds && !aNbBalls) return; break; case eSurface: - if (!aNbFaces && !aNbVolumes) return; + if (!aNbFaces && !aNbVolumes && !aNb0Ds && !aNbBalls) return; break; } myRepresentation = theMode; @@ -1528,6 +1573,7 @@ void SMESH_ActorDef::SetRepresentation (int theMode) myNodeActor->SetVisibility(false); myNodeExtActor->SetVisibility(false); vtkProperty *aProp = NULL, *aBackProp = NULL; + vtkProperty *aPropVN = NULL, *aPropVR = NULL; SMESH_DeviceActor::EReperesent aReperesent = SMESH_DeviceActor::EReperesent(-1); SMESH_Actor::EQuadratic2DRepresentation aQuadraticMode = GetQuadratic2DRepresentation(); switch (myRepresentation) { @@ -1535,16 +1581,18 @@ void SMESH_ActorDef::SetRepresentation (int theMode) myPickableActor = myNodeActor; myNodeActor->SetVisibility(true); aQuadraticMode = SMESH_Actor::eLines; - aProp = aBackProp = myNodeProp; + aProp = aBackProp = aPropVN = aPropVR = myNodeProp; aReperesent = SMESH_DeviceActor::ePoint; break; case eEdge: - aProp = aBackProp = myEdgeProp; + aProp = aBackProp = aPropVN = aPropVR = myEdgeProp; aReperesent = SMESH_DeviceActor::eInsideframe; break; case eSurface: aProp = mySurfaceProp; aBackProp = myBackSurfaceProp; + aPropVN = myNormalVProp; + aPropVR = myReversedVProp; aReperesent = SMESH_DeviceActor::eSurface; break; } @@ -1560,8 +1608,8 @@ void SMESH_ActorDef::SetRepresentation (int theMode) my2DExtActor->SetRepresentation(aReperesent); - my3DActor->SetProperty(aProp); - my3DActor->SetBackfaceProperty(aBackProp); + my3DActor->SetProperty(aPropVN); + my3DActor->SetBackfaceProperty(aPropVR); my3DActor->SetRepresentation(aReperesent); //my0DExtActor->SetVisibility(false); @@ -1633,9 +1681,12 @@ void SMESH_ActorDef::UpdateHighlight(){ { if(myIsHighlighted) { myHighlitableActor->SetProperty(myHighlightProp); + myBallActor->SetProperty(myBallHighlightProp); }else if(myIsPreselected){ myHighlitableActor->SetProperty(myPreselectProp); + myBallActor->SetProperty(myBallPreselectProp); } else if(anIsVisible){ + myBallActor->SetProperty(myBallProp); (myRepresentation == eSurface) ? myHighlitableActor->SetProperty(myOutLineProp) : myHighlitableActor->SetProperty(myEdgeProp); } @@ -1777,10 +1828,15 @@ static void GetColor(vtkProperty *theProperty, vtkFloatingPointType& r,vtkFloati void SMESH_ActorDef::SetOpacity(vtkFloatingPointType theValue){ mySurfaceProp->SetOpacity(theValue); myBackSurfaceProp->SetOpacity(theValue); + myNormalVProp->SetOpacity(theValue); + myReversedVProp->SetOpacity(theValue); myEdgeProp->SetOpacity(theValue); + myOutLineProp->SetOpacity(theValue); myNodeProp->SetOpacity(theValue); my1DProp->SetOpacity(theValue); + my0DProp->SetOpacity(theValue); + myBallProp->SetOpacity(theValue); } @@ -1791,9 +1847,9 @@ vtkFloatingPointType SMESH_ActorDef::GetOpacity(){ void SMESH_ActorDef::SetSufaceColor(vtkFloatingPointType r,vtkFloatingPointType g,vtkFloatingPointType b, int delta){ mySurfaceProp->SetColor(r,g,b); + my2DExtProp->SetColor(1.0-r,1.0-g,1.0-b); if( SMESH_GroupObj* aGroupObj = dynamic_cast( myVisualObj.get() ) ) - if( aGroupObj->GetElementType() == SMDSAbs_Face || - aGroupObj->GetElementType() == SMDSAbs_Volume ) + if( aGroupObj->GetElementType() == SMDSAbs_Face ) myNameActor->SetBackgroundColor(r,g,b); myDeltaBrightness = delta; @@ -1804,10 +1860,27 @@ void SMESH_ActorDef::SetSufaceColor(vtkFloatingPointType r,vtkFloatingPointType void SMESH_ActorDef::GetSufaceColor(vtkFloatingPointType& r,vtkFloatingPointType& g,vtkFloatingPointType& b, int& delta){ ::GetColor(mySurfaceProp,r,g,b); - my2DExtProp->SetColor(1.0-r,1.0-g,1.0-b); delta = myDeltaBrightness; } +void SMESH_ActorDef::SetVolumeColor(vtkFloatingPointType r,vtkFloatingPointType g,vtkFloatingPointType b, int delta){ + myNormalVProp->SetColor(r,g,b); + my3DExtProp->SetColor(1.0-r,1.0-g,1.0-b); + if( SMESH_GroupObj* aGroupObj = dynamic_cast( myVisualObj.get() ) ) + if( aGroupObj->GetElementType() == SMDSAbs_Volume ) + myNameActor->SetBackgroundColor(r,g,b); + + myDeltaVBrightness = delta; + QColor bfc = Qtx::mainColorToSecondary(QColor(int(r*255),int(g*255),int(b*255)), delta); + myReversedVProp->SetColor( bfc.red() / 255. , bfc.green() / 255. , bfc.blue() / 255. ); + Modified(); +} + +void SMESH_ActorDef::GetVolumeColor(vtkFloatingPointType& r,vtkFloatingPointType& g,vtkFloatingPointType& b, int& delta){ + ::GetColor(myNormalVProp,r,g,b); + delta = myDeltaVBrightness; +} + void SMESH_ActorDef::SetEdgeColor(vtkFloatingPointType r,vtkFloatingPointType g,vtkFloatingPointType b){ myEdgeProp->SetColor(r,g,b); my1DProp->SetColor(r,g,b); @@ -1871,6 +1944,7 @@ void SMESH_ActorDef::GetBallColor(vtkFloatingPointType& r,vtkFloatingPointType& void SMESH_ActorDef::SetHighlightColor(vtkFloatingPointType r,vtkFloatingPointType g,vtkFloatingPointType b){ myHighlightProp->SetColor(r,g,b); + myBallHighlightProp->SetColor(r,g,b); Modified(); } @@ -1880,6 +1954,7 @@ void SMESH_ActorDef::GetHighlightColor(vtkFloatingPointType& r,vtkFloatingPointT void SMESH_ActorDef::SetPreHighlightColor(vtkFloatingPointType r,vtkFloatingPointType g,vtkFloatingPointType b){ myPreselectProp->SetColor(r,g,b); + myBallPreselectProp->SetColor(r,g,b); Modified(); } @@ -1899,15 +1974,36 @@ void SMESH_ActorDef::SetLineWidth(vtkFloatingPointType theVal){ my1DProp->SetLineWidth(theVal + aLineWidthInc); my1DExtProp->SetLineWidth(theVal + aLineWidthInc); my2DExtProp->SetLineWidth(theVal + aLineWidthInc); + my3DExtProp->SetLineWidth(theVal + aLineWidthInc); myOutLineProp->SetLineWidth(theVal); myHighlightProp->SetLineWidth(theVal); myPreselectProp->SetLineWidth(theVal); Modified(); } +vtkFloatingPointType SMESH_ActorDef::GetOutlineWidth() +{ + return myOutLineProp->GetLineWidth(); +} + +void SMESH_ActorDef::SetOutlineWidth(vtkFloatingPointType theVal) +{ + myOutLineProp->SetLineWidth(theVal); + Modified(); +} void SMESH_ActorDef::Set0DSize(vtkFloatingPointType theVal){ my0DProp->SetPointSize(theVal); + myHighlightProp->SetPointSize(theVal); + myPreselectProp->SetPointSize(theVal); + + if(SMESH_SVTKActor* aCustom = SMESH_SVTKActor::SafeDownCast( myHighlightActor )) { + aCustom->Set0DSize(theVal); + } + if(SMESH_SVTKActor* aCustom = SMESH_SVTKActor::SafeDownCast( myPreHighlightActor )) { + aCustom->Set0DSize(theVal); + } + Modified(); } @@ -1917,6 +2013,15 @@ vtkFloatingPointType SMESH_ActorDef::Get0DSize(){ void SMESH_ActorDef::SetBallSize(vtkFloatingPointType theVal){ myBallProp->SetPointSize(theVal); + myBallHighlightProp->SetPointSize(theVal); + myBallPreselectProp->SetPointSize(theVal); + if(SMESH_SVTKActor* aCustom = SMESH_SVTKActor::SafeDownCast( myHighlightActor )) { + aCustom->SetBallSize(theVal); + } + if(SMESH_SVTKActor* aCustom = SMESH_SVTKActor::SafeDownCast( myPreHighlightActor )) { + aCustom->SetBallSize(theVal); + } + Modified(); } diff --git a/src/OBJECT/SMESH_Actor.h b/src/OBJECT/SMESH_Actor.h index 4e04546f4..fc954253d 100644 --- a/src/OBJECT/SMESH_Actor.h +++ b/src/OBJECT/SMESH_Actor.h @@ -64,6 +64,9 @@ class SMESHOBJECT_EXPORT SMESH_Actor: public SALOME_Actor virtual void SetSufaceColor(vtkFloatingPointType r,vtkFloatingPointType g,vtkFloatingPointType b, int delta ) = 0; virtual void GetSufaceColor(vtkFloatingPointType& r,vtkFloatingPointType& g,vtkFloatingPointType& b, int& delta ) = 0; + virtual void SetVolumeColor(vtkFloatingPointType r,vtkFloatingPointType g,vtkFloatingPointType b, int delta ) = 0; + virtual void GetVolumeColor(vtkFloatingPointType& r,vtkFloatingPointType& g,vtkFloatingPointType& b, int& delta) = 0; + virtual void SetEdgeColor(vtkFloatingPointType r,vtkFloatingPointType g,vtkFloatingPointType b) = 0; virtual void GetEdgeColor(vtkFloatingPointType& r,vtkFloatingPointType& g,vtkFloatingPointType& b) = 0; @@ -88,6 +91,9 @@ class SMESHOBJECT_EXPORT SMESH_Actor: public SALOME_Actor virtual vtkFloatingPointType GetLineWidth() = 0; virtual void SetLineWidth(vtkFloatingPointType theVal) = 0; + virtual vtkFloatingPointType GetOutlineWidth() = 0; + virtual void SetOutlineWidth(vtkFloatingPointType theVal) = 0; + virtual void Set0DSize(vtkFloatingPointType size) = 0; virtual vtkFloatingPointType Get0DSize() = 0; @@ -122,8 +128,8 @@ class SMESHOBJECT_EXPORT SMESH_Actor: public SALOME_Actor virtual void SetFacesOriented(bool theIsFacesOriented) = 0; virtual bool GetFacesOriented() = 0; - virtual void SetFacesOrientationColor(vtkFloatingPointType theColor[3]) = 0; - virtual void GetFacesOrientationColor(vtkFloatingPointType theColor[3]) = 0; + virtual void SetFacesOrientationColor(vtkFloatingPointType r,vtkFloatingPointType g,vtkFloatingPointType b) = 0; + virtual void GetFacesOrientationColor(vtkFloatingPointType& r,vtkFloatingPointType& g,vtkFloatingPointType& b) = 0; virtual void SetFacesOrientationScale(vtkFloatingPointType theScale) = 0; virtual vtkFloatingPointType GetFacesOrientationScale() = 0; diff --git a/src/OBJECT/SMESH_ActorDef.h b/src/OBJECT/SMESH_ActorDef.h index b346e68b4..11d7fe41a 100644 --- a/src/OBJECT/SMESH_ActorDef.h +++ b/src/OBJECT/SMESH_ActorDef.h @@ -106,6 +106,9 @@ class SMESH_ActorDef : public SMESH_Actor virtual void SetSufaceColor(vtkFloatingPointType r,vtkFloatingPointType g,vtkFloatingPointType b, int delta ); virtual void GetSufaceColor(vtkFloatingPointType& r,vtkFloatingPointType& g,vtkFloatingPointType& b, int& delta); + virtual void SetVolumeColor(vtkFloatingPointType r,vtkFloatingPointType g,vtkFloatingPointType b, int delta ); + virtual void GetVolumeColor(vtkFloatingPointType& r,vtkFloatingPointType& g,vtkFloatingPointType& b, int& delta); + virtual void SetEdgeColor(vtkFloatingPointType r,vtkFloatingPointType g,vtkFloatingPointType b); virtual void GetEdgeColor(vtkFloatingPointType& r,vtkFloatingPointType& g,vtkFloatingPointType& b); @@ -131,6 +134,9 @@ class SMESH_ActorDef : public SMESH_Actor virtual vtkFloatingPointType GetLineWidth(); virtual void SetLineWidth(vtkFloatingPointType theVal); + virtual vtkFloatingPointType GetOutlineWidth(); + virtual void SetOutlineWidth(vtkFloatingPointType theVal); + virtual void Set0DSize(vtkFloatingPointType size); virtual vtkFloatingPointType Get0DSize(); @@ -180,8 +186,8 @@ class SMESH_ActorDef : public SMESH_Actor virtual void SetFacesOriented(bool theIsFacesOriented); virtual bool GetFacesOriented(); - virtual void SetFacesOrientationColor(vtkFloatingPointType theColor[3]); - virtual void GetFacesOrientationColor(vtkFloatingPointType theColor[3]); + virtual void SetFacesOrientationColor(vtkFloatingPointType r,vtkFloatingPointType g,vtkFloatingPointType b); + virtual void GetFacesOrientationColor(vtkFloatingPointType& r,vtkFloatingPointType& g,vtkFloatingPointType& b); virtual void SetFacesOrientationScale(vtkFloatingPointType theScale); virtual vtkFloatingPointType GetFacesOrientationScale(); @@ -233,6 +239,8 @@ class SMESH_ActorDef : public SMESH_Actor vtkProperty* mySurfaceProp; vtkProperty* myBackSurfaceProp; + vtkProperty* myNormalVProp; + vtkProperty* myReversedVProp; vtkProperty* myEdgeProp; vtkProperty* myNodeProp; @@ -243,12 +251,16 @@ class SMESH_ActorDef : public SMESH_Actor vtkProperty* myHighlightProp; vtkProperty* myOutLineProp; vtkProperty* myPreselectProp; + + vtkProperty* myBallHighlightProp; + vtkProperty* myBallPreselectProp; SMESH_DeviceActor* myHighlitableActor; eControl myControlMode; SMESH::Controls::FunctorPtr myFunctor; vtkProperty* my2DExtProp; + vtkProperty* my3DExtProp; SMESH_CellLabelActor* my2DActor; SMESH_DeviceActor* my2DExtActor; SMESH_CellLabelActor* my3DActor; @@ -292,6 +304,7 @@ class SMESH_ActorDef : public SMESH_Actor bool myIsFacesOriented; int myDeltaBrightness; + int myDeltaVBrightness; VTK::MarkerTexture myMarkerTexture; diff --git a/src/OBJECT/SMESH_DeviceActor.cxx b/src/OBJECT/SMESH_DeviceActor.cxx index 7a88f701b..d53765d79 100644 --- a/src/OBJECT/SMESH_DeviceActor.cxx +++ b/src/OBJECT/SMESH_DeviceActor.cxx @@ -642,16 +642,16 @@ SMESH_DeviceActor void SMESH_DeviceActor -::SetFacesOrientationColor(vtkFloatingPointType theColor[3]) +::SetFacesOrientationColor(vtkFloatingPointType r,vtkFloatingPointType g,vtkFloatingPointType b) { - myFaceOrientation->GetProperty()->SetColor( theColor ); + myFaceOrientation->GetProperty()->SetColor( r, g, b ); } void SMESH_DeviceActor -::GetFacesOrientationColor(vtkFloatingPointType theColor[3]) +::GetFacesOrientationColor(vtkFloatingPointType& r,vtkFloatingPointType& g,vtkFloatingPointType& b) { - myFaceOrientation->GetProperty()->GetColor( theColor ); + myFaceOrientation->GetProperty()->GetColor( r, g, b ); } void diff --git a/src/OBJECT/SMESH_DeviceActor.h b/src/OBJECT/SMESH_DeviceActor.h index 8c3abb7ae..554af35d9 100644 --- a/src/OBJECT/SMESH_DeviceActor.h +++ b/src/OBJECT/SMESH_DeviceActor.h @@ -79,8 +79,8 @@ class SMESHOBJECT_EXPORT SMESH_DeviceActor: public vtkLODActor{ virtual void SetFacesOriented(bool theIsFacesOriented); virtual bool GetFacesOriented() { return myIsFacesOriented; } - virtual void SetFacesOrientationColor(vtkFloatingPointType theColor[3]); - virtual void GetFacesOrientationColor(vtkFloatingPointType theColor[3]); + virtual void SetFacesOrientationColor(vtkFloatingPointType r,vtkFloatingPointType g,vtkFloatingPointType b); + virtual void GetFacesOrientationColor(vtkFloatingPointType& r,vtkFloatingPointType& g,vtkFloatingPointType& b); virtual void SetFacesOrientationScale(vtkFloatingPointType theScale); virtual vtkFloatingPointType GetFacesOrientationScale(); diff --git a/src/OBJECT/SMESH_Object.cxx b/src/OBJECT/SMESH_Object.cxx index e137a1c6d..30bef0579 100644 --- a/src/OBJECT/SMESH_Object.cxx +++ b/src/OBJECT/SMESH_Object.cxx @@ -82,14 +82,14 @@ static int MYDEBUGWITHFILES = 0; // purpose : Get type of VTK cell //================================================================================= static inline vtkIdType getCellType( const SMDSAbs_ElementType theType, - const bool thePoly, - const int theNbNodes ) + const bool thePoly, + const int theNbNodes ) { switch( theType ) { case SMDSAbs_0DElement: return VTK_VERTEX; - case SMDSAbs_Ball: return VTK_POLY_VERTEX; + case SMDSAbs_Ball: return VTK_POLY_VERTEX; case SMDSAbs_Edge: if( theNbNodes == 2 ) return VTK_LINE; @@ -345,16 +345,21 @@ void SMESH_VisualObjDef::buildElemPrs() // Calculate cells size - static SMDSAbs_ElementType aTypes[ 5 ] = - { SMDSAbs_Ball, SMDSAbs_0DElement, SMDSAbs_Edge, SMDSAbs_Face, SMDSAbs_Volume }; + const int nbTypes = 5; + static SMDSAbs_ElementType aTypes[ nbTypes ] = + { SMDSAbs_Edge, SMDSAbs_Face, SMDSAbs_Volume, SMDSAbs_Ball, SMDSAbs_0DElement }; // get entity data map nbEnts; map anEnts; - for ( int i = 0; i <= 3; i++ ) - nbEnts[ aTypes[ i ] ] = GetEntities( aTypes[ i ], anEnts[ aTypes[ i ] ] ); + vtkIdType aNbCells = 0; + for ( int i = 0; i < nbTypes; i++ ) + { + nbEnts[ aTypes[ i ] ] = GetEntities( aTypes[ i ], anEnts[ aTypes[ i ] ] ); + aNbCells += nbEnts[ aTypes [ i ]]; + } // PAL16631: without swap, bad_alloc is not thrown but hung up and crash instead, // so check remaining memory size for safety SMDS_Mesh::CheckMemory(); // PAL16631 @@ -362,7 +367,7 @@ void SMESH_VisualObjDef::buildElemPrs() vtkIdType aCellsSize = 2 * nbEnts[ SMDSAbs_0DElement ] + 3 * nbEnts[ SMDSAbs_Edge ]; aCellsSize += 2 * nbEnts[ SMDSAbs_Ball ]; - for ( int i = 2; i <= 3; i++ ) // iterate through faces and volumes + for ( int i = 1; i <= 2; i++ ) // iterate through faces and volumes { if ( nbEnts[ aTypes[ i ] ] ) { @@ -388,11 +393,6 @@ void SMESH_VisualObjDef::buildElemPrs() } } } - - vtkIdType aNbCells = - nbEnts[ SMDSAbs_0DElement ] + nbEnts[ SMDSAbs_Ball ] + nbEnts[ SMDSAbs_Edge ] + - nbEnts[ SMDSAbs_Face ] + nbEnts[ SMDSAbs_Volume ]; - if ( MYDEBUG ) MESSAGE( "Update - aNbCells = "< +#include + + +#include +#include +#include +#include +#include +#include +#include + +vtkStandardNewMacro(SMESH_SVTKActor); + +/*! + Constructor +*/ +SMESH_SVTKActor::SMESH_SVTKActor(): + my0DGrid(vtkUnstructuredGrid::New()), + myBallGrid(vtkUnstructuredGrid::New()) +{ + my0DActor = SVTK_DeviceActor::New(); + myBallActor = SVTK_DeviceActor::New(); + + myBallActor->SetResolveCoincidentTopology(false); + myBallActor->SetCoincident3DAllowed(true); + myBallActor->PickableOff(); + my0DActor->SetResolveCoincidentTopology(false); + my0DActor->SetCoincident3DAllowed(true); + my0DActor->PickableOff(); + + my0DGrid->Allocate(); + myBallGrid->Allocate(); +} + +/*! + Constructor +*/ +SMESH_SVTKActor::~SMESH_SVTKActor() { + my0DActor->Delete(); + myBallActor->Delete(); + my0DGrid->Delete(); + myBallGrid->Delete(); +} + +/*! + Publishes the actor in all its internal devices +*/ +void SMESH_SVTKActor::AddToRender(vtkRenderer* theRenderer) { + Superclass::AddToRender(theRenderer); + float a0D = my0DActor->GetProperty()->GetPointSize(); + float aBall = myBallActor->GetProperty()->GetPointSize(); + my0DActor->GetProperty()->DeepCopy(GetProperty()); + myBallActor->GetProperty()->DeepCopy(GetProperty()); + my0DActor->GetProperty()->SetPointSize(a0D); + myBallActor->GetProperty()->SetPointSize(aBall); + theRenderer->AddActor(my0DActor); + theRenderer->AddActor(myBallActor); + +} + +/*! + Removes the actor from all its internal devices +*/ +void +SMESH_SVTKActor +::RemoveFromRender(vtkRenderer* theRenderer) +{ + Superclass::RemoveFromRender(theRenderer); + theRenderer->RemoveActor( myBallActor ); + theRenderer->RemoveActor( my0DActor ); +} + +void +SMESH_SVTKActor +::MapCells(SALOME_Actor* theMapActor, + const TColStd_IndexedMapOfInteger& theMapIndex) +{ + myUnstructuredGrid->Initialize(); + myUnstructuredGrid->Allocate(); + + my0DGrid->Initialize(); + my0DGrid->Allocate(); + + myBallGrid->Initialize(); + myBallGrid->Allocate(); + + vtkDataSet *aSourceDataSet = theMapActor->GetInput(); + SVTK::CopyPoints( GetSource(), aSourceDataSet ); + SVTK::CopyPoints( myBallGrid, aSourceDataSet ); + SVTK::CopyPoints( my0DGrid, aSourceDataSet ); + + int aNbOfParts = theMapIndex.Extent(); + for(int ind = 1; ind <= aNbOfParts; ind++){ + int aPartId = theMapIndex( ind ); + if(vtkCell* aCell = theMapActor->GetElemCell(aPartId)) + { +#if VTK_XVERSION > 50700 + if (aCell->GetCellType() != VTK_POLYHEDRON) +#endif + if(aCell->GetCellType() == VTK_VERTEX ) { + my0DGrid->InsertNextCell(aCell->GetCellType(),aCell->GetPointIds()); + } else if(aCell->GetCellType() == VTK_POLY_VERTEX ) { + myBallGrid->InsertNextCell(aCell->GetCellType(),aCell->GetPointIds()); + } else { + myUnstructuredGrid->InsertNextCell(aCell->GetCellType(),aCell->GetPointIds()); + } +#if VTK_XVERSION > 50700 + else + { + vtkPolyhedron *polyhedron = dynamic_cast(aCell); + if (!polyhedron) + throw SALOME_Exception(LOCALIZED ("not a polyhedron")); + vtkIdType *pts = polyhedron->GetFaces(); + myUnstructuredGrid->InsertNextCell(aCell->GetCellType(),pts[0], pts+1); + } +#endif + } + + UnShrink(); + if(theMapActor->IsShrunk()){ + SetShrinkFactor(theMapActor->GetShrinkFactor()); + SetShrink(); + } + + myMapIndex = theMapIndex; + } +} + +void +SMESH_SVTKActor +::Initialize() +{ + Superclass::Initialize(); + my0DActor->SetInput(my0DGrid); + myBallActor->SetInput(myBallGrid); +} + + +void SMESH_SVTKActor::SetVisibility( int theVisibility ) { + Superclass::SetVisibility( theVisibility ); + my0DActor->SetVisibility( theVisibility ); + myBallActor->SetVisibility( theVisibility ); +} + + +void SMESH_SVTKActor::Set0DSize(float theSize) { + my0DActor->GetProperty()->SetPointSize(theSize); +} + +void SMESH_SVTKActor::SetBallSize(float theSize) { + myBallActor->GetProperty()->SetPointSize(theSize); +} + diff --git a/src/OBJECT/SMESH_SVTKActor.h b/src/OBJECT/SMESH_SVTKActor.h new file mode 100644 index 000000000..54b3ad305 --- /dev/null +++ b/src/OBJECT/SMESH_SVTKActor.h @@ -0,0 +1,82 @@ +// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// 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 +// + +// SMESH OBJECT : interactive object for SMESH visualization +// File : SMESH_SVTKActor.h +// Author : Roman NIKOLAEV +// Module : SMESH +// +#ifndef SMESH_SVTKACTOR_H +#define SMESH_SVTKACTOR_H + +#include "SMESH_Object.h" +#include + + +class SVTK_Actor; +class vtkUnstructureGrid; +class vtkDataSetMapper; + +class SMESHOBJECT_EXPORT SMESH_SVTKActor : public SVTK_Actor { + +public: + static SMESH_SVTKActor* New(); + + vtkTypeMacro(SMESH_SVTKActor, SVTK_Actor); + + void SetBallSize(float theSize); + void Set0DSize(float theSize); + + //! To publish the actor an all its internal devices + virtual + void + AddToRender(vtkRenderer* theRendere); + + virtual void SetVisibility( int theVisibility ); + + //! Initialiaze the instance completely + virtual void + Initialize(); + + //! Allow to recostruct selected cells from source SALOME_Actor and map of subindexes + virtual void + MapCells(SALOME_Actor* theMapActor, + const TColStd_IndexedMapOfInteger& theMapIndex); + + + //! To remove the actor an all its internal devices + virtual + void + RemoveFromRender(vtkRenderer* theRendere); + + protected: + SVTK_DeviceActor* my0DActor; + SVTK_DeviceActor* myBallActor; + + vtkUnstructuredGrid* my0DGrid; + vtkUnstructuredGrid* myBallGrid; + + SMESH_SVTKActor(); + virtual ~SMESH_SVTKActor(); +}; + +#endif diff --git a/src/SMDS/SMDS_Downward.hxx b/src/SMDS/SMDS_Downward.hxx index 56854fd1d..c4557b236 100644 --- a/src/SMDS/SMDS_Downward.hxx +++ b/src/SMDS/SMDS_Downward.hxx @@ -42,7 +42,7 @@ typedef struct int nbElems; } ListElemByNodesType; // TODO resize for polyhedrons -class DownIdType +class SMDS_EXPORT DownIdType { public: DownIdType(int a, unsigned char b) : @@ -64,7 +64,7 @@ struct DownIdCompare } }; -class SMDS_Downward +class SMDS_EXPORT SMDS_Downward { friend class SMDS_UnstructuredGrid; friend class SMDS_Down2D; @@ -109,7 +109,7 @@ protected: static std::vector _cellDimension; //!< conversion table: type --> dimension }; -class SMDS_Down1D: public SMDS_Downward +class SMDS_EXPORT SMDS_Down1D: public SMDS_Downward { friend class SMDS_UnstructuredGrid; public: @@ -140,7 +140,7 @@ protected: std::vector _upCellIndex; //!< compacted storage after connectivity calculation }; -class SMDS_Down2D: public SMDS_Downward +class SMDS_EXPORT SMDS_Down2D: public SMDS_Downward { friend class SMDS_UnstructuredGrid; friend class SMDS_Down1D; @@ -171,7 +171,7 @@ protected: int _nbNodes; //!< number of nodes in a face }; -class SMDS_Down3D: public SMDS_Downward +class SMDS_EXPORT SMDS_Down3D: public SMDS_Downward { friend class SMDS_UnstructuredGrid; public: @@ -188,7 +188,7 @@ protected: int FindFaceByNodes(int cellId, ElemByNodesType& faceByNodes); }; -class SMDS_DownEdge: public SMDS_Down1D +class SMDS_EXPORT SMDS_DownEdge: public SMDS_Down1D { friend class SMDS_UnstructuredGrid; public: @@ -197,7 +197,7 @@ protected: ~SMDS_DownEdge(); }; -class SMDS_DownQuadEdge: public SMDS_Down1D +class SMDS_EXPORT SMDS_DownQuadEdge: public SMDS_Down1D { friend class SMDS_UnstructuredGrid; public: @@ -206,7 +206,7 @@ protected: ~SMDS_DownQuadEdge(); }; -class SMDS_DownTriangle: public SMDS_Down2D +class SMDS_EXPORT SMDS_DownTriangle: public SMDS_Down2D { friend class SMDS_UnstructuredGrid; public: @@ -217,7 +217,7 @@ protected: virtual void addDownCell(int cellId, int lowCellId, unsigned char aType); //!< Id's are downward connectivity id's }; -class SMDS_DownQuadTriangle: public SMDS_Down2D +class SMDS_EXPORT SMDS_DownQuadTriangle: public SMDS_Down2D { friend class SMDS_UnstructuredGrid; public: @@ -228,7 +228,7 @@ protected: virtual void addDownCell(int cellId, int lowCellId, unsigned char aType); //!< Id's are downward connectivity id's }; -class SMDS_DownQuadrangle: public SMDS_Down2D +class SMDS_EXPORT SMDS_DownQuadrangle: public SMDS_Down2D { friend class SMDS_UnstructuredGrid; public: @@ -239,7 +239,7 @@ protected: virtual void addDownCell(int cellId, int lowCellId, unsigned char aType); //!< Id's are downward connectivity id's }; -class SMDS_DownQuadQuadrangle: public SMDS_Down2D +class SMDS_EXPORT SMDS_DownQuadQuadrangle: public SMDS_Down2D { friend class SMDS_UnstructuredGrid; public: @@ -266,7 +266,7 @@ protected: //protected: //}; -class SMDS_DownTetra: public SMDS_Down3D +class SMDS_EXPORT SMDS_DownTetra: public SMDS_Down3D { friend class SMDS_UnstructuredGrid; public: @@ -278,7 +278,7 @@ protected: virtual void computeFacesWithNodes(int cellId, ListElemByNodesType& facesWithNodes); }; -class SMDS_DownQuadTetra: public SMDS_Down3D +class SMDS_EXPORT SMDS_DownQuadTetra: public SMDS_Down3D { friend class SMDS_UnstructuredGrid; public: @@ -290,7 +290,7 @@ protected: virtual void computeFacesWithNodes(int cellId, ListElemByNodesType& facesWithNodes); }; -class SMDS_DownPyramid: public SMDS_Down3D +class SMDS_EXPORT SMDS_DownPyramid: public SMDS_Down3D { friend class SMDS_UnstructuredGrid; public: @@ -302,7 +302,7 @@ protected: virtual void computeFacesWithNodes(int cellId, ListElemByNodesType& facesWithNodes); }; -class SMDS_DownQuadPyramid: public SMDS_Down3D +class SMDS_EXPORT SMDS_DownQuadPyramid: public SMDS_Down3D { friend class SMDS_UnstructuredGrid; public: @@ -314,7 +314,7 @@ protected: virtual void computeFacesWithNodes(int cellId, ListElemByNodesType& facesWithNodes); }; -class SMDS_DownPenta: public SMDS_Down3D +class SMDS_EXPORT SMDS_DownPenta: public SMDS_Down3D { friend class SMDS_UnstructuredGrid; public: @@ -326,7 +326,7 @@ protected: virtual void computeFacesWithNodes(int cellId, ListElemByNodesType& facesWithNodes); }; -class SMDS_DownQuadPenta: public SMDS_Down3D +class SMDS_EXPORT SMDS_DownQuadPenta: public SMDS_Down3D { friend class SMDS_UnstructuredGrid; public: @@ -338,7 +338,7 @@ protected: virtual void computeFacesWithNodes(int cellId, ListElemByNodesType& facesWithNodes); }; -class SMDS_DownHexa: public SMDS_Down3D +class SMDS_EXPORT SMDS_DownHexa: public SMDS_Down3D { friend class SMDS_UnstructuredGrid; public: @@ -350,7 +350,7 @@ protected: virtual void computeFacesWithNodes(int cellId, ListElemByNodesType& facesWithNodes); }; -class SMDS_DownQuadHexa: public SMDS_Down3D +class SMDS_EXPORT SMDS_DownQuadHexa: public SMDS_Down3D { friend class SMDS_UnstructuredGrid; public: diff --git a/src/SMDS/SMDS_MeshNode.hxx b/src/SMDS/SMDS_MeshNode.hxx index 78966bc57..1f6712a74 100644 --- a/src/SMDS/SMDS_MeshNode.hxx +++ b/src/SMDS/SMDS_MeshNode.hxx @@ -45,7 +45,7 @@ public: double X() const; // ! NOT thread safe methods ! double Y() const; double Z() const; - void GetXYZ(double xyx[3]) const; // thread safe getting coords + void GetXYZ(double xyz[3]) const; // thread safe getting coords SMDS_ElemIteratorPtr GetInverseElementIterator(SMDSAbs_ElementType type=SMDSAbs_All) const; int NbInverseElements(SMDSAbs_ElementType type=SMDSAbs_All) const; const SMDS_PositionPtr& GetPosition() const; diff --git a/src/SMDS/SMDS_UnstructuredGrid.cxx b/src/SMDS/SMDS_UnstructuredGrid.cxx index 0d9b1e6c3..1eb5c445d 100644 --- a/src/SMDS/SMDS_UnstructuredGrid.cxx +++ b/src/SMDS/SMDS_UnstructuredGrid.cxx @@ -763,7 +763,7 @@ void SMDS_UnstructuredGrid::BuildDownwardConnectivity(bool withEdges) * @param vtkId the vtk id of the cell * @return number of neighbors */ -int SMDS_UnstructuredGrid::GetNeighbors(int* neighborsVtkIds, int* downIds, unsigned char* downTypes, int vtkId) +int SMDS_UnstructuredGrid::GetNeighbors(int* neighborsVtkIds, int* downIds, unsigned char* downTypes, int vtkId, bool getSkin) { int vtkType = this->GetCellType(vtkId); int cellDim = SMDS_Downward::getCellDimension(vtkType); @@ -798,9 +798,27 @@ int SMDS_UnstructuredGrid::GetNeighbors(int* neighborsVtkIds, int* downIds, unsi downIds[nb] = downId; downTypes[nb] = cellType; nb++; + if (nb >= NBMAXNEIGHBORS) + { + INFOS("SMDS_UnstructuredGrid::GetNeighbors problem: NBMAXNEIGHBORS=" <getVtkCellId(downId); // OK if skin present + downIds[nb] = downId; + downTypes[nb] = cellType; + nb++; + if (nb >= NBMAXNEIGHBORS) + { + INFOS("SMDS_UnstructuredGrid::GetNeighbors problem: NBMAXNEIGHBORS=" <= NBMAXNEIGHBORS) - assert(0); } return nb; } diff --git a/src/SMDS/SMDS_UnstructuredGrid.hxx b/src/SMDS/SMDS_UnstructuredGrid.hxx index 4c1cc7b80..774c54e27 100644 --- a/src/SMDS/SMDS_UnstructuredGrid.hxx +++ b/src/SMDS/SMDS_UnstructuredGrid.hxx @@ -83,7 +83,7 @@ public: void setCellIdToDownId(int vtkCellId, int downId); void CleanDownwardConnectivity(); void BuildDownwardConnectivity(bool withEdges); - int GetNeighbors(int* neighborsVtkIds, int* downIds, unsigned char* downTypes, int vtkId); + int GetNeighbors(int* neighborsVtkIds, int* downIds, unsigned char* downTypes, int vtkId, bool getSkin=false); int GetParentVolumes(int* volVtkIds, int vtkId); int GetParentVolumes(int* volVtkIds, int downId, unsigned char downType); void GetNodeIds(std::set& nodeSet, int downId, unsigned char downType); diff --git a/src/SMDS/SMDS_VolumeTool.cxx b/src/SMDS/SMDS_VolumeTool.cxx index 841d23540..2c7c401cb 100644 --- a/src/SMDS/SMDS_VolumeTool.cxx +++ b/src/SMDS/SMDS_VolumeTool.cxx @@ -1452,6 +1452,45 @@ double SMDS_VolumeTool::MinLinearSize2() const return minSize; } +//================================================================================ +/*! + * \brief Return maximal square distance between connected corner nodes + */ +//================================================================================ + +double SMDS_VolumeTool::MaxLinearSize2() const +{ + double maxSize = -1e+100; + int iQ = myVolume->IsQuadratic() ? 2 : 1; + + // store current face data + int curFace = myCurFace, nbN = myFaceNbNodes; + int* ind = myFaceNodeIndices; + myFaceNodeIndices = NULL; + const SMDS_MeshNode** nodes = myFaceNodes; + myFaceNodes = NULL; + + // it seems that compute distance twice is faster than organization of a sole computing + myCurFace = -1; + for ( int iF = 0; iF < myNbFaces; ++iF ) + { + setFace( iF ); + for ( int iN = 0; iN < myFaceNbNodes; iN += iQ ) + { + XYZ n1( myFaceNodes[ iN ]); + XYZ n2( myFaceNodes[(iN + iQ) % myFaceNbNodes]); + maxSize = std::max( maxSize, (n1 - n2).SquareMagnitude()); + } + } + // restore current face data + myCurFace = curFace; + myFaceNbNodes = nbN; + myFaceNodeIndices = ind; + delete [] myFaceNodes; myFaceNodes = nodes; + + return maxSize; +} + //================================================================================ /*! * \brief check that only one volume is build on the face nodes diff --git a/src/SMDS/SMDS_VolumeTool.hxx b/src/SMDS/SMDS_VolumeTool.hxx index 5c22c3eda..ff067eb3a 100644 --- a/src/SMDS/SMDS_VolumeTool.hxx +++ b/src/SMDS/SMDS_VolumeTool.hxx @@ -128,6 +128,9 @@ class SMDS_EXPORT SMDS_VolumeTool double MinLinearSize2() const; // Return minimal square distance between connected corner nodes + double MaxLinearSize2() const; + // Return maximal square distance between connected corner nodes + // ------------- // info on faces // ------------- diff --git a/src/SMESH/Makefile.am b/src/SMESH/Makefile.am index 3008e024f..72cc31ce1 100644 --- a/src/SMESH/Makefile.am +++ b/src/SMESH/Makefile.am @@ -34,10 +34,6 @@ salomeinclude_HEADERS = \ SMESH_Hypothesis.hxx \ SMESH_HypoFilter.hxx \ SMESH_Algo.hxx \ - SMESH_0D_Algo.hxx \ - SMESH_1D_Algo.hxx \ - SMESH_2D_Algo.hxx \ - SMESH_3D_Algo.hxx \ SMESH_Group.hxx \ SMESH_MeshEditor.hxx \ SMESH_Pattern.hxx \ @@ -56,10 +52,6 @@ dist_libSMESHimpl_la_SOURCES = \ SMESH_subMesh.cxx \ SMESH_Hypothesis.cxx \ SMESH_Algo.cxx \ - SMESH_0D_Algo.cxx \ - SMESH_1D_Algo.cxx \ - SMESH_2D_Algo.cxx \ - SMESH_3D_Algo.cxx \ SMESH_Group.cxx \ SMESH_MeshEditor.cxx \ SMESH_Pattern.cxx \ @@ -83,6 +75,7 @@ libSMESHimpl_la_CPPFLAGS = \ -I$(srcdir)/../DriverUNV \ -I$(srcdir)/../DriverSTL \ -I$(srcdir)/../DriverCGNS \ + -I$(srcdir)/../DriverGMF \ -I$(srcdir)/../SMDS \ -I$(srcdir)/../SMESHDS \ -I$(srcdir)/../SMESHUtils @@ -98,8 +91,9 @@ libSMESHimpl_la_LDFLAGS = \ ../DriverSTL/libMeshDriverSTL.la \ ../DriverMED/libMeshDriverMED.la \ ../DriverUNV/libMeshDriverUNV.la \ + ../DriverGMF/libMeshDriverGMF.la \ $(DriverCGNS_LIB) \ ../SMESHUtils/libSMESHUtils.la \ $(BOOST_LIB_THREAD) \ $(GEOM_LDFLAGS) -lNMTTools \ - $(CAS_LDPATH) -lTKShHealing -lTKPrim -lTKG2d + $(CAS_LDPATH) -lTKShHealing -lTKPrim -lTKG2d -lTKCDF diff --git a/src/SMESH/SMESH_0D_Algo.cxx b/src/SMESH/SMESH_0D_Algo.cxx deleted file mode 100644 index bc3461d10..000000000 --- a/src/SMESH/SMESH_0D_Algo.cxx +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE -// -// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, -// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License. -// -// 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 -// - -// SMESH SMESH : implementaion of SMESH idl descriptions -// File : SMESH_0D_Algo.cxx -// Module : SMESH -// $Header$ -// -#include "SMESH_0D_Algo.hxx" -#include "SMESH_Gen.hxx" - -//============================================================================= -/*! - * - */ -//============================================================================= - -SMESH_0D_Algo::SMESH_0D_Algo(int hypId, int studyId, SMESH_Gen* gen) - : SMESH_Algo(hypId, studyId, gen) -{ - _type = ALGO_0D; - gen->_map0D_Algo[hypId] = this; -} - -//============================================================================= -/*! - * - */ -//============================================================================= - -SMESH_0D_Algo::~SMESH_0D_Algo() -{ -} - diff --git a/src/SMESH/SMESH_1D_Algo.cxx b/src/SMESH/SMESH_1D_Algo.cxx deleted file mode 100644 index 3027f82f4..000000000 --- a/src/SMESH/SMESH_1D_Algo.cxx +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE -// -// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, -// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License. -// -// 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 -// - -// SMESH SMESH : implementaion of SMESH idl descriptions -// File : SMESH_1D_Algo.cxx -// Author : Paul RASCLE, EDF -// Module : SMESH -// $Header$ -// -#include "SMESH_1D_Algo.hxx" -#include "SMESH_Gen.hxx" -#include "SMESH_subMesh.hxx" - -using namespace std; - -//============================================================================= -/*! - * - */ -//============================================================================= - -SMESH_1D_Algo::SMESH_1D_Algo(int hypId, int studyId, SMESH_Gen* gen) - : SMESH_Algo(hypId, studyId, gen) -{ -// _compatibleHypothesis.push_back("hypothese_1D_bidon"); - _type = ALGO_1D; - gen->_map1D_Algo[hypId] = this; -} - -//============================================================================= -/*! - * - */ -//============================================================================= - -SMESH_1D_Algo::~SMESH_1D_Algo() -{ -} - diff --git a/src/SMESH/SMESH_1D_Algo.hxx b/src/SMESH/SMESH_1D_Algo.hxx deleted file mode 100644 index e10aa197d..000000000 --- a/src/SMESH/SMESH_1D_Algo.hxx +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE -// -// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, -// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License. -// -// 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 -// - -// SMESH SMESH : implementaion of SMESH idl descriptions -// File : SMESH_1D_Algo.hxx -// Author : Paul RASCLE, EDF -// Module : SMESH -// $Header$ -// -#ifndef _SMESH_1D_ALGO_HXX_ -#define _SMESH_1D_ALGO_HXX_ - -#include "SMESH_SMESH.hxx" - -#include "SMESH_Algo.hxx" - -class SMESH_EXPORT SMESH_1D_Algo: - public SMESH_Algo -{ -public: - SMESH_1D_Algo(int hypId, int studyId, SMESH_Gen* gen); - virtual ~SMESH_1D_Algo(); -}; - -#endif diff --git a/src/SMESH/SMESH_2D_Algo.cxx b/src/SMESH/SMESH_2D_Algo.cxx deleted file mode 100644 index a4feece7b..000000000 --- a/src/SMESH/SMESH_2D_Algo.cxx +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE -// -// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, -// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License. -// -// 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 -// - -// SMESH SMESH : implementaion of SMESH idl descriptions -// File : SMESH_2D_Algo.cxx -// Author : Paul RASCLE, EDF -// Module : SMESH -// $Header$ -// -#include "SMESH_2D_Algo.hxx" -#include "SMESH_Gen.hxx" - -#include "utilities.h" - -#include -#include -#include - -using namespace std; - -//============================================================================= -/*! - * - */ -//============================================================================= - -SMESH_2D_Algo::SMESH_2D_Algo(int hypId, int studyId, SMESH_Gen* gen) - : SMESH_Algo(hypId, studyId, gen) -{ -// _compatibleHypothesis.push_back("hypothese_2D_bidon"); - _type = ALGO_2D; - gen->_map2D_Algo[hypId] = this; -} - -//============================================================================= -/*! - * - */ -//============================================================================= - -SMESH_2D_Algo::~SMESH_2D_Algo() -{ -} - -//============================================================================= -/*! - * - */ -//============================================================================= - -int SMESH_2D_Algo::NumberOfWires(const TopoDS_Shape& S) -{ - int i = 0; - for (TopExp_Explorer exp(S,TopAbs_WIRE); exp.More(); exp.Next()) - i++; - return i; -} - -//============================================================================= -/*! - * - */ -//============================================================================= - -int SMESH_2D_Algo::NumberOfPoints(SMESH_Mesh& aMesh, const TopoDS_Wire& W) -{ - int nbPoints = 0; - for (TopExp_Explorer exp(W,TopAbs_EDGE); exp.More(); exp.Next()) { - const TopoDS_Edge& E = TopoDS::Edge(exp.Current()); - int nb = aMesh.GetSubMesh(E)->GetSubMeshDS()->NbNodes(); - if(_quadraticMesh) - nb = nb/2; - nbPoints += nb + 1; // internal points plus 1 vertex of 2 (last point ?) - } - return nbPoints; -} - - diff --git a/src/SMESH/SMESH_3D_Algo.cxx b/src/SMESH/SMESH_3D_Algo.cxx deleted file mode 100644 index d7a0ed88d..000000000 --- a/src/SMESH/SMESH_3D_Algo.cxx +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE -// -// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, -// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License. -// -// 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 -// - -// SMESH SMESH : implementaion of SMESH idl descriptions -// File : SMESH_3D_Algo.cxx -// Author : Paul RASCLE, EDF -// Module : SMESH -// $Header$ -// -#include "SMESH_3D_Algo.hxx" -#include "SMESH_Gen.hxx" - -#include "utilities.h" - -using namespace std; - -//============================================================================= -/*! - * - */ -//============================================================================= - -SMESH_3D_Algo::SMESH_3D_Algo(int hypId, int studyId, SMESH_Gen* gen) - : SMESH_Algo(hypId, studyId, gen) -{ -// _compatibleHypothesis.push_back("hypothese_3D_bidon"); - _type = ALGO_3D; - gen->_map3D_Algo[hypId] = this; -} - -//============================================================================= -/*! - * - */ -//============================================================================= - -SMESH_3D_Algo::~SMESH_3D_Algo() -{ -} - - diff --git a/src/SMESH/SMESH_Algo.cxx b/src/SMESH/SMESH_Algo.cxx index 9768eb049..f7bd7f9bf 100644 --- a/src/SMESH/SMESH_Algo.cxx +++ b/src/SMESH/SMESH_Algo.cxx @@ -39,6 +39,7 @@ #include "SMESH_HypoFilter.hxx" #include "SMESH_Mesh.hxx" #include "SMESH_TypeDefs.hxx" +#include "SMESH_subMesh.hxx" #include @@ -49,6 +50,7 @@ #include #include #include +#include #include #include #include @@ -56,6 +58,7 @@ #include #include #include +#include #include #include #include @@ -96,6 +99,41 @@ SMESH_Algo::~SMESH_Algo() { } +//============================================================================= +/*! + * + */ +//============================================================================= + +SMESH_0D_Algo::SMESH_0D_Algo(int hypId, int studyId, SMESH_Gen* gen) + : SMESH_Algo(hypId, studyId, gen) +{ + _shapeType = (1 << TopAbs_VERTEX); + _type = ALGO_0D; + gen->_map0D_Algo[hypId] = this; +} +SMESH_1D_Algo::SMESH_1D_Algo(int hypId, int studyId, SMESH_Gen* gen) + : SMESH_Algo(hypId, studyId, gen) +{ + _shapeType = (1 << TopAbs_EDGE); + _type = ALGO_1D; + gen->_map1D_Algo[hypId] = this; +} +SMESH_2D_Algo::SMESH_2D_Algo(int hypId, int studyId, SMESH_Gen* gen) + : SMESH_Algo(hypId, studyId, gen) +{ + _shapeType = (1 << TopAbs_FACE); + _type = ALGO_2D; + gen->_map2D_Algo[hypId] = this; +} +SMESH_3D_Algo::SMESH_3D_Algo(int hypId, int studyId, SMESH_Gen* gen) + : SMESH_Algo(hypId, studyId, gen) +{ + _shapeType = (1 << TopAbs_SOLID); + _type = ALGO_3D; + gen->_map3D_Algo[hypId] = this; +} + //============================================================================= /*! * Usually an algoritm has nothing to save @@ -309,7 +347,14 @@ bool SMESH_Algo::IsReversedSubMesh (const TopoDS_Face& theFace, // face normal at node position TopLoc_Location loc; Handle(Geom_Surface) surf = BRep_Tool::Surface( theFace, loc ); - if ( surf.IsNull() || surf->Continuity() < GeomAbs_C1 ) return isReversed; + // if ( surf.IsNull() || surf->Continuity() < GeomAbs_C1 ) + // some surfaces not detected as GeomAbs_C1 are nevertheless correct for meshing + if ( surf.IsNull() || surf->Continuity() < GeomAbs_C0 ) + { + if (!surf.IsNull()) + MESSAGE("surf->Continuity() < GeomAbs_C1 " << (surf->Continuity() < GeomAbs_C1)); + return isReversed; + } gp_Vec d1u, d1v; surf->D1( u, v, nPnt[0], d1u, d1v ); gp_Vec Nf = (d1u ^ d1v).Transformed( loc ); @@ -777,3 +822,38 @@ void SMESH_Algo::addBadInputElement(const SMDS_MeshElement* elem) if ( elem ) _badInputElements.push_back( elem ); } + +//============================================================================= +/*! + * + */ +//============================================================================= + +int SMESH_Algo::NumberOfWires(const TopoDS_Shape& S) +{ + int i = 0; + for (TopExp_Explorer exp(S,TopAbs_WIRE); exp.More(); exp.Next()) + i++; + return i; +} + +//============================================================================= +/*! + * + */ +//============================================================================= + +int SMESH_Algo::NumberOfPoints(SMESH_Mesh& aMesh, const TopoDS_Wire& W) +{ + int nbPoints = 0; + for (TopExp_Explorer exp(W,TopAbs_EDGE); exp.More(); exp.Next()) { + const TopoDS_Edge& E = TopoDS::Edge(exp.Current()); + int nb = aMesh.GetSubMesh(E)->GetSubMeshDS()->NbNodes(); + if(_quadraticMesh) + nb = nb/2; + nbPoints += nb + 1; // internal points plus 1 vertex of 2 (last point ?) + } + return nbPoints; +} + + diff --git a/src/SMESH/SMESH_Algo.hxx b/src/SMESH/SMESH_Algo.hxx index 580445b48..1a3be0876 100644 --- a/src/SMESH/SMESH_Algo.hxx +++ b/src/SMESH/SMESH_Algo.hxx @@ -47,6 +47,7 @@ class SMESH_Gen; class SMESH_Mesh; class SMESH_HypoFilter; class TopoDS_Vertex; +class TopoDS_Wire; class TopoDS_Face; class TopoDS_Shape; class SMESHDS_Mesh; @@ -301,6 +302,9 @@ public: */ static bool FaceNormal(const SMDS_MeshElement* F, gp_XYZ& normal, bool normalized=true); + static int NumberOfWires(const TopoDS_Shape& S); + int NumberOfPoints(SMESH_Mesh& aMesh,const TopoDS_Wire& W); + /*! * \brief Return continuity of two edges * \param E1 - the 1st edge @@ -373,8 +377,8 @@ protected: bool _requireShape; // work with GetDim()-1 mesh bound to geom only. Default TRUE bool _supportSubmeshes; // if !_requireDiscreteBoundary. Default FALSE - // quadratic mesh creation required, - // is usually set trough SMESH_MesherHelper::IsQuadraticSubMesh() + // indicates if quadratic mesh creation is required, + // is usually set like this: _quadraticMesh = SMESH_MesherHelper::IsQuadraticSubMesh(shape) bool _quadraticMesh; int _error; //!< SMESH_ComputeErrorName or anything algo specific @@ -384,4 +388,28 @@ protected: volatile bool _computeCanceled; //!< is set to True while computing to stop it }; +class SMESH_EXPORT SMESH_0D_Algo: public SMESH_Algo +{ +public: + SMESH_0D_Algo(int hypId, int studyId, SMESH_Gen* gen); +}; + +class SMESH_EXPORT SMESH_1D_Algo: public SMESH_Algo +{ +public: + SMESH_1D_Algo(int hypId, int studyId, SMESH_Gen* gen); +}; + +class SMESH_EXPORT SMESH_2D_Algo: public SMESH_Algo +{ +public: + SMESH_2D_Algo(int hypId, int studyId, SMESH_Gen* gen); +}; + +class SMESH_EXPORT SMESH_3D_Algo: public SMESH_Algo +{ +public: + SMESH_3D_Algo(int hypId, int studyId, SMESH_Gen* gen); +}; + #endif diff --git a/src/SMESH/SMESH_Gen.cxx b/src/SMESH/SMESH_Gen.cxx index dae945eec..c18ace194 100644 --- a/src/SMESH/SMESH_Gen.cxx +++ b/src/SMESH/SMESH_Gen.cxx @@ -43,9 +43,14 @@ #include "Utils_ExceptHandlers.hxx" #include +#include #include "memoire.h" +#ifdef WNT + #include +#endif + using namespace std; //============================================================================= @@ -374,7 +379,9 @@ bool SMESH_Gen::Compute(SMESH_Mesh & aMesh, { SMESH_MesherHelper aHelper( aMesh ); if ( aHelper.IsQuadraticMesh() != SMESH_MesherHelper::LINEAR ) - aHelper.FixQuadraticElements(); + { + aHelper.FixQuadraticElements( sm->GetComputeError() ); + } } return ret; } @@ -645,7 +652,8 @@ static bool checkMissing(SMESH_Gen* aGen, set& aCheckedMap, list< SMESH_Gen::TAlgoStateError > & theErrors) { - if ( aSubMesh->GetSubShape().ShapeType() == TopAbs_VERTEX) + if ( aSubMesh->GetSubShape().ShapeType() == TopAbs_VERTEX || + aCheckedMap.count( aSubMesh )) return true; //MESSAGE("=====checkMissing"); @@ -701,8 +709,15 @@ static bool checkMissing(SMESH_Gen* aGen, break; } case SMESH_subMesh::HYP_OK: - algo = aGen->GetAlgo( aMesh, aSubMesh->GetSubShape() ); + algo = aSubMesh->GetAlgo(); ret = true; + if (!algo->NeedDiscreteBoundary()) + { + SMESH_subMeshIteratorPtr itsub = aSubMesh->getDependsOnIterator( /*includeSelf=*/false, + /*complexShapeFirst=*/false); + while ( itsub->more() ) + aCheckedMap.insert( itsub->next() ); + } break; default: ASSERT(0); } @@ -721,7 +736,6 @@ static bool checkMissing(SMESH_Gen* aGen, { // sub-meshes should not be checked further more SMESH_subMesh* sm = itsub->next(); - aCheckedMap.insert( sm ); if (isTopLocalAlgo) { @@ -735,6 +749,7 @@ static bool checkMissing(SMESH_Gen* aGen, checkNoAlgo2 = false; } } + aCheckedMap.insert( sm ); } } return ret; @@ -768,9 +783,9 @@ bool SMESH_Gen::GetAlgoState(SMESH_Mesh& theMesh, bool ret = true; bool hasAlgo = false; - SMESH_subMesh* sm = theMesh.GetSubMesh(theShape); + SMESH_subMesh* sm = theMesh.GetSubMesh(theShape); const SMESHDS_Mesh* meshDS = theMesh.GetMeshDS(); - TopoDS_Shape mainShape = meshDS->ShapeToMesh(); + TopoDS_Shape mainShape = meshDS->ShapeToMesh(); // ----------------- // get global algos @@ -896,6 +911,177 @@ bool SMESH_Gen::IsGlobalHypothesis(const SMESH_Hypothesis* theHyp, SMESH_Mesh& a return aMesh.GetHypothesis( aMesh.GetMeshDS()->ShapeToMesh(), filter, false ); } +//================================================================================ +/*! + * \brief Return paths to xml files of plugins + */ +//================================================================================ + +std::vector< std::string > SMESH_Gen::GetPluginXMLPaths() +{ + // Get paths to xml files of plugins + vector< string > xmlPaths; + string sep; + if ( const char* meshersList = getenv("SMESH_MeshersList") ) + { + string meshers = meshersList, plugin; + string::size_type from = 0, pos; + while ( from < meshers.size() ) + { + // cut off plugin name + pos = meshers.find( ':', from ); + if ( pos != string::npos ) + plugin = meshers.substr( from, pos-from ); + else + plugin = meshers.substr( from ), pos = meshers.size(); + from = pos + 1; + + // get PLUGIN_ROOT_DIR path + string rootDirVar, pluginSubDir = plugin; + if ( plugin == "StdMeshers" ) + rootDirVar = "SMESH", pluginSubDir = "smesh"; + else + for ( pos = 0; pos < plugin.size(); ++pos ) + rootDirVar += toupper( plugin[pos] ); + rootDirVar += "_ROOT_DIR"; + + const char* rootDir = getenv( rootDirVar.c_str() ); + if ( !rootDir || strlen(rootDir) == 0 ) + { + rootDirVar = plugin + "_ROOT_DIR"; // HexoticPLUGIN_ROOT_DIR + rootDir = getenv( rootDirVar.c_str() ); + if ( !rootDir || strlen(rootDir) == 0 ) continue; + } + + // get a separator from rootDir + for ( pos = strlen( rootDir )-1; pos >= 0 && sep.empty(); --pos ) + if ( rootDir[pos] == '/' || rootDir[pos] == '\\' ) + { + sep = rootDir[pos]; + break; + } +#ifdef WNT + if (sep.empty() ) sep = "\\"; +#else + if (sep.empty() ) sep = "/"; +#endif + + // get a path to resource file + string xmlPath = rootDir; + if ( xmlPath[ xmlPath.size()-1 ] != sep[0] ) + xmlPath += sep; + xmlPath += "share" + sep + "salome" + sep + "resources" + sep; + for ( pos = 0; pos < pluginSubDir.size(); ++pos ) + xmlPath += tolower( pluginSubDir[pos] ); + xmlPath += sep + plugin + ".xml"; + bool fileOK; +#ifdef WNT + fileOK = (GetFileAttributes(xmlPath.c_str()) != INVALID_FILE_ATTRIBUTES); +#else + fileOK = (access(xmlPath.c_str(), F_OK) == 0); +#endif + if ( fileOK ) + xmlPaths.push_back( xmlPath ); + } + } + + return xmlPaths; +} + +//======================================================================= +namespace // Access to type of input and output of an algorithm +//======================================================================= +{ + struct AlgoData + { + int _dim; + set _inElemTypes; // acceptable types of input mesh element + set _outElemTypes; // produced types of mesh elements + + bool IsCompatible( const AlgoData& algo2 ) const + { + if ( _dim > algo2._dim ) return algo2.IsCompatible( *this ); + // algo2 is of highter dimension + if ( _outElemTypes.empty() || algo2._inElemTypes.empty() ) + return false; + bool compatible = true; + set::const_iterator myOutType = _outElemTypes.begin(); + for ( ; myOutType != _outElemTypes.end() && compatible; ++myOutType ) + compatible = algo2._inElemTypes.count( *myOutType ); + return compatible; + } + }; + + //================================================================================ + /*! + * \brief Return AlgoData of the algorithm + */ + //================================================================================ + + const AlgoData& getAlgoData( const SMESH_Algo* algo ) + { + static map< string, AlgoData > theDataByName; + if ( theDataByName.empty() ) + { + // Read Plugin.xml files + vector< string > xmlPaths = SMESH_Gen::GetPluginXMLPaths(); + LDOMParser xmlParser; + for ( size_t iXML = 0; iXML < xmlPaths.size(); ++iXML ) + { + bool error = xmlParser.parse( xmlPaths[iXML].c_str() ); + if ( error ) + { + TCollection_AsciiString data; + INFOS( xmlParser.GetError(data) ); + continue; + } + // + // + LDOM_Document xmlDoc = xmlParser.getDocument(); + LDOM_NodeList algoNodeList = xmlDoc.getElementsByTagName( "algorithm" ); + for ( int i = 0; i < algoNodeList.getLength(); ++i ) + { + LDOM_Node algoNode = algoNodeList.item( i ); + LDOM_Element& algoElem = (LDOM_Element&) algoNode; + TCollection_AsciiString algoType = algoElem.getAttribute("type"); + TCollection_AsciiString input = algoElem.getAttribute("input"); + TCollection_AsciiString output = algoElem.getAttribute("output"); + TCollection_AsciiString dim = algoElem.getAttribute("dim"); + if ( algoType.IsEmpty() ) continue; + AlgoData & data = theDataByName[ algoType.ToCString() ]; + data._dim = dim.IntegerValue(); + for ( int isInput = 0; isInput < 2; ++isInput ) + { + TCollection_AsciiString& typeStr = isInput ? input : output; + set& typeSet = isInput ? data._inElemTypes : data._outElemTypes; + int beg = 1, end; + while ( beg <= typeStr.Length() ) + { + while ( beg < typeStr.Length() && !isalpha( typeStr.Value( beg ) )) + ++beg; + end = beg; + while ( end < typeStr.Length() && isalpha( typeStr.Value( end + 1 ) )) + ++end; + if ( end > beg ) + { + TCollection_AsciiString typeName = typeStr.SubString( beg, end ); + if ( typeName == "EDGE" ) typeSet.insert( SMDSGeom_EDGE ); + else if ( typeName == "TRIA" ) typeSet.insert( SMDSGeom_TRIANGLE ); + else if ( typeName == "QUAD" ) typeSet.insert( SMDSGeom_QUADRANGLE ); + } + beg = end + 1; + } + } + } + } + } + return theDataByName[ algo->GetName() ]; + } +} + //============================================================================= /*! * Finds algo to mesh a shape. Optionally returns a shape the found algo is bound to @@ -909,7 +1095,63 @@ SMESH_Algo *SMESH_Gen::GetAlgo(SMESH_Mesh & aMesh, SMESH_HypoFilter filter( SMESH_HypoFilter::IsAlgo() ); filter.And( filter.IsApplicableTo( aShape )); - return (SMESH_Algo*) aMesh.GetHypothesis( aShape, filter, true, assignedTo ); + TopoDS_Shape assignedToShape; + SMESH_Algo* algo = + (SMESH_Algo*) aMesh.GetHypothesis( aShape, filter, true, &assignedToShape ); + + if ( algo && + aShape.ShapeType() == TopAbs_FACE && + !aShape.IsSame( assignedToShape ) && + SMESH_MesherHelper::NbAncestors( aShape, aMesh, TopAbs_SOLID ) > 1 ) + { + // Issue 0021559. If there is another 2D algo with different types of output + // elements that can be used to mesh aShape, and 3D algos on adjacent SOLIDs + // have different types of input elements, we choose a most appropriate 2D algo. + + // try to find a concurrent 2D algo + filter.AndNot( filter.Is( algo )); + TopoDS_Shape assignedToShape2; + SMESH_Algo* algo2 = + (SMESH_Algo*) aMesh.GetHypothesis( aShape, filter, true, &assignedToShape2 ); + if ( algo2 && // algo found + !assignedToShape2.IsSame( aMesh.GetShapeToMesh() ) && // algo is local + ( SMESH_MesherHelper::GetGroupType( assignedToShape2 ) == // algo of the same level + SMESH_MesherHelper::GetGroupType( assignedToShape )) && + aMesh.IsOrderOK( aMesh.GetSubMesh( assignedToShape2 ), // no forced order + aMesh.GetSubMesh( assignedToShape ))) + { + // get algos on the adjacent SOLIDs + filter.Init( filter.IsAlgo() ).And( filter.HasDim( 3 )); + vector< SMESH_Algo* > algos3D; + PShapeIteratorPtr solidIt = SMESH_MesherHelper::GetAncestors( aShape, aMesh, + TopAbs_SOLID ); + while ( const TopoDS_Shape* solid = solidIt->next() ) + if ( SMESH_Algo* algo3D = (SMESH_Algo*) aMesh.GetHypothesis( *solid, filter, true )) + { + algos3D.push_back( algo3D ); + filter.AndNot( filter.HasName( algo3D->GetName() )); + } + // check compatibility of algos + if ( algos3D.size() > 1 ) + { + const AlgoData& algoData = getAlgoData( algo ); + const AlgoData& algoData2 = getAlgoData( algo2 ); + const AlgoData& algoData3d0 = getAlgoData( algos3D[0] ); + const AlgoData& algoData3d1 = getAlgoData( algos3D[1] ); + if (( algoData2.IsCompatible( algoData3d0 ) && + algoData2.IsCompatible( algoData3d1 )) + && + !(algoData.IsCompatible( algoData3d0 ) && + algoData.IsCompatible( algoData3d1 ))) + algo = algo2; + } + } + } + + if ( assignedTo && algo ) + * assignedTo = assignedToShape; + + return algo; } //============================================================================= diff --git a/src/SMESH/SMESH_Gen.hxx b/src/SMESH/SMESH_Gen.hxx index 353cba6df..b7854786f 100644 --- a/src/SMESH/SMESH_Gen.hxx +++ b/src/SMESH/SMESH_Gen.hxx @@ -35,10 +35,6 @@ #include "SMESH_Hypothesis.hxx" #include "SMESH_ComputeError.hxx" #include "SMESH_Algo.hxx" -#include "SMESH_0D_Algo.hxx" -#include "SMESH_1D_Algo.hxx" -#include "SMESH_2D_Algo.hxx" -#include "SMESH_3D_Algo.hxx" #include "SMESH_Mesh.hxx" #include "chrono.hxx" @@ -47,6 +43,8 @@ #include #include +#include +#include class SMESHDS_Document; @@ -144,9 +142,13 @@ public: static int GetShapeDim(const TopAbs_ShapeEnum & aShapeType); static int GetShapeDim(const TopoDS_Shape & aShape) { return GetShapeDim( aShape.ShapeType() ); } + SMESH_Algo* GetAlgo(SMESH_Mesh & aMesh, const TopoDS_Shape & aShape, TopoDS_Shape* assignedTo=0); + static bool IsGlobalHypothesis(const SMESH_Hypothesis* theHyp, SMESH_Mesh& aMesh); + static std::vector< std::string > GetPluginXMLPaths(); + int GetANewId(); std::map < int, SMESH_Algo * >_mapAlgo; diff --git a/src/SMESH/SMESH_Group.cxx b/src/SMESH/SMESH_Group.cxx index 7ef568593..dae4e3188 100644 --- a/src/SMESH/SMESH_Group.cxx +++ b/src/SMESH/SMESH_Group.cxx @@ -24,7 +24,6 @@ // File : SMESH_Group.cxx // Author : Michael Sazonov (OCC) // Module : SMESH -// $Header$ // #include "SMESH_Group.hxx" #include "SMESH_Mesh.hxx" @@ -60,6 +59,7 @@ SMESH_Group::SMESH_Group (int theID, myGroupDS = new SMESHDS_Group (theID, const_cast(theMesh)->GetMeshDS(), theType); + myGroupDS->SetStoreName( theName ); } //================================================================================ @@ -76,7 +76,7 @@ SMESH_Group::SMESH_Group (SMESHDS_GroupBase* groupDS): myGroupDS( groupDS ) //============================================================================= /*! - * + * Destructor deletes myGroupDS */ //============================================================================= @@ -84,3 +84,15 @@ SMESH_Group::~SMESH_Group () { delete myGroupDS; myGroupDS=0; } + +//================================================================================ +/*! + * \brief Sets a new name + */ +//================================================================================ + +void SMESH_Group::SetName (const char* theName) +{ + myName = theName; + myGroupDS->SetStoreName( theName ); +} diff --git a/src/SMESH/SMESH_Group.hxx b/src/SMESH/SMESH_Group.hxx index f378be296..edb14b900 100644 --- a/src/SMESH/SMESH_Group.hxx +++ b/src/SMESH/SMESH_Group.hxx @@ -52,7 +52,7 @@ class SMESH_EXPORT SMESH_Group SMESH_Group (SMESHDS_GroupBase* groupDS); ~SMESH_Group (); - void SetName (const char* theName) { myName = theName; } + void SetName (const char* theName); const char* GetName () const { return myName.c_str(); } diff --git a/src/SMESH/SMESH_Hypothesis.cxx b/src/SMESH/SMESH_Hypothesis.cxx index fee310f27..48f293a56 100644 --- a/src/SMESH/SMESH_Hypothesis.cxx +++ b/src/SMESH/SMESH_Hypothesis.cxx @@ -43,7 +43,6 @@ SMESH_Hypothesis::SMESH_Hypothesis(int hypId, int studyId, SMESH_Gen* gen) : SMESHDS_Hypothesis(hypId) { - //MESSAGE("SMESH_Hypothesis::SMESH_Hypothesis"); _gen = gen; _studyId = studyId; StudyContextStruct* myStudyContext = _gen->GetStudyContext(_studyId); @@ -51,9 +50,8 @@ SMESH_Hypothesis::SMESH_Hypothesis(int hypId, _type = PARAM_ALGO; _shapeType = 0; // to be set by algo with TopAbs_Enum _param_algo_dim = -1; // to be set by algo parameter - _parameters = string(); - _lastParameters = string(); - _libName = string(); + //_parameters = string(); + //_lastParameters = string(); } //============================================================================= @@ -65,6 +63,8 @@ SMESH_Hypothesis::SMESH_Hypothesis(int hypId, SMESH_Hypothesis::~SMESH_Hypothesis() { MESSAGE("SMESH_Hypothesis::~SMESH_Hypothesis"); + StudyContextStruct* myStudyContext = _gen->GetStudyContext(_studyId); + myStudyContext->mapHypothesis[_hypId] = 0; } //============================================================================= @@ -177,53 +177,53 @@ SMESH_Mesh* SMESH_Hypothesis::GetMeshByPersistentID(int id) * */ //============================================================================= -void SMESH_Hypothesis::SetParameters(const char *theParameters) -{ - string aNewParameters(theParameters); - if(aNewParameters.size()==0 && _parameters.size()==0) - aNewParameters = " "; - if(_parameters.size()>0) - _parameters +="|"; - _parameters +=aNewParameters; - SetLastParameters(theParameters); -} - -//============================================================================= -/*! - * - */ -//============================================================================= -void SMESH_Hypothesis::ClearParameters() -{ - _parameters = string(); -} - -//============================================================================= -/*! - * - */ -//============================================================================= -char* SMESH_Hypothesis::GetParameters() const -{ - return (char*)_parameters.c_str(); -} - -//============================================================================= -/*! - * - */ -//============================================================================= -char* SMESH_Hypothesis::GetLastParameters() const -{ - return (char*)_lastParameters.c_str(); -} - -//============================================================================= -/*! - * - */ -//============================================================================= -void SMESH_Hypothesis::SetLastParameters(const char* theParameters) -{ - _lastParameters = string(theParameters); -} +// void SMESH_Hypothesis::SetParameters(const char *theParameters) +// { +// string aNewParameters(theParameters); +// if(aNewParameters.size()==0 && _parameters.size()==0) +// aNewParameters = " "; +// if(_parameters.size()>0) +// _parameters +="|"; +// _parameters +=aNewParameters; +// SetLastParameters(theParameters); +// } + +// //============================================================================= +// /*! +// * +// */ +// //============================================================================= +// void SMESH_Hypothesis::ClearParameters() +// { +// _parameters = string(); +// } + +// //============================================================================= +// /*! +// * +// */ +// //============================================================================= +// char* SMESH_Hypothesis::GetParameters() const +// { +// return (char*)_parameters.c_str(); +// } + +// //============================================================================= +// /*! +// * +// */ +// //============================================================================= +// char* SMESH_Hypothesis::GetLastParameters() const +// { +// return (char*)_lastParameters.c_str(); +// } + +// //============================================================================= +// /*! +// * +// */ +// //============================================================================= +// void SMESH_Hypothesis::SetLastParameters(const char* theParameters) +// { +// _lastParameters = string(theParameters); +// } diff --git a/src/SMESH/SMESH_Hypothesis.hxx b/src/SMESH/SMESH_Hypothesis.hxx index 0c81caac7..4c29ff333 100644 --- a/src/SMESH/SMESH_Hypothesis.hxx +++ b/src/SMESH/SMESH_Hypothesis.hxx @@ -51,7 +51,7 @@ public: { HYP_OK = 0, HYP_MISSING, // algo misses a hypothesis - HYP_CONCURENT, // several applicable hypotheses + HYP_CONCURENT, // several applicable hypotheses assigned to father shapes HYP_BAD_PARAMETER,// hypothesis has a bad parameter value HYP_HIDDEN_ALGO, // an algo is hidden by an upper dim algo generating all-dim elements HYP_HIDING_ALGO, // an algo hides lower dim algos by generating all-dim elements @@ -59,7 +59,7 @@ public: // for Add/RemoveHypothesis operations HYP_INCOMPATIBLE, // hypothesis does not fit algo HYP_NOTCONFORM, // not conform mesh is produced appling a hypothesis - HYP_ALREADY_EXIST,// such hypothesis already exist + HYP_ALREADY_EXIST,// several applicable hypothesis of same priority assigned HYP_BAD_DIM, // bad dimension HYP_BAD_SUBSHAPE, // shape is neither the main one, nor its sub-shape, nor a group HYP_BAD_GEOMETRY, // shape geometry mismatches algorithm's expectation @@ -77,12 +77,12 @@ public: virtual const char* GetLibName() const; void SetLibName(const char* theLibName); - void SetParameters(const char *theParameters); - char* GetParameters() const; + //void SetParameters(const char *theParameters); + //char* GetParameters() const; - void SetLastParameters(const char* theParameters); - char* GetLastParameters() const; - void ClearParameters(); + // void SetLastParameters(const char* theParameters); + // char* GetLastParameters() const; + // void ClearParameters(); /*! * \brief Initialize my parameter values by the mesh built on the geometry @@ -122,14 +122,14 @@ public: protected: SMESH_Gen* _gen; - int _studyId; - int _shapeType; - int _param_algo_dim; // to be set at descendant hypothesis constructor + int _studyId; + int _shapeType; + int _param_algo_dim; // to be set at descendant hypothesis constructor private: - std::string _libName; - std::string _parameters; - std::string _lastParameters; + std::string _libName; // name of library of plug-in Engine + //std::string _parameters; + //std::string _lastParameters; }; #endif diff --git a/src/SMESH/SMESH_Mesh.cxx b/src/SMESH/SMESH_Mesh.cxx index 1057d3dee..0b171a6ef 100644 --- a/src/SMESH/SMESH_Mesh.cxx +++ b/src/SMESH/SMESH_Mesh.cxx @@ -40,14 +40,15 @@ #include "utilities.h" -#include "DriverMED_W_SMESHDS_Mesh.h" #include "DriverDAT_W_SMDS_Mesh.h" -#include "DriverUNV_W_SMDS_Mesh.h" -#include "DriverSTL_W_SMDS_Mesh.h" - +#include "DriverGMF_Read.hxx" +#include "DriverGMF_Write.hxx" #include "DriverMED_R_SMESHDS_Mesh.h" -#include "DriverUNV_R_SMDS_Mesh.h" +#include "DriverMED_W_SMESHDS_Mesh.h" #include "DriverSTL_R_SMDS_Mesh.h" +#include "DriverSTL_W_SMDS_Mesh.h" +#include "DriverUNV_R_SMDS_Mesh.h" +#include "DriverUNV_W_SMDS_Mesh.h" #ifdef WITH_CGNS #include "DriverCGNS_Read.hxx" #include "DriverCGNS_Write.hxx" @@ -538,6 +539,26 @@ int SMESH_Mesh::CGNSToMesh(const char* theFileName, return res; } +//================================================================================ +/*! + * \brief Fill its data by reading a GMF file + */ +//================================================================================ + +SMESH_ComputeErrorPtr SMESH_Mesh::GMFToMesh(const char* theFileName) +{ + DriverGMF_Read myReader; + myReader.SetMesh(_myMeshDS); + myReader.SetFile(theFileName); + myReader.Perform(); + //theMeshName = myReader.GetMeshName(); + + // create groups + SynchronizeGroups(); + + return myReader.GetError(); +} + //============================================================================= /*! * @@ -1391,6 +1412,21 @@ void SMESH_Mesh::ExportCGNS(const char * file, throw SALOME_Exception("Export failed"); } +//================================================================================ +/*! + * \brief Export the mesh to a GMF file + */ +//================================================================================ + +void SMESH_Mesh::ExportGMF(const char * file, + const SMESHDS_Mesh* meshDS) +{ + DriverGMF_Write myWriter; + myWriter.SetFile( file ); + myWriter.SetMesh( const_cast( meshDS )); + myWriter.Perform(); +} + //================================================================================ /*! * \brief Return number of nodes in the mesh @@ -1651,6 +1687,35 @@ SMESH_Group* SMESH_Mesh::AddGroup (const SMDSAbs_ElementType theType, return aGroup; } +//================================================================================ +/*! + * \brief Creates a group based on an existing SMESHDS group. Group ID should be unique + */ +//================================================================================ + +SMESH_Group* SMESH_Mesh::AddGroup (SMESHDS_GroupBase* groupDS) throw(SALOME_Exception) +{ + if ( !groupDS ) + throw SALOME_Exception(LOCALIZED ("SMESH_Mesh::AddGroup(): NULL SMESHDS_GroupBase")); + + map ::iterator i_g = _mapGroup.find( groupDS->GetID() ); + if ( i_g != _mapGroup.end() && i_g->second ) + { + if ( i_g->second->GetGroupDS() == groupDS ) + return i_g->second; + else + throw SALOME_Exception(LOCALIZED ("SMESH_Mesh::AddGroup() wrong ID of SMESHDS_GroupBase")); + } + SMESH_Group* aGroup = new SMESH_Group (groupDS); + _mapGroup[ groupDS->GetID() ] = aGroup; + GetMeshDS()->AddGroup( aGroup->GetGroupDS() ); + + _groupId = 1 + _mapGroup.rbegin()->first; + + return aGroup; +} + + //================================================================================ /*! * \brief Creates SMESH_Groups for not wrapped SMESHDS_Groups @@ -1955,6 +2020,13 @@ void SMESH_Mesh::fillAncestorsMap(const TopoDS_Shape& theShape) (TopAbs_ShapeEnum) ancType, _mapAncestors ); } + // visit COMPOUNDs inside a COMPOUND that are not reachable by TopExp_Explorer + if ( theShape.ShapeType() == TopAbs_COMPOUND ) + { + for ( TopoDS_Iterator sIt(theShape); sIt.More(); sIt.Next() ) + if ( sIt.Value().ShapeType() == TopAbs_COMPOUND ) + fillAncestorsMap( sIt.Value() ); + } } //============================================================================= @@ -1977,9 +2049,9 @@ bool SMESH_Mesh::SortByMeshOrder(list& theListToSort) const typedef list::iterator TPosInList; map< int, TPosInList > sortedPos; TPosInList smBeg = theListToSort.begin(), smEnd = theListToSort.end(); - TListOfListOfInt::const_iterator listIddIt = _mySubMeshOrder.begin(); - for( ; listIddIt != _mySubMeshOrder.end(); listIddIt++) { - const TListOfInt& listOfId = *listIddIt; + TListOfListOfInt::const_iterator listIdsIt = _mySubMeshOrder.begin(); + for( ; listIdsIt != _mySubMeshOrder.end(); listIdsIt++) { + const TListOfInt& listOfId = *listIdsIt; TListOfInt::const_iterator idIt = listOfId.begin(); for ( ; idIt != listOfId.end(); idIt++ ) { if ( SMESH_subMesh * sm = GetSubMeshContaining( *idIt )) { @@ -2006,6 +2078,30 @@ bool SMESH_Mesh::SortByMeshOrder(list& theListToSort) const return res; } +//================================================================================ +/*! + * \brief Return true if given order of sub-meshes is OK + */ +//================================================================================ + +bool SMESH_Mesh::IsOrderOK( const SMESH_subMesh* smBefore, + const SMESH_subMesh* smAfter ) const +{ + TListOfListOfInt::const_iterator listIdsIt = _mySubMeshOrder.begin(); + TListOfInt::const_iterator idBef, idAft; + for( ; listIdsIt != _mySubMeshOrder.end(); listIdsIt++) + { + const TListOfInt& listOfId = *listIdsIt; + idBef = std::find( listOfId.begin(), listOfId.end(), smBefore->GetId() ); + if ( idBef != listOfId.end() ) + idAft = std::find( listOfId.begin(), listOfId.end(), smAfter->GetId() ); + if ( idAft != listOfId.end () ) + return ( std::distance( listOfId.begin(), idBef ) < + std::distance( listOfId.begin(), idAft ) ); + } + return true; // no order imposed to given submeshes +} + //============================================================================= /*! * \brief sort submeshes according to stored mesh order @@ -2014,8 +2110,8 @@ bool SMESH_Mesh::SortByMeshOrder(list& theListToSort) const */ //============================================================================= -list SMESH_Mesh::getAncestorsSubMeshes - (const TopoDS_Shape& theSubShape) const +list +SMESH_Mesh::getAncestorsSubMeshes (const TopoDS_Shape& theSubShape) const { list listOfSubMesh; TopTools_ListIteratorOfListOfShape it( GetAncestors( theSubShape )); diff --git a/src/SMESH/SMESH_Mesh.hxx b/src/SMESH/SMESH_Mesh.hxx index 5ae3cc61c..5bd9b9c14 100644 --- a/src/SMESH/SMESH_Mesh.hxx +++ b/src/SMESH/SMESH_Mesh.hxx @@ -29,12 +29,12 @@ #include "SMESH_SMESH.hxx" -#include "SMESH_Hypothesis.hxx" -#include "SMESH_Controls.hxx" - -#include "SMESHDS_Mesh.hxx" -#include "SMESHDS_Command.hxx" #include "SMDSAbs_ElementType.hxx" +#include "SMESHDS_Command.hxx" +#include "SMESHDS_Mesh.hxx" +#include "SMESH_ComputeError.hxx" +#include "SMESH_Controls.hxx" +#include "SMESH_Hypothesis.hxx" #include "Utils_SALOME_Exception.hxx" @@ -44,6 +44,7 @@ #include #include + #ifdef WNT #pragma warning(disable:4251) // Warning DLL Interface ... #pragma warning(disable:4290) // Warning Exception ... @@ -121,6 +122,8 @@ public: int CGNSToMesh(const char* theFileName, const int theMeshIndex, std::string& theMeshName); + SMESH_ComputeErrorPtr GMFToMesh(const char* theFileName); + SMESH_Hypothesis::Hypothesis_Status AddHypothesis(const TopoDS_Shape & aSubShape, int anHypId) throw(SALOME_Exception); @@ -240,6 +243,8 @@ public: const SMESHDS_Mesh* meshPart = 0) throw(SALOME_Exception); void ExportCGNS(const char * file, const SMESHDS_Mesh* mesh); + void ExportGMF(const char * file, + const SMESHDS_Mesh* mesh); void ExportSAUV(const char *file, const char* theMeshName = NULL, bool theAutoGroups = true) throw(SALOME_Exception); @@ -287,7 +292,9 @@ public: int& theId, const TopoDS_Shape& theShape=TopoDS_Shape(), const SMESH_PredicatePtr& thePredicate=SMESH_PredicatePtr()); - + + SMESH_Group* AddGroup (SMESHDS_GroupBase* groupDS) throw(SALOME_Exception); + typedef boost::shared_ptr< SMDS_Iterator > GroupIteratorPtr; GroupIteratorPtr GetGroups() const; @@ -317,15 +324,13 @@ public: void SetMeshOrder(const TListOfListOfInt& theOrder ); const TListOfListOfInt& GetMeshOrder() const; - /*! - * \brief sort submeshes according to stored mesh order - * \param theListToSort in out list to be sorted - * \return FALSE if nothing sorted - */ + // sort submeshes according to stored mesh order bool SortByMeshOrder(std::list& theListToSort) const; - // - + // return true if given order of sub-meshes is OK + bool IsOrderOK( const SMESH_subMesh* smBefore, + const SMESH_subMesh* smAfter ) const; + ostream& Dump(ostream & save); private: diff --git a/src/SMESH/SMESH_MeshEditor.cxx b/src/SMESH/SMESH_MeshEditor.cxx index 324b6b81d..9a821ab80 100644 --- a/src/SMESH/SMESH_MeshEditor.cxx +++ b/src/SMESH/SMESH_MeshEditor.cxx @@ -496,10 +496,10 @@ static void ShiftNodesQuadTria(const SMDS_MeshNode* aNodes[]) //======================================================================= //function : edgeConnectivity -//purpose : auxilary +//purpose : auxilary // return number of the edges connected with the theNode. // if theEdges has connections with the other type of the -// elements, return -1 +// elements, return -1 //======================================================================= static int nbEdgeConnectivity(const SMDS_MeshNode* theNode) { @@ -1741,7 +1741,7 @@ void SMESH_MeshEditor::SplitVolumesIntoTetra (const TIDSortedElemSet & theElems, SMESHDS_SubMesh* subMesh = 0;//GetMeshDS()->MeshElements(1); SMESHDS_SubMesh* fSubMesh = 0;//subMesh; - + SMESH_SequenceOfElemPtr newNodes, newElems; // map face of volume to it's baricenrtic node @@ -2854,7 +2854,7 @@ void SMESH_MeshEditor::GetLinkedNodes( const SMDS_MeshNode* theNode, const SMDS_MeshElement* elem = elemIt->next(); if(elem->GetType() == SMDSAbs_0DElement) continue; - + SMDS_ElemIteratorPtr nodeIt = elem->nodesIterator(); if ( elem->GetType() == SMDSAbs_Volume ) { @@ -3581,9 +3581,9 @@ void SMESH_MeshEditor::sweepElement(const SMDS_MeshElement* elem, //MESSAGE("sweepElement " << nbSteps); SMESHDS_Mesh* aMesh = GetMeshDS(); - const int nbNodes = elem->NbNodes(); + const int nbNodes = elem->NbNodes(); const int nbCorners = elem->NbCornerNodes(); - SMDSAbs_EntityType baseType = elem->GetEntityType(); /* it can change in case of + SMDSAbs_EntityType baseType = elem->GetEntityType(); /* it can change in case of polyhedron creation !!! */ // Loop on elem nodes: // find new nodes and detect same nodes indices @@ -3861,7 +3861,7 @@ void SMESH_MeshEditor::sweepElement(const SMDS_MeshElement* elem, midlNod[0], midlNod[1], midlNod[2], midlNod[3]); } else if(nbSame==1) { - // ---> pyramid + pentahedron - can not be created since it is needed + // ---> pyramid + pentahedron - can not be created since it is needed // additional middle node at the center of face INFOS( " Sweep for face " << elem->GetID() << " can not be created" ); return; @@ -4031,6 +4031,8 @@ void SMESH_MeshEditor::makeWalls (TNodeOfNodeListMap & mapNewNodes, { const SMDS_MeshNode* node = static_cast( nList->first ); + if ( newElemsMap.count( node )) + continue; // node was extruded into edge SMDS_ElemIteratorPtr eIt = node->GetInverseElementIterator(); int nbInitElems = 0; const SMDS_MeshElement* el = 0; @@ -4822,7 +4824,7 @@ SMESH_MeshEditor::ExtrusionAlongTrack (TIDSortedElemSet & theElements, list< list > LLPPs; int startNid = theN1->GetID(); TColStd_MapOfInteger UsedNums; - + int NbEdges = Edges.Length(); int i = 1; for(; i<=NbEdges; i++) { @@ -4973,7 +4975,7 @@ SMESH_MeshEditor::ExtrusionAlongTrack (TIDSortedElemSet & theElements, if( !theTrack->GetMeshDS()->Contains(theN1) ) { return EXTR_BAD_STARTING_NODE; } - + conn = nbEdgeConnectivity(theN1); if(conn > 2) return EXTR_PATH_NOT_EDGE; @@ -4988,14 +4990,14 @@ SMESH_MeshEditor::ExtrusionAlongTrack (TIDSortedElemSet & theElements, if(currentNode == prevNode) currentNode = static_cast(nIt->next()); aNodesList.push_back(currentNode); - } else { + } else { nIt = currentElem->nodesIterator(); while( nIt->more() ) { currentNode = static_cast(nIt->next()); if(currentNode == prevNode) currentNode = static_cast(nIt->next()); aNodesList.push_back(currentNode); - + //case of the closed mesh if(currentNode == theN1) { nbEdges++; @@ -5004,7 +5006,7 @@ SMESH_MeshEditor::ExtrusionAlongTrack (TIDSortedElemSet & theElements, conn = nbEdgeConnectivity(currentNode); if(conn > 2) { - return EXTR_PATH_NOT_EDGE; + return EXTR_PATH_NOT_EDGE; }else if( conn == 1 && nbEdges > 0 ) { //End of the path nbEdges++; @@ -5020,8 +5022,8 @@ SMESH_MeshEditor::ExtrusionAlongTrack (TIDSortedElemSet & theElements, nbEdges++; } } - } - + } + if(nbEdges != totalNbEdges) return EXTR_PATH_NOT_EDGE; @@ -5033,7 +5035,7 @@ SMESH_MeshEditor::ExtrusionAlongTrack (TIDSortedElemSet & theElements, x1 = aNodesList[i-1]->X();x2 = aNodesList[i]->X(); y1 = aNodesList[i-1]->Y();y2 = aNodesList[i]->Y(); z1 = aNodesList[i-1]->Z();z2 = aNodesList[i]->Z(); - TopoDS_Edge e = BRepBuilderAPI_MakeEdge(gp_Pnt(x1,y1,z1),gp_Pnt(x2,y2,z2)); + TopoDS_Edge e = BRepBuilderAPI_MakeEdge(gp_Pnt(x1,y1,z1),gp_Pnt(x2,y2,z2)); list LPP; aPrms.clear(); MakeEdgePathPoints(aPrms, e, (aNodesList[i-1]->GetID()==startNid), LPP); @@ -5072,7 +5074,7 @@ SMESH_MeshEditor::ExtrusionAlongTrack (TIDSortedElemSet & theElements, fullList.pop_back(); } fullList.push_back(PP1); - + } // Sub-shape for the Pattern must be an Edge or Wire else if( aS.ShapeType() == TopAbs_EDGE ) { aTrackEdge = TopoDS::Edge( aS ); @@ -5707,7 +5709,7 @@ SMESH_MeshEditor::Transform (TIDSortedElemSet & theElems, SMDSAbs_GeometryType geomType = elem->GetGeomType(); int nbNodes = elem->NbNodes(); - if ( geomType == SMDSGeom_POINT ) continue; // node + if ( geomType == SMDSGeom_NONE ) continue; // node switch ( geomType ) { @@ -5884,26 +5886,32 @@ SMESH_MeshEditor::generateGroups(const SMESH_SequenceOfElemPtr& nodeGens, // Sort existing groups by types and collect their names // to store an old group and a generated new one - typedef pair< SMESHDS_GroupBase*, SMDS_MeshGroup* > TOldNewGroup; + typedef pair< SMESHDS_GroupBase*, SMESHDS_Group* > TOldNewGroup; vector< list< TOldNewGroup > > groupsByType( SMDSAbs_NbElementTypes ); + vector< TOldNewGroup* > orderedOldNewGroups; // in order of old groups // group names set< string > groupNames; - // - SMDS_MeshGroup* nullNewGroup = (SMDS_MeshGroup*) 0; + SMESH_Mesh::GroupIteratorPtr groupIt = GetMesh()->GetGroups(); - while ( groupIt->more() ) { + if ( !groupIt->more() ) return newGroupIDs; + + int newGroupID = mesh->GetGroupIds().back()+1; + while ( groupIt->more() ) + { SMESH_Group * group = groupIt->next(); if ( !group ) continue; SMESHDS_GroupBase* groupDS = group->GetGroupDS(); if ( !groupDS || groupDS->IsEmpty() ) continue; groupNames.insert( group->GetName() ); groupDS->SetStoreName( group->GetName() ); - groupsByType[ groupDS->GetType() ].push_back( make_pair( groupDS, nullNewGroup )); + SMESHDS_Group* newGroup = new SMESHDS_Group( newGroupID++, mesh->GetMeshDS(), + groupDS->GetType() ); + groupsByType[ groupDS->GetType() ].push_back( make_pair( groupDS, newGroup )); + orderedOldNewGroups.push_back( & groupsByType[ groupDS->GetType() ].back() ); } - // Groups creation + // Loop on nodes and elements to add them in new groups - // loop on nodes and elements for ( int isNodes = 0; isNodes < 2; ++isNodes ) { const SMESH_SequenceOfElemPtr& gens = isNodes ? nodeGens : elemGens; @@ -5920,7 +5928,7 @@ SMESH_MeshEditor::generateGroups(const SMESH_SequenceOfElemPtr& nodeGens, continue; } list< TOldNewGroup > & groupsOldNew = groupsByType[ sourceElem->GetType() ]; - if ( groupsOldNew.empty() ) { + if ( groupsOldNew.empty() ) { // no groups of this type at all while ( iElem < gens.Length() && gens( iElem+1 ) == sourceElem ) ++iElem; // skip all elements made by sourceElem continue; @@ -5934,58 +5942,56 @@ SMESH_MeshEditor::generateGroups(const SMESH_SequenceOfElemPtr& nodeGens, if ( const SMDS_MeshElement* resElem = elems( ++iElem )) if ( resElem != sourceElem ) resultElems.push_back( resElem ); - // do not generate element groups from node ones -// if ( sourceElem->GetType() == SMDSAbs_Node && -// elems( iElem )->GetType() != SMDSAbs_Node ) -// continue; // add resultElems to groups made by ones the sourceElem belongs to list< TOldNewGroup >::iterator gOldNew, gLast = groupsOldNew.end(); for ( gOldNew = groupsOldNew.begin(); gOldNew != gLast; ++gOldNew ) { SMESHDS_GroupBase* oldGroup = gOldNew->first; - if ( oldGroup->Contains( sourceElem )) // sourceElem in oldGroup + if ( oldGroup->Contains( sourceElem )) // sourceElem is in oldGroup { - SMDS_MeshGroup* & newGroup = gOldNew->second; - if ( !newGroup )// create a new group - { - // make a name - string name = oldGroup->GetStoreName(); - if ( !targetMesh ) { - name += "_"; - name += postfix; - int nb = 0; - while ( !groupNames.insert( name ).second ) // name exists - { - if ( nb == 0 ) { - name += "_1"; - } - else { - TCollection_AsciiString nbStr(nb+1); - name.resize( name.rfind('_')+1 ); - name += nbStr.ToCString(); - } - ++nb; - } - } - // make a group - int id; - SMESH_Group* group = mesh->AddGroup( resultElems.back()->GetType(), - name.c_str(), id ); - SMESHDS_Group* groupDS = static_cast(group->GetGroupDS()); - newGroup = & groupDS->SMDSGroup(); - newGroupIDs->push_back( id ); - } - // fill in a new group + SMDS_MeshGroup & newGroup = gOldNew->second->SMDSGroup(); list< const SMDS_MeshElement* >::iterator resLast = resultElems.end(), resElemIt; for ( resElemIt = resultElems.begin(); resElemIt != resLast; ++resElemIt ) - newGroup->Add( *resElemIt ); + newGroup.Add( *resElemIt ); } } } // loop on created elements }// loop on nodes and elements + // Create new SMESH_Groups from SMESHDS_Groups and remove empty SMESHDS_Groups + + for ( size_t i = 0; i < orderedOldNewGroups.size(); ++i ) + { + SMESHDS_GroupBase* oldGroupDS = orderedOldNewGroups[i]->first; + SMESHDS_Group* newGroupDS = orderedOldNewGroups[i]->second; + if ( newGroupDS->IsEmpty() ) + { + mesh->GetMeshDS()->RemoveGroup( newGroupDS ); + } + else + { + // make a name + string name = oldGroupDS->GetStoreName(); + if ( !targetMesh ) { + name += "_"; + name += postfix; + int nb = 1; + while ( !groupNames.insert( name ).second ) // name exists + name = SMESH_Comment( oldGroupDS->GetStoreName() ) << "_" << postfix << "_" << nb++; + } + newGroupDS->SetStoreName( name.c_str() ); + + // make a SMESH_Groups + mesh->AddGroup( newGroupDS ); + newGroupIDs->push_back( newGroupDS->GetID() ); + + // set group type + newGroupDS->SetType( newGroupDS->GetElements()->next()->GetType() ); + } + } + return newGroupIDs; } @@ -6159,7 +6165,7 @@ private: */ //======================================================================= -SMESH_NodeSearcher* SMESH_MeshEditor::GetNodeSearcher() +SMESH_NodeSearcher* SMESH_MeshEditor::GetNodeSearcher() { return new SMESH_NodeSearcherImpl( GetMeshDS() ); } @@ -6524,12 +6530,12 @@ bool SMESH_ElementSearcherImpl::getIntersParamOnLine(const gp_Lin& lin GeomAPI_ExtremaCurveCurve anExtCC; Handle(Geom_Curve) lineCurve = new Geom_Line( line ); - + int nbNodes = face->IsQuadratic() ? face->NbNodes()/2 : face->NbNodes(); for ( int i = 0; i < nbNodes && nbInts < 2; ++i ) { GC_MakeSegment edge( SMESH_TNodeXYZ( face->GetNode( i )), - SMESH_TNodeXYZ( face->GetNode( (i+1)%nbNodes) )); + SMESH_TNodeXYZ( face->GetNode( (i+1)%nbNodes) )); anExtCC.Init( lineCurve, edge); if ( anExtCC.NbExtrema() > 0 && anExtCC.LowerDistance() <= tol) { @@ -6578,7 +6584,7 @@ void SMESH_ElementSearcherImpl::findOuterBoundary(const SMDS_MeshElement* outerF while (( f = SMESH_MeshEditor::FindFaceInSet(link.node1(), link.node2(), emptySet, faces ))) faces.insert( f ); - // select another outer face among the found + // select another outer face among the found const SMDS_MeshElement* outerFace2 = 0; if ( faces.size() == 2 ) { @@ -6638,7 +6644,7 @@ void SMESH_ElementSearcherImpl::findOuterBoundary(const SMDS_MeshElement* outerF // There are internal boundaries touching the outher one, // find all faces of internal boundaries in order to find // faces of boundaries of holes, if any. - + } else { @@ -6857,7 +6863,7 @@ TopAbs_State SMESH_ElementSearcherImpl::GetPointState(const gp_Pnt& point) int nbInter = u2inters.size(); if ( nbInter == 0 ) - return TopAbs_OUT; + return TopAbs_OUT; double f = u2inters.begin()->first, l = u2inters.rbegin()->first; if ( nbInter == 1 ) // not closed mesh @@ -6991,7 +6997,7 @@ TopAbs_State SMESH_ElementSearcherImpl::GetPointState(const gp_Pnt& point) return TopAbs_ON; if ( nbIntBeforePoint == 0 || nbIntAfterPoint == 0) - return TopAbs_OUT; + return TopAbs_OUT; if ( nbIntBeforePoint + nbIntAfterPoint == 1 ) // not closed mesh return fabs( f ) < tolerance ? TopAbs_ON : TopAbs_UNKNOWN; @@ -9629,7 +9635,7 @@ void SMESH_MeshEditor::ConvertToQuadratic(const bool theForce3d) if ( !theForce3d ) { // setenv NO_FixQuadraticElements to know if FixQuadraticElements() is guilty of bad conversion aHelper.SetSubShape(0); // apply FixQuadraticElements() to the whole mesh - aHelper.FixQuadraticElements(); + aHelper.FixQuadraticElements(myError); } } @@ -9637,7 +9643,7 @@ void SMESH_MeshEditor::ConvertToQuadratic(const bool theForce3d) /*! * \brief Makes given elements quadratic * \param theForce3d - if true, the medium nodes will be placed in the middle of link - * \param theElements - elements to make quadratic + * \param theElements - elements to make quadratic */ //================================================================================ @@ -9648,7 +9654,7 @@ void SMESH_MeshEditor::ConvertToQuadratic(const bool theForce3d, // we believe that all theElements are of the same type const SMDSAbs_ElementType elemType = (*theElements.begin())->GetType(); - + // get all nodes shared by theElements TIDSortedNodeSet allNodes; TIDSortedElemSet::iterator eIt = theElements.begin(); @@ -9769,7 +9775,7 @@ void SMESH_MeshEditor::ConvertToQuadratic(const bool theForce3d, if ( !theForce3d && !getenv("NO_FixQuadraticElements")) { // setenv NO_FixQuadraticElements to know if FixQuadraticElements() is guilty of bad conversion helper.SetSubShape(0); // apply FixQuadraticElements() to the whole mesh - helper.FixQuadraticElements(); + helper.FixQuadraticElements( myError ); } } @@ -10633,7 +10639,7 @@ SMESH_MeshEditor::FindMatchingNodes(set& theSide1, \param theElems - the list of elements (edges or faces) to be replicated The nodes for duplication could be found from these elements \param theNodesNot - list of nodes to NOT replicate - \param theAffectedElems - the list of elements (cells and edges) to which the + \param theAffectedElems - the list of elements (cells and edges) to which the replicated nodes should be associated to. \return TRUE if operation has been completed successfully, FALSE otherwise */ @@ -10696,8 +10702,8 @@ bool SMESH_MeshEditor::doubleNodes( SMESHDS_Mesh* theMeshDS, std::vector newNodes( anElem->NbNodes() ); SMDS_ElemIteratorPtr anIter = anElem->nodesIterator(); int ind = 0; - while ( anIter->more() ) - { + while ( anIter->more() ) + { SMDS_MeshNode* aCurrNode = (SMDS_MeshNode*)anIter->next(); SMDS_MeshNode* aNewNode = aCurrNode; @@ -10732,14 +10738,14 @@ bool SMESH_MeshEditor::doubleNodes( SMESHDS_Mesh* theMeshDS, /*! \brief Creates a hole in a mesh by doubling the nodes of some particular elements \param theNodes - identifiers of nodes to be doubled - \param theModifiedElems - identifiers of elements to be updated by the new (doubled) - nodes. If list of element identifiers is empty then nodes are doubled but + \param theModifiedElems - identifiers of elements to be updated by the new (doubled) + nodes. If list of element identifiers is empty then nodes are doubled but they not assigned to elements \return TRUE if operation has been completed successfully, FALSE otherwise */ //================================================================================ -bool SMESH_MeshEditor::DoubleNodes( const std::list< int >& theListOfNodes, +bool SMESH_MeshEditor::DoubleNodes( const std::list< int >& theListOfNodes, const std::list< int >& theListOfModifiedElems ) { MESSAGE("DoubleNodes"); @@ -10780,7 +10786,7 @@ bool SMESH_MeshEditor::DoubleNodes( const std::list< int >& theListOfNodes, std::map< SMDS_MeshElement*, vector > anElemToNodes; std::list< int >::const_iterator anElemIter; - for ( anElemIter = theListOfModifiedElems.begin(); + for ( anElemIter = theListOfModifiedElems.begin(); anElemIter != theListOfModifiedElems.end(); ++anElemIter ) { int aCurr = *anElemIter; @@ -10792,8 +10798,8 @@ bool SMESH_MeshEditor::DoubleNodes( const std::list< int >& theListOfNodes, SMDS_ElemIteratorPtr anIter = anElem->nodesIterator(); int ind = 0; - while ( anIter->more() ) - { + while ( anIter->more() ) + { SMDS_MeshNode* aCurrNode = (SMDS_MeshNode*)anIter->next(); if ( aCurr && anOldNodeToNewNode.find( aCurrNode ) != anOldNodeToNewNode.end() ) { @@ -10806,7 +10812,7 @@ bool SMESH_MeshEditor::DoubleNodes( const std::list< int >& theListOfNodes, anElemToNodes[ anElem ] = aNodeArr; } - // Change nodes of elements + // Change nodes of elements std::map< SMDS_MeshElement*, vector >::iterator anElemToNodesIter = anElemToNodes.begin(); @@ -10888,6 +10894,70 @@ namespace { }; } +//================================================================================ +/*! + \brief Identify the elements that will be affected by node duplication (actual duplication is not performed. + This method is the first step of DoubleNodeElemGroupsInRegion. + \param theElems - list of groups of elements (edges or faces) to be replicated + \param theNodesNot - list of groups of nodes not to replicated + \param theShape - shape to detect affected elements (element which geometric center + located on or inside shape). + The replicated nodes should be associated to affected elements. + \return groups of affected elements + \sa DoubleNodeElemGroupsInRegion() + */ +//================================================================================ + +bool SMESH_MeshEditor::AffectedElemGroupsInRegion( const TIDSortedElemSet& theElems, + const TIDSortedElemSet& theNodesNot, + const TopoDS_Shape& theShape, + TIDSortedElemSet& theAffectedElems) +{ + if ( theShape.IsNull() ) + return false; + + const double aTol = Precision::Confusion(); + auto_ptr< BRepClass3d_SolidClassifier> bsc3d; + auto_ptr<_FaceClassifier> aFaceClassifier; + if ( theShape.ShapeType() == TopAbs_SOLID ) + { + bsc3d.reset( new BRepClass3d_SolidClassifier(theShape));; + bsc3d->PerformInfinitePoint(aTol); + } + else if (theShape.ShapeType() == TopAbs_FACE ) + { + aFaceClassifier.reset( new _FaceClassifier(TopoDS::Face(theShape))); + } + + // iterates on indicated elements and get elements by back references from their nodes + TIDSortedElemSet::const_iterator elemItr = theElems.begin(); + for ( ; elemItr != theElems.end(); ++elemItr ) + { + SMDS_MeshElement* anElem = (SMDS_MeshElement*)*elemItr; + if (!anElem) + continue; + + SMDS_ElemIteratorPtr nodeItr = anElem->nodesIterator(); + while ( nodeItr->more() ) + { + const SMDS_MeshNode* aNode = cast2Node(nodeItr->next()); + if ( !aNode || theNodesNot.find(aNode) != theNodesNot.end() ) + continue; + SMDS_ElemIteratorPtr backElemItr = aNode->GetInverseElementIterator(); + while ( backElemItr->more() ) + { + const SMDS_MeshElement* curElem = backElemItr->next(); + if ( curElem && theElems.find(curElem) == theElems.end() && + ( bsc3d.get() ? + isInside( curElem, *bsc3d, aTol ) : + isInside( curElem, *aFaceClassifier, aTol ))) + theAffectedElems.insert( curElem ); + } + } + } + return true; +} + //================================================================================ /*! \brief Creates a hole in a mesh by doubling the nodes of some particular elements @@ -11018,7 +11088,7 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector volume to modify) // with all the faces shared by 2 domains (group of elements) // and corresponding volume of this domain, for each shared face. - // a volume has a face shared by 2 domains if it has a neighbor which is not in is domain. + // a volume has a face shared by 2 domains if it has a neighbor which is not in his domain. //MESSAGE("Domain " << idom); const TIDSortedElemSet& domain = theElems[idom]; @@ -11081,8 +11151,6 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector cells; - cells.clear(); vtkCellLinks::Link l = grid->GetCellLinks()->GetLink(oldId); for (int i=0; i oldNodes; oldNodes.clear(); grid->GetNodeIds(oldNodes, face.cellId, face.cellType); - bool isMultipleDetected = false; std::set::iterator itn = oldNodes.begin(); for (; itn != oldNodes.end(); ++itn) { int oldId = *itn; - //MESSAGE(" node " << oldId); + //MESSAGE("-+-+-a node " << oldId); if (!nodeDomains.count(oldId)) nodeDomains[oldId] = emptyMap; // create an empty entry for node if (nodeDomains[oldId].empty()) - nodeDomains[oldId][idomain] = oldId; // keep the old node in the first domain + { + nodeDomains[oldId][idomain] = oldId; // keep the old node in the first domain + //MESSAGE("-+-+-b oldNode " << oldId << " domain " << idomain); + } std::map::iterator itdom = domvol.begin(); for (; itdom != domvol.end(); ++itdom) { @@ -11155,7 +11225,6 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector orderedDoms; //MESSAGE("multiple node " << oldId); - isMultipleDetected =true; if (mutipleNodes.count(oldId)) orderedDoms = mutipleNodes[oldId]; else @@ -11175,16 +11244,35 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vectorAddNode(coords[0], coords[1], coords[2]); int newId = newNode->getVtkId(); nodeDomains[oldId][idom] = newId; // cloned node for other domains - //MESSAGE(" newNode " << newId << " oldNode " << oldId << " size=" <= 3) - { - //MESSAGE("confirm multiple node " << oldId); - isMultipleDetected =true; + //MESSAGE("-+-+-c oldNode " << oldId << " domain " << idomain << " newNode " << newId << " domain " << idom << " size=" < domvol = itface->second; + if (!domvol.count(idomain)) + continue; + DownIdType face = itface->first; + //MESSAGE(" --- face " << face.cellId); + std::set oldNodes; + oldNodes.clear(); + grid->GetNodeIds(oldNodes, face.cellId, face.cellType); + int nbMultipleNodes = 0; + std::set::iterator itn = oldNodes.begin(); + for (; itn != oldNodes.end(); ++itn) + { + int oldId = *itn; + if (mutipleNodes.count(oldId)) + nbMultipleNodes++; + } + if (nbMultipleNodes > 1) // check if an edge of the face is shared between 3 or more domains { //MESSAGE("multiple Nodes detected on a shared face"); int downId = itface->first.cellId; @@ -11198,7 +11286,7 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vectorgetDownArray(cellType)->getNumberOfDownCells(downId); @@ -11212,9 +11300,12 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector vn0 = mutipleNodes[nodes[0]]; vector vn1 = mutipleNodes[nodes[nbNodes - 1]]; - sort( vn0.begin(), vn0.end() ); - sort( vn1.begin(), vn1.end() ); - if (vn0 == vn1) + vector doms; + for (int i0 = 0; i0 < vn0.size(); i0++) + for (int i1 = 0; i1 < vn1.size(); i1++) + if (vn0[i0] == vn1[i1]) + doms.push_back(vn0[i0]); + if (doms.size() >2) { //MESSAGE(" detect edgesMultiDomains " << nodes[0] << " " << nodes[nbNodes - 1]); double *coords = grid->GetPoint(nodes[0]); @@ -11226,9 +11317,9 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector domvol; // domain --> a volume with the edge map angleDom; // oriented angles between planes defined by edge and volume centers int nbvol = grid->GetParentVolumes(vtkVolIds, downEdgeIds[ie], edgeType[ie]); - for (int id=0; id < vn0.size(); id++) + for (int id=0; id < doms.size(); id++) { - int idom = vn0[id]; + int idom = doms[id]; for (int ivol=0; ivolfromVtkToSmds(vtkVolIds[ivol]); @@ -11291,6 +11382,14 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vectormyMesh->AddGroup(SMDSAbs_Face, joints2DName.c_str(), idg); + SMESHDS_Group *joints2DGrp = dynamic_cast(mapOfJunctionGroups[joints2DName]->GetGroupDS()); + string joints3DName = "joints3D"; + mapOfJunctionGroups[joints3DName] = this->myMesh->AddGroup(SMDSAbs_Volume, joints3DName.c_str(), idg); + SMESHDS_Group *joints3DGrp = dynamic_cast(mapOfJunctionGroups[joints3DName]->GetGroupDS()); + itface = faceDomains.begin(); for (; itface != faceDomains.end(); ++itface) { @@ -11314,13 +11413,16 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vectormyMesh->AddGroup(vol->GetType(), namegrp.c_str(), idg); SMESHDS_Group *sgrp = dynamic_cast(mapOfJunctionGroups[namegrp]->GetGroupDS()); if (sgrp) sgrp->Add(vol->GetID()); + if (vol->GetType() == SMDSAbs_Volume) + joints3DGrp->Add(vol->GetID()); + else if (vol->GetType() == SMDSAbs_Face) + joints2DGrp->Add(vol->GetID()); } } @@ -11374,11 +11476,8 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vectorGetMeshDS()->AddVolumeFromVtkIds(orderedNodes); - stringstream grpname; - grpname << "mj_"; - grpname << 0 << "_" << 0; int idg; - string namegrp = grpname.str(); + string namegrp = "jointsMultiples"; if (!mapOfJunctionGroups.count(namegrp)) mapOfJunctionGroups[namegrp] = this->myMesh->AddGroup(SMDSAbs_Volume, namegrp.c_str(), idg); SMESHDS_Group *sgrp = dynamic_cast(mapOfJunctionGroups[namegrp]->GetGroupDS()); @@ -11387,7 +11486,7 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector& nodesCoords, + std::vector >& listOfListOfNodes) +{ + MESSAGE("--------------------------------"); + MESSAGE("SMESH_MeshEditor::CreateHoleSkin"); + MESSAGE("--------------------------------"); + + // --- zone of volumes to remove is given : + // 1 either by a geom shape (one or more vertices) and a radius, + // 2 either by a group of nodes (representative of the shape)to use with the radius, + // 3 either by a group of nodes where all the elements build on one of this nodes are to remove, + // In the case 2, the group of nodes is an external group of nodes from another mesh, + // In the case 3, the group of nodes is an internal group of the mesh (obtained for instance by a filter), + // defined by it's name. + + SMESHDS_GroupBase* groupDS = 0; + SMESH_Mesh::GroupIteratorPtr groupIt = this->myMesh->GetGroups(); + while ( groupIt->more() ) + { + groupDS = 0; + SMESH_Group * group = groupIt->next(); + if ( !group ) continue; + groupDS = group->GetGroupDS(); + if ( !groupDS || groupDS->IsEmpty() ) continue; + std::string grpName = group->GetName(); + if (grpName == groupName) + break; + } + + bool isNodeGroup = false; + bool isNodeCoords = false; + if (groupDS) + { + if (groupDS->GetType() != SMDSAbs_Node) + return; + isNodeGroup = true; // a group of nodes exists and it is in this mesh + } + + if (nodesCoords.size() > 0) + isNodeCoords = true; // a list o nodes given by their coordinates + + // --- define groups to build + + int idg; // --- group of SMDS volumes + string grpvName = groupName; + grpvName += "_vol"; + SMESH_Group *grp = this->myMesh->AddGroup(SMDSAbs_Volume, grpvName.c_str(), idg); + if (!grp) + { + MESSAGE("group not created " << grpvName); + return; + } + SMESHDS_Group *sgrp = dynamic_cast(grp->GetGroupDS()); + + int idgs; // --- group of SMDS faces on the skin + string grpsName = groupName; + grpsName += "_skin"; + SMESH_Group *grps = this->myMesh->AddGroup(SMDSAbs_Face, grpsName.c_str(), idgs); + if (!grps) + { + MESSAGE("group not created " << grpsName); + return; + } + SMESHDS_Group *sgrps = dynamic_cast(grps->GetGroupDS()); + + int idgi; // --- group of SMDS faces internal (several shapes) + string grpiName = groupName; + grpiName += "_internalFaces"; + SMESH_Group *grpi = this->myMesh->AddGroup(SMDSAbs_Face, grpiName.c_str(), idgi); + if (!grpi) + { + MESSAGE("group not created " << grpiName); + return; + } + SMESHDS_Group *sgrpi = dynamic_cast(grpi->GetGroupDS()); + + int idgei; // --- group of SMDS faces internal (several shapes) + string grpeiName = groupName; + grpeiName += "_internalEdges"; + SMESH_Group *grpei = this->myMesh->AddGroup(SMDSAbs_Edge, grpeiName.c_str(), idgei); + if (!grpei) + { + MESSAGE("group not created " << grpeiName); + return; + } + SMESHDS_Group *sgrpei = dynamic_cast(grpei->GetGroupDS()); + + // --- build downward connectivity + + SMESHDS_Mesh *meshDS = this->myMesh->GetMeshDS(); + meshDS->BuildDownWardConnectivity(true); + SMDS_UnstructuredGrid* grid = meshDS->getGrid(); + + // --- set of volumes detected inside + + std::set setOfInsideVol; + std::set setOfVolToCheck; + + std::vector gpnts; + gpnts.clear(); + + if (isNodeGroup) // --- a group of nodes is provided : find all the volumes using one or more of this nodes + { + MESSAGE("group of nodes provided"); + SMDS_ElemIteratorPtr elemIt = groupDS->GetElements(); + while ( elemIt->more() ) + { + const SMDS_MeshElement* elem = elemIt->next(); + if (!elem) + continue; + const SMDS_MeshNode* node = dynamic_cast(elem); + if (!node) + continue; + SMDS_MeshElement* vol = 0; + SMDS_ElemIteratorPtr volItr = node->GetInverseElementIterator(SMDSAbs_Volume); + while (volItr->more()) + { + vol = (SMDS_MeshElement*)volItr->next(); + setOfInsideVol.insert(vol->getVtkId()); + sgrp->Add(vol->GetID()); + } + } + } + else if (isNodeCoords) + { + MESSAGE("list of nodes coordinates provided"); + int i = 0; + int k = 0; + while (i < nodesCoords.size()-2) + { + double x = nodesCoords[i++]; + double y = nodesCoords[i++]; + double z = nodesCoords[i++]; + gp_Pnt p = gp_Pnt(x, y ,z); + gpnts.push_back(p); + MESSAGE("TopoDS_Vertex " << k++ << " " << p.X() << " " << p.Y() << " " << p.Z()); + } + } + else // --- no group, no coordinates : use the vertices of the geom shape provided, and radius + { + MESSAGE("no group of nodes provided, using vertices from geom shape, and radius"); + TopTools_IndexedMapOfShape vertexMap; + TopExp::MapShapes( theShape, TopAbs_VERTEX, vertexMap ); + gp_Pnt p = gp_Pnt(0,0,0); + if (vertexMap.Extent() < 1) + return; + + for ( int i = 1; i <= vertexMap.Extent(); ++i ) + { + const TopoDS_Vertex& vertex = TopoDS::Vertex( vertexMap( i )); + p = BRep_Tool::Pnt(vertex); + gpnts.push_back(p); + MESSAGE("TopoDS_Vertex " << i << " " << p.X() << " " << p.Y() << " " << p.Z()); + } + } + + if (gpnts.size() > 0) + { + int nodeId = 0; + const SMDS_MeshNode* startNode = theNodeSearcher->FindClosestTo(gpnts[0]); + if (startNode) + nodeId = startNode->GetID(); + MESSAGE("nodeId " << nodeId); + + double radius2 = radius*radius; + MESSAGE("radius2 " << radius2); + + // --- volumes on start node + + setOfVolToCheck.clear(); + SMDS_MeshElement* startVol = 0; + SMDS_ElemIteratorPtr volItr = startNode->GetInverseElementIterator(SMDSAbs_Volume); + while (volItr->more()) + { + startVol = (SMDS_MeshElement*)volItr->next(); + setOfVolToCheck.insert(startVol->getVtkId()); + } + if (setOfVolToCheck.empty()) + { + MESSAGE("No volumes found"); + return; + } + + // --- starting with central volumes then their neighbors, check if they are inside + // or outside the domain, until no more new neighbor volume is inside. + // Fill the group of inside volumes + + std::map mapOfNodeDistance2; + mapOfNodeDistance2.clear(); + std::set setOfOutsideVol; + while (!setOfVolToCheck.empty()) + { + std::set::iterator it = setOfVolToCheck.begin(); + int vtkId = *it; + MESSAGE("volume to check, vtkId " << vtkId << " smdsId " << meshDS->fromVtkToSmds(vtkId)); + bool volInside = false; + vtkIdType npts = 0; + vtkIdType* pts = 0; + grid->GetCellPoints(vtkId, npts, pts); + for (int i=0; iGetPoint(pts[i]); + gp_Pnt aPoint = gp_Pnt(coords[0], coords[1], coords[2]); + distance2 = 1.E40; + for (int j=0; jAdd(meshDS->fromVtkToSmds(vtkId)); + break; + } + } + if (volInside) + { + setOfInsideVol.insert(vtkId); + MESSAGE(" volume inside, vtkId " << vtkId << " smdsId " << meshDS->fromVtkToSmds(vtkId)); + int neighborsVtkIds[NBMAXNEIGHBORS]; + int downIds[NBMAXNEIGHBORS]; + unsigned char downTypes[NBMAXNEIGHBORS]; + int nbNeighbors = grid->GetNeighbors(neighborsVtkIds, downIds, downTypes, vtkId); + for (int n = 0; n < nbNeighbors; n++) + if (!setOfInsideVol.count(neighborsVtkIds[n]) ||setOfOutsideVol.count(neighborsVtkIds[n])) + setOfVolToCheck.insert(neighborsVtkIds[n]); + } + else + { + setOfOutsideVol.insert(vtkId); + MESSAGE(" volume outside, vtkId " << vtkId << " smdsId " << meshDS->fromVtkToSmds(vtkId)); + } + setOfVolToCheck.erase(vtkId); + } + } + + // --- for outside hexahedrons, check if they have more than one neighbor volume inside + // If yes, add the volume to the inside set + + bool addedInside = true; + std::set setOfVolToReCheck; + while (addedInside) + { + MESSAGE(" --------------------------- re check"); + addedInside = false; + std::set::iterator itv = setOfInsideVol.begin(); + for (; itv != setOfInsideVol.end(); ++itv) + { + int vtkId = *itv; + int neighborsVtkIds[NBMAXNEIGHBORS]; + int downIds[NBMAXNEIGHBORS]; + unsigned char downTypes[NBMAXNEIGHBORS]; + int nbNeighbors = grid->GetNeighbors(neighborsVtkIds, downIds, downTypes, vtkId); + for (int n = 0; n < nbNeighbors; n++) + if (!setOfInsideVol.count(neighborsVtkIds[n])) + setOfVolToReCheck.insert(neighborsVtkIds[n]); + } + setOfVolToCheck = setOfVolToReCheck; + setOfVolToReCheck.clear(); + while (!setOfVolToCheck.empty()) + { + std::set::iterator it = setOfVolToCheck.begin(); + int vtkId = *it; + if (grid->GetCellType(vtkId) == VTK_HEXAHEDRON) + { + MESSAGE("volume to recheck, vtkId " << vtkId << " smdsId " << meshDS->fromVtkToSmds(vtkId)); + int countInside = 0; + int neighborsVtkIds[NBMAXNEIGHBORS]; + int downIds[NBMAXNEIGHBORS]; + unsigned char downTypes[NBMAXNEIGHBORS]; + int nbNeighbors = grid->GetNeighbors(neighborsVtkIds, downIds, downTypes, vtkId); + for (int n = 0; n < nbNeighbors; n++) + if (setOfInsideVol.count(neighborsVtkIds[n])) + countInside++; + MESSAGE("countInside " << countInside); + if (countInside > 1) + { + MESSAGE(" volume inside, vtkId " << vtkId << " smdsId " << meshDS->fromVtkToSmds(vtkId)); + setOfInsideVol.insert(vtkId); + sgrp->Add(meshDS->fromVtkToSmds(vtkId)); + addedInside = true; + } + else + setOfVolToReCheck.insert(vtkId); + } + setOfVolToCheck.erase(vtkId); + } + } + + // --- map of Downward faces at the boundary, inside the global volume + // map of Downward faces on the skin of the global volume (equivalent to SMDS faces on the skin) + // fill group of SMDS faces inside the volume (when several volume shapes) + // fill group of SMDS faces on the skin of the global volume (if skin) + + std::map boundaryFaces; // boundary faces inside the volume --> corresponding cell + std::map skinFaces; // faces on the skin of the global volume --> corresponding cell + std::set::iterator it = setOfInsideVol.begin(); + for (; it != setOfInsideVol.end(); ++it) + { + int vtkId = *it; + //MESSAGE(" vtkId " << vtkId << " smdsId " << meshDS->fromVtkToSmds(vtkId)); + int neighborsVtkIds[NBMAXNEIGHBORS]; + int downIds[NBMAXNEIGHBORS]; + unsigned char downTypes[NBMAXNEIGHBORS]; + int nbNeighbors = grid->GetNeighbors(neighborsVtkIds, downIds, downTypes, vtkId, true); + for (int n = 0; n < nbNeighbors; n++) + { + int neighborDim = SMDS_Downward::getCellDimension(grid->GetCellType(neighborsVtkIds[n])); + if (neighborDim == 3) + { + if (! setOfInsideVol.count(neighborsVtkIds[n])) // neighbor volume is not inside : face is boundary + { + DownIdType face(downIds[n], downTypes[n]); + boundaryFaces[face] = vtkId; + } + // if the face between to volumes is in the mesh, get it (internal face between shapes) + int vtkFaceId = grid->getDownArray(downTypes[n])->getVtkCellId(downIds[n]); + if (vtkFaceId >= 0) + { + sgrpi->Add(meshDS->fromVtkToSmds(vtkFaceId)); + // find also the smds edges on this face + int nbEdges = grid->getDownArray(downTypes[n])->getNumberOfDownCells(downIds[n]); + const int* dEdges = grid->getDownArray(downTypes[n])->getDownCells(downIds[n]); + const unsigned char* dTypes = grid->getDownArray(downTypes[n])->getDownTypes(downIds[n]); + for (int i = 0; i < nbEdges; i++) + { + int vtkEdgeId = grid->getDownArray(dTypes[i])->getVtkCellId(dEdges[i]); + if (vtkEdgeId >= 0) + sgrpei->Add(meshDS->fromVtkToSmds(vtkEdgeId)); + } + } + } + else if (neighborDim == 2) // skin of the volume + { + DownIdType face(downIds[n], downTypes[n]); + skinFaces[face] = vtkId; + int vtkFaceId = grid->getDownArray(downTypes[n])->getVtkCellId(downIds[n]); + if (vtkFaceId >= 0) + sgrps->Add(meshDS->fromVtkToSmds(vtkFaceId)); + } + } + } + + // --- identify the edges constituting the wire of each subshape on the skin + // define polylines with the nodes of edges, equivalent to wires + // project polylines on subshapes, and partition, to get geom faces + + std::map > shapeIdToVtkIdSet; // shapeId --> set of vtkId on skin + std::set emptySet; + emptySet.clear(); + std::set shapeIds; + + SMDS_ElemIteratorPtr itelem = sgrps->GetElements(); + while (itelem->more()) + { + const SMDS_MeshElement *elem = itelem->next(); + int shapeId = elem->getshapeId(); + int vtkId = elem->getVtkId(); + if (!shapeIdToVtkIdSet.count(shapeId)) + { + shapeIdToVtkIdSet[shapeId] = emptySet; + shapeIds.insert(shapeId); + } + shapeIdToVtkIdSet[shapeId].insert(vtkId); + } + + std::map > shapeIdToEdges; // shapeId --> set of downward edges + std::set emptyEdges; + emptyEdges.clear(); + + std::map >::iterator itShape = shapeIdToVtkIdSet.begin(); + for (; itShape != shapeIdToVtkIdSet.end(); ++itShape) + { + int shapeId = itShape->first; + MESSAGE(" --- Shape ID --- "<< shapeId); + shapeIdToEdges[shapeId] = emptyEdges; + + std::vector nodesEdges; + + std::set::iterator its = itShape->second.begin(); + for (; its != itShape->second.end(); ++its) + { + int vtkId = *its; + MESSAGE(" " << vtkId); + int neighborsVtkIds[NBMAXNEIGHBORS]; + int downIds[NBMAXNEIGHBORS]; + unsigned char downTypes[NBMAXNEIGHBORS]; + int nbNeighbors = grid->GetNeighbors(neighborsVtkIds, downIds, downTypes, vtkId); + for (int n = 0; n < nbNeighbors; n++) + { + if (neighborsVtkIds[n]<0) // only smds faces are considered as neighbors here + continue; + int smdsId = meshDS->fromVtkToSmds(neighborsVtkIds[n]); + const SMDS_MeshElement* elem = meshDS->FindElement(smdsId); + if ( shapeIds.count(elem->getshapeId()) && !sgrps->Contains(elem)) // edge : neighbor in the set of shape, not in the group + { + DownIdType edge(downIds[n], downTypes[n]); + if (!shapeIdToEdges[shapeId].count(edge)) + { + shapeIdToEdges[shapeId].insert(edge); + int vtkNodeId[3]; + int nbNodes = grid->getDownArray(downTypes[n])->getNodes(downIds[n],vtkNodeId); + nodesEdges.push_back(vtkNodeId[0]); + nodesEdges.push_back(vtkNodeId[nbNodes-1]); + MESSAGE(" --- nodes " << vtkNodeId[0]+1 << " " << vtkNodeId[nbNodes-1]+1); + } + } + } + } + + std::list order; + order.clear(); + if (nodesEdges.size() > 0) + { + order.push_back(nodesEdges[0]); MESSAGE(" --- back " << order.back()+1); // SMDS id = VTK id + 1; + nodesEdges[0] = -1; + order.push_back(nodesEdges[1]); MESSAGE(" --- back " << order.back()+1); + nodesEdges[1] = -1; // do not reuse this edge + bool found = true; + while (found) + { + int nodeTofind = order.back(); // try first to push back + int i = 0; + for (i = 0; i use the previous one + if (nodesEdges[i-1] < 0) + found = false; + else + { + order.push_back(nodesEdges[i-1]); MESSAGE(" --- back " << order.back()+1); + nodesEdges[i-1] = -1; + } + else // even ==> use the next one + if (nodesEdges[i+1] < 0) + found = false; + else + { + order.push_back(nodesEdges[i+1]); MESSAGE(" --- back " << order.back()+1); + nodesEdges[i+1] = -1; + } + } + if (found) + continue; + // try to push front + found = true; + nodeTofind = order.front(); // try to push front + for (i = 0; i use the previous one + if (nodesEdges[i-1] < 0) + found = false; + else + { + order.push_front(nodesEdges[i-1]); MESSAGE(" --- front " << order.front()+1); + nodesEdges[i-1] = -1; + } + else // even ==> use the next one + if (nodesEdges[i+1] < 0) + found = false; + else + { + order.push_front(nodesEdges[i+1]); MESSAGE(" --- front " << order.front()+1); + nodesEdges[i+1] = -1; + } + } + } + + + std::vector nodes; + nodes.push_back(shapeId); + std::list::iterator itl = order.begin(); + for (; itl != order.end(); itl++) + { + nodes.push_back((*itl) + 1); // SMDS id = VTK id + 1; + MESSAGE(" ordered node " << nodes[nodes.size()-1]); + } + listOfListOfNodes.push_back(nodes); + } + + // partition geom faces with blocFissure + // mesh blocFissure and geom faces of the skin (external wires given, triangle algo to choose) + // mesh volume around blocFissure (skin triangles and quadrangle given, tetra algo to choose) + + return; +} + + //================================================================================ /*! * \brief Generates skin mesh (containing 2D cells) from 3D mesh @@ -11887,7 +12512,7 @@ int SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements, missType, /*noMedium=*/false)) continue; - SMDS_MeshElement* elem = + SMDS_MeshElement* elem = tgtEditor.AddElement(nodes, missType, !iQuad && nodes.size()/(iQuad+1)>4); ++nbAddedBnd; @@ -11937,7 +12562,7 @@ int SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements, { presentEditor->myLastCreatedElems.Append(presentBndElems[i]); } - + } // loop on given elements // --------------------------------------------- diff --git a/src/SMESH/SMESH_MeshEditor.hxx b/src/SMESH/SMESH_MeshEditor.hxx index 4bd455825..1874360a7 100644 --- a/src/SMESH/SMESH_MeshEditor.hxx +++ b/src/SMESH/SMESH_MeshEditor.hxx @@ -34,6 +34,7 @@ #include "SMESH_Controls.hxx" #include "SMESH_Mesh.hxx" #include "SMESH_TypeDefs.hxx" +#include "SMESH_ComputeError.hxx" #include @@ -110,6 +111,14 @@ public: SMESH_MeshEditor( SMESH_Mesh* theMesh ); + SMESH_Mesh * GetMesh() { return myMesh; } + SMESHDS_Mesh * GetMeshDS() { return myMesh->GetMeshDS(); } + + const SMESH_SequenceOfElemPtr& GetLastCreatedNodes() const { return myLastCreatedNodes; } + const SMESH_SequenceOfElemPtr& GetLastCreatedElems() const { return myLastCreatedElems; } + + SMESH_ComputeErrorPtr & GetError() { return myError; } + /*! * \brief Add element */ @@ -561,14 +570,6 @@ public: // Return an index of the shape theElem is on // or zero if a shape not found - SMESH_Mesh * GetMesh() { return myMesh; } - - SMESHDS_Mesh * GetMeshDS() { return myMesh->GetMeshDS(); } - - const SMESH_SequenceOfElemPtr& GetLastCreatedNodes() const { return myLastCreatedNodes; } - - const SMESH_SequenceOfElemPtr& GetLastCreatedElems() const { return myLastCreatedElems; } - bool DoubleNodes( const std::list< int >& theListOfNodes, const std::list< int >& theListOfModifiedElems ); @@ -576,6 +577,11 @@ public: const TIDSortedElemSet& theNodesNot, const TIDSortedElemSet& theAffectedElems ); + bool AffectedElemGroupsInRegion( const TIDSortedElemSet& theElems, + const TIDSortedElemSet& theNodesNot, + const TopoDS_Shape& theShape, + TIDSortedElemSet& theAffectedElems); + bool DoubleNodesInRegion( const TIDSortedElemSet& theElems, const TIDSortedElemSet& theNodesNot, const TopoDS_Shape& theShape ); @@ -587,6 +593,13 @@ public: bool CreateFlatElementsOnFacesGroups( const std::vector& theElems ); + void CreateHoleSkin(double radius, + const TopoDS_Shape& theShape, + SMESH_NodeSearcher* theNodeSearcher, + const char* groupName, + std::vector& nodesCoords, + std::vector >& listOfListOfNodes); + /*! * \brief Generated skin mesh (containing 2D cells) from 3D mesh * The created 2D mesh elements based on nodes of free faces of boundary volumes @@ -709,18 +722,13 @@ public: private: - SMESH_Mesh * myMesh; + SMESH_Mesh * myMesh; - /*! - * Sequence for keeping nodes created during last operation - */ - SMESH_SequenceOfElemPtr myLastCreatedNodes; - - /*! - * Sequence for keeping elements created during last operation - */ - SMESH_SequenceOfElemPtr myLastCreatedElems; + // Nodes and elements created during last operation + SMESH_SequenceOfElemPtr myLastCreatedNodes, myLastCreatedElems; + // Description of error/warning occured during last operation + SMESH_ComputeErrorPtr myError; }; #endif diff --git a/src/SMESH/SMESH_MesherHelper.cxx b/src/SMESH/SMESH_MesherHelper.cxx index efaf7a853..ffca47e6a 100644 --- a/src/SMESH/SMESH_MesherHelper.cxx +++ b/src/SMESH/SMESH_MesherHelper.cxx @@ -26,13 +26,17 @@ // #include "SMESH_MesherHelper.hxx" -#include "SMDS_FacePosition.hxx" #include "SMDS_EdgePosition.hxx" +#include "SMDS_FaceOfNodes.hxx" +#include "SMDS_FacePosition.hxx" +#include "SMDS_IteratorOnIterators.hxx" #include "SMDS_VolumeTool.hxx" -#include "SMESH_subMesh.hxx" #include "SMESH_ProxyMesh.hxx" +#include "SMESH_subMesh.hxx" +#include #include +#include #include #include #include @@ -403,7 +407,7 @@ void SMESH_MesherHelper::AddTLinks(const SMDS_MeshVolume* volume) { int iN1 = iNodes[i++]; int iN12 = iNodes[i++]; - int iN2 = iNodes[i++]; + int iN2 = iNodes[i]; if ( iN1 > iN2 ) std::swap( iN1, iN2 ); int linkID = iN1 * vTool.NbNodes() + iN2; pair< set::iterator, bool > it_isNew = addedLinks.insert( linkID ); @@ -1675,6 +1679,24 @@ SMESH_MesherHelper::AddPolyhedralVolume (const std::vector return elem; } +namespace +{ + //================================================================================ + /*! + * \brief Check if a node belongs to any face of sub-mesh + */ + //================================================================================ + + bool isNodeInSubMesh( const SMDS_MeshNode* n, const SMESHDS_SubMesh* sm ) + { + SMDS_ElemIteratorPtr fIt = n->GetInverseElementIterator( SMDSAbs_Face ); + while ( fIt->more() ) + if ( sm->Contains( fIt->next() )) + return true; + return false; + } +} + //======================================================================= //function : LoadNodeColumns //purpose : Load nodes bound to face into a map of node columns @@ -1746,13 +1768,36 @@ bool SMESH_MesherHelper::LoadNodeColumns(TParam2ColumnMap & theParam2 SMESH_Algo::GetSortedNodesOnEdge( theMesh, *edge,/*noMedium=*/true, sortedBaseNodes); if ( sortedBaseNodes.empty() ) continue; + map< double, const SMDS_MeshNode*>::iterator u_n = sortedBaseNodes.begin(); + if ( theProxyMesh ) // from sortedBaseNodes remove nodes not shared by faces of faceSubMesh + { + const SMDS_MeshNode* n1 = sortedBaseNodes.begin()->second; + const SMDS_MeshNode* n2 = sortedBaseNodes.rbegin()->second; + bool allNodesAreProxy = ( n1 != theProxyMesh->GetProxyNode( n1 ) && + n2 != theProxyMesh->GetProxyNode( n2 )); + if ( allNodesAreProxy ) + for ( u_n = sortedBaseNodes.begin(); u_n != sortedBaseNodes.end(); u_n++ ) + u_n->second = theProxyMesh->GetProxyNode( u_n->second ); + + if ( u_n = sortedBaseNodes.begin(), !isNodeInSubMesh( u_n->second, faceSubMesh )) + { + while ( ++u_n != sortedBaseNodes.end() && !isNodeInSubMesh( u_n->second, faceSubMesh )); + sortedBaseNodes.erase( sortedBaseNodes.begin(), u_n ); + } + else if ( u_n = --sortedBaseNodes.end(), !isNodeInSubMesh( u_n->second, faceSubMesh )) + { + while ( u_n != sortedBaseNodes.begin() && !isNodeInSubMesh( (--u_n)->second, faceSubMesh )); + sortedBaseNodes.erase( ++u_n, sortedBaseNodes.end() ); + } + if ( sortedBaseNodes.empty() ) continue; + } + double f, l; BRep_Tool::Range( *edge, f, l ); if ( edge->Orientation() == TopAbs_REVERSED ) std::swap( f, l ); const double coeff = 1. / ( l - f ) * length[iE] / fullLen; const double prevPar = theParam2ColumnMap.empty() ? 0 : theParam2ColumnMap.rbegin()->first; - map< double, const SMDS_MeshNode*>::iterator u_n = sortedBaseNodes.begin(); - for ( ; u_n != sortedBaseNodes.end(); u_n++ ) + for ( u_n = sortedBaseNodes.begin(); u_n != sortedBaseNodes.end(); u_n++ ) { double par = prevPar + coeff * ( u_n->first - f ); TParam2ColumnMap::iterator u2nn = @@ -1760,21 +1805,16 @@ bool SMESH_MesherHelper::LoadNodeColumns(TParam2ColumnMap & theParam2 u2nn->second.push_back( u_n->second ); } } - TParam2ColumnMap::iterator par_nVec_2, par_nVec_1 = theParam2ColumnMap.begin(); - if ( theProxyMesh ) - { - for ( ; par_nVec_1 != theParam2ColumnMap.end(); ++par_nVec_1 ) - { - const SMDS_MeshNode* & n = par_nVec_1->second[0]; - n = theProxyMesh->GetProxyNode( n ); - } - } + if ( theParam2ColumnMap.empty() ) + return false; + int nbRows = 1 + faceSubMesh->NbElements() / ( theParam2ColumnMap.size()-1 ); // fill theParam2ColumnMap column by column by passing from nodes on // theBaseEdge up via mesh faces on theFace + TParam2ColumnMap::iterator par_nVec_1, par_nVec_2; par_nVec_2 = theParam2ColumnMap.begin(); par_nVec_1 = par_nVec_2++; TIDSortedElemSet emptySet, avoidSet; @@ -1947,6 +1987,30 @@ TopoDS_Vertex SMESH_MesherHelper::IthVertex( const bool is2nd, return ( vIt.More() ? TopoDS::Vertex(vIt.Value()) : TopoDS_Vertex() ); } +//================================================================================ +/*! + * \brief Return type of shape contained in a group + * \param group - a shape of type TopAbs_COMPOUND + * \param avoidCompound - not to return TopAbs_COMPOUND + */ +//================================================================================ + +TopAbs_ShapeEnum SMESH_MesherHelper::GetGroupType(const TopoDS_Shape& group, + const bool avoidCompound) +{ + if ( !group.IsNull() ) + { + if ( group.ShapeType() != TopAbs_COMPOUND ) + return group.ShapeType(); + + // iterate on a compound + TopoDS_Iterator it( group ); + if ( it.More() ) + return avoidCompound ? GetGroupType( it.Value() ) : it.Value().ShapeType(); + } + return TopAbs_SHAPE; +} + //======================================================================= //function : IsQuadraticMesh //purpose : Check mesh without geometry for: if all elements on this shape are quadratic, @@ -1961,6 +2025,8 @@ SMESH_MesherHelper:: MType SMESH_MesherHelper::IsQuadraticMesh() int NbFacesAndEdges=0; //All faces and edges NbAllEdgsAndFaces = myMesh->NbEdges() + myMesh->NbFaces(); + if ( NbAllEdgsAndFaces == 0 ) + return SMESH_MesherHelper::LINEAR; //Quadratic faces and edges NbQuadFacesAndEdgs = myMesh->NbEdges(ORDER_QUADRATIC) + myMesh->NbFaces(ORDER_QUADRATIC); @@ -3021,18 +3087,349 @@ namespace { // Structures used by FixQuadraticElements() return _OK; } + + //================================================================================ + /*! + * \brief Place medium nodes at the link middle for elements whose corner nodes + * are out of geometrical boundary to prevent distorting elements. + * Issue 0020982, note 0013990 + */ + //================================================================================ + + void force3DOutOfBoundary( SMESH_MesherHelper& theHelper, + SMESH_ComputeErrorPtr& theError) + { + SMESHDS_Mesh* meshDS = theHelper.GetMeshDS(); + TopoDS_Shape shape = theHelper.GetSubShape().Oriented( TopAbs_FORWARD ); + if ( shape.IsNull() ) return; + + if ( !theError ) theError = SMESH_ComputeError::New(); + + gp_XYZ faceNorm; + + if ( shape.ShapeType() == TopAbs_FACE ) // 2D + { + if ( theHelper.GetMesh()->NbTriangles( ORDER_QUADRATIC ) < 1 ) return; + + SMESHDS_SubMesh* faceSM = meshDS->MeshElements( shape ); + if ( !faceSM ) return; + + const TopoDS_Face& face = TopoDS::Face( shape ); + Handle(Geom_Surface) surface = BRep_Tool::Surface( face ); + + TopExp_Explorer edgeIt( face, TopAbs_EDGE ); + for ( ; edgeIt.More(); edgeIt.Next() ) // loop on EDGEs of a FACE + { + // check if the EDGE needs checking + const TopoDS_Edge& edge = TopoDS::Edge( edgeIt.Current() ); + if ( BRep_Tool::Degenerated( edge ) ) + continue; + if ( theHelper.IsRealSeam( edge ) && + edge.Orientation() == TopAbs_REVERSED ) + continue; + + SMESHDS_SubMesh* edgeSM = meshDS->MeshElements( edge ); + if ( !edgeSM ) continue; + + double f,l; + Handle(Geom2d_Curve) pcurve = BRep_Tool::CurveOnSurface( edge, face, f, l ); + BRepAdaptor_Curve curve3D( edge ); + switch ( curve3D.GetType() ) { + case GeomAbs_Line: continue; + case GeomAbs_Circle: + case GeomAbs_Ellipse: + case GeomAbs_Hyperbola: + case GeomAbs_Parabola: + try + { + gp_Vec D1, D2, Du1, Dv1; gp_Pnt p; + curve3D.D2( 0.5 * ( f + l ), p, D1, D2 ); + gp_Pnt2d uv = pcurve->Value( 0.5 * ( f + l ) ); + surface->D1( uv.X(), uv.Y(), p, Du1, Dv1 ); + gp_Vec fNorm = Du1 ^ Dv1; + if ( fNorm.IsParallel( D2, M_PI * 25./180. )) + continue; // face is normal to the curve3D + + gp_Vec curvNorm = fNorm ^ D1; + if ( edge.Orientation() == TopAbs_REVERSED ) curvNorm.Reverse(); + if ( curvNorm * D2 > 0 ) + continue; // convex edge + } + catch ( Standard_Failure ) + { + continue; + } + } + // get nodes shared by faces that may be distorted + SMDS_NodeIteratorPtr nodeIt; + if ( edgeSM->NbNodes() > 0 ) { + nodeIt = edgeSM->GetNodes(); + } + else { + SMESHDS_SubMesh* vertexSM = meshDS->MeshElements( theHelper.IthVertex( 0, edge )); + if ( !vertexSM ) + vertexSM = meshDS->MeshElements( theHelper.IthVertex( 1, edge )); + if ( !vertexSM ) continue; + nodeIt = vertexSM->GetNodes(); + } + + // find suspicious faces + TIDSortedElemSet checkedFaces; + vector< const SMDS_MeshNode* > nOnEdge( 2 ); + const SMDS_MeshNode* nOnFace; + while ( nodeIt->more() ) + { + const SMDS_MeshNode* n = nodeIt->next(); + SMDS_ElemIteratorPtr faceIt = n->GetInverseElementIterator( SMDSAbs_Face ); + while ( faceIt->more() ) + { + const SMDS_MeshElement* f = faceIt->next(); + if ( !faceSM->Contains( f ) || + f->NbNodes() != 6 || // check quadratic triangles only + !checkedFaces.insert( f ).second ) + continue; + + // get nodes on EDGE and on FACE of a suspicious face + nOnEdge.clear(); nOnFace = 0; + SMDS_MeshElement::iterator triNode = f->begin_nodes(); + for ( int nbN = 0; nbN < 3; ++triNode, ++nbN ) + { + n = *triNode; + if ( n->GetPosition()->GetDim() == 2 ) + nOnFace = n; + else + nOnEdge.push_back( n ); + } + + // check if nOnFace is inside the FACE + if ( nOnFace && nOnEdge.size() == 2 ) + { + theHelper.AddTLinks( static_cast< const SMDS_MeshFace* > ( f )); + if ( !SMESH_Algo::FaceNormal( f, faceNorm, /*normalized=*/false )) + continue; + gp_XYZ edgeDir = SMESH_TNodeXYZ( nOnEdge[0] ) - SMESH_TNodeXYZ( nOnEdge[1] ); + gp_XYZ edgeNorm = faceNorm ^ edgeDir; + n = theHelper.GetMediumNode( nOnEdge[0], nOnEdge[1], true ); + gp_XYZ pN0 = SMESH_TNodeXYZ( nOnEdge[0] ); + gp_XYZ pMedium = SMESH_TNodeXYZ( n ); // on-edge node location + gp_XYZ pFaceN = SMESH_TNodeXYZ( nOnFace ); // on-face node location + double hMedium = edgeNorm * gp_Vec( pN0, pMedium ).XYZ(); + double hFace = edgeNorm * gp_Vec( pN0, pFaceN ).XYZ(); + if ( Abs( hMedium ) > Abs( hFace * 0.6 )) + { + // nOnFace is out of FACE, move a medium on-edge node to the middle + gp_XYZ pMid3D = 0.5 * ( pN0 + SMESH_TNodeXYZ( nOnEdge[1] )); + meshDS->MoveNode( n, pMid3D.X(), pMid3D.Y(), pMid3D.Z() ); + MSG( "move OUT of face " << n ); + theError->myBadElements.push_back( f ); + } + } + } + } + } + if ( !theError->myBadElements.empty() ) + theError->myName = EDITERR_NO_MEDIUM_ON_GEOM; + return; + + } // 2D ============================================================================== + + if ( shape.ShapeType() == TopAbs_SOLID ) // 3D + { + if ( theHelper.GetMesh()->NbTetras ( ORDER_QUADRATIC ) < 1 && + theHelper.GetMesh()->NbPyramids( ORDER_QUADRATIC ) < 1 ) return; + + SMESHDS_SubMesh* solidSM = meshDS->MeshElements( shape ); + if ( !solidSM ) return; + + // check if the SOLID is bound by concave FACEs + vector< TopoDS_Face > concaveFaces; + TopExp_Explorer faceIt( shape, TopAbs_FACE ); + for ( ; faceIt.More(); faceIt.Next() ) // loop on FACEs of a SOLID + { + const TopoDS_Face& face = TopoDS::Face( faceIt.Current() ); + if ( !meshDS->MeshElements( face )) continue; + + BRepAdaptor_Surface surface( face ); + switch ( surface.GetType() ) { + case GeomAbs_Plane: continue; + case GeomAbs_Cylinder: + case GeomAbs_Cone: + case GeomAbs_Sphere: + try + { + double u = 0.5 * ( surface.FirstUParameter() + surface.LastUParameter() ); + double v = 0.5 * ( surface.FirstVParameter() + surface.LastVParameter() ); + gp_Vec Du1, Dv1, Du2, Dv2, Duv2; gp_Pnt p; + surface.D2( u,v, p, Du1, Dv1, Du2, Dv2, Duv2 ); + gp_Vec fNorm = Du1 ^ Dv1; + if ( face.Orientation() == TopAbs_REVERSED ) fNorm.Reverse(); + bool concaveU = ( fNorm * Du2 > 1e-100 ); + bool concaveV = ( fNorm * Dv2 > 1e-100 ); + if ( concaveU || concaveV ) + concaveFaces.push_back( face ); + } + catch ( Standard_Failure ) + { + concaveFaces.push_back( face ); + } + } + } + if ( concaveFaces.empty() ) + return; + + // fix 2D mesh on the SOLID + for ( faceIt.ReInit(); faceIt.More(); faceIt.Next() ) // loop on FACEs of a SOLID + { + SMESH_MesherHelper faceHelper( *theHelper.GetMesh() ); + faceHelper.SetSubShape( faceIt.Current() ); + force3DOutOfBoundary( faceHelper, theError ); + } + + // get an iterator over faces on concaveFaces + vector< SMDS_ElemIteratorPtr > faceIterVec( concaveFaces.size() ); + for ( size_t i = 0; i < concaveFaces.size(); ++i ) + faceIterVec[i] = meshDS->MeshElements( concaveFaces[i] )->GetElements(); + typedef SMDS_IteratorOnIterators + < const SMDS_MeshElement*, vector< SMDS_ElemIteratorPtr > > TIterOnIter; + SMDS_ElemIteratorPtr faceIter( new TIterOnIter( faceIterVec )); + + // a seacher to check if a volume is close to a concave face + std::auto_ptr< SMESH_ElementSearcher > faceSearcher + ( SMESH_MeshEditor( theHelper.GetMesh() ).GetElementSearcher( faceIter )); + + // classifier + //BRepClass3d_SolidClassifier solidClassifier( shape ); + + TIDSortedElemSet checkedVols, movedNodes; + for ( faceIt.ReInit(); faceIt.More(); faceIt.Next() ) // loop on FACEs of a SOLID + { + const TopoDS_Shape& face = faceIt.Current(); + SMESHDS_SubMesh* faceSM = meshDS->MeshElements( face ); + if ( !faceSM ) continue; + + // get nodes shared by volumes (tet and pyra) on the FACE that may be distorted + SMDS_NodeIteratorPtr nodeIt; + if ( faceSM->NbNodes() > 0 ) { + nodeIt = faceSM->GetNodes(); + } + else { + TopExp_Explorer vertex( face, TopAbs_VERTEX ); + SMESHDS_SubMesh* vertexSM = meshDS->MeshElements( vertex.Current() ); + if ( !vertexSM ) continue; + nodeIt = vertexSM->GetNodes(); + } + + // find suspicious volumes adjacent to the FACE + vector< const SMDS_MeshNode* > nOnFace( 4 ); + const SMDS_MeshNode* nInSolid; + //vector< const SMDS_MeshElement* > intersectedFaces; + while ( nodeIt->more() ) + { + const SMDS_MeshNode* n = nodeIt->next(); + SMDS_ElemIteratorPtr volIt = n->GetInverseElementIterator( SMDSAbs_Volume ); + while ( volIt->more() ) + { + const SMDS_MeshElement* vol = volIt->next(); + int nbN = vol->NbCornerNodes(); + if ( ( nbN != 4 && nbN != 5 ) || + !solidSM->Contains( vol ) || + !checkedVols.insert( vol ).second ) + continue; + + // get nodes on FACE and in SOLID of a suspicious volume + nOnFace.clear(); nInSolid = 0; + SMDS_MeshElement::iterator volNode = vol->begin_nodes(); + for ( int nb = nbN; nb > 0; ++volNode, --nb ) + { + n = *volNode; + if ( n->GetPosition()->GetDim() == 3 ) + nInSolid = n; + else + nOnFace.push_back( n ); + } + if ( !nInSolid || nOnFace.size() != nbN - 1 ) + continue; + + // get size of the vol + SMESH_TNodeXYZ pInSolid( nInSolid ), pOnFace0( nOnFace[0] ); + double volLength = pInSolid.SquareDistance( nOnFace[0] ); + for ( size_t i = 1; i < nOnFace.size(); ++i ) + { + volLength = Max( volLength, pOnFace0.SquareDistance( nOnFace[i] )); + } + + // check if vol is close to concaveFaces + const SMDS_MeshElement* closeFace = + faceSearcher->FindClosestTo( pInSolid, SMDSAbs_Face ); + if ( !closeFace || + pInSolid.SquareDistance( closeFace->GetNode(0) ) > 4 * volLength ) + continue; + + // check if vol is distorted, i.e. a medium node is much closer + // to nInSolid than the link middle + bool isDistorted = false; + SMDS_FaceOfNodes onFaceTria( nOnFace[0], nOnFace[1], nOnFace[2] ); + if ( !SMESH_Algo::FaceNormal( &onFaceTria, faceNorm, /*normalized=*/false )) + continue; + theHelper.AddTLinks( static_cast< const SMDS_MeshVolume* > ( vol )); + vector< pair< SMESH_TLink, const SMDS_MeshNode* > > links; + for ( size_t i = 0; i < nOnFace.size(); ++i ) // loop on links between nOnFace + for ( size_t j = i+1; j < nOnFace.size(); ++j ) + { + SMESH_TLink link( nOnFace[i], nOnFace[j] ); + TLinkNodeMap::const_iterator linkIt = + theHelper.GetTLinkNodeMap().find( link ); + if ( linkIt != theHelper.GetTLinkNodeMap().end() ) + { + links.push_back( make_pair( linkIt->first, linkIt->second )); + if ( !isDistorted ) { + // compare projections of nInSolid and nMedium to face normal + gp_Pnt pMedium = SMESH_TNodeXYZ( linkIt->second ); + double hMedium = faceNorm * gp_Vec( pOnFace0, pMedium ).XYZ(); + double hVol = faceNorm * gp_Vec( pOnFace0, pInSolid ).XYZ(); + isDistorted = ( Abs( hMedium ) > Abs( hVol * 0.5 )); + } + } + } + // move medium nodes to link middle + if ( isDistorted ) + { + for ( size_t i = 0; i < links.size(); ++i ) + { + const SMDS_MeshNode* nMedium = links[i].second; + if ( movedNodes.insert( nMedium ).second ) + { + gp_Pnt pMid3D = 0.5 * ( SMESH_TNodeXYZ( links[i].first.node1() ) + + SMESH_TNodeXYZ( links[i].first.node2() )); + meshDS->MoveNode( nMedium, pMid3D.X(), pMid3D.Y(), pMid3D.Z() ); + MSG( "move OUT of solid " << nMedium ); + } + } + theError->myBadElements.push_back( vol ); + } + } // loop on volumes sharing a node on FACE + } // loop on nodes on FACE + } // loop on FACEs of a SOLID + + if ( !theError->myBadElements.empty() ) + theError->myName = EDITERR_NO_MEDIUM_ON_GEOM; + } // 3D case + } + } //namespace //======================================================================= /*! * \brief Move medium nodes of faces and volumes to fix distorted elements + * \param error - container of fixed distorted elements * \param volumeOnly - to fix nodes on faces or not, if the shape is solid * * Issue 0020307: EDF 992 SMESH : Linea/Quadratic with Medium Node on Geometry */ //======================================================================= -void SMESH_MesherHelper::FixQuadraticElements(bool volumeOnly) +void SMESH_MesherHelper::FixQuadraticElements(SMESH_ComputeErrorPtr& error, + bool volumeOnly) { // setenv NO_FixQuadraticElements to know if FixQuadraticElements() is guilty of bad conversion if ( getenv("NO_FixQuadraticElements") ) @@ -3065,7 +3462,7 @@ void SMESH_MesherHelper::FixQuadraticElements(bool volumeOnly) #endif SMESH_MesherHelper h(*myMesh); h.SetSubShape( s.Current() ); - h.FixQuadraticElements(false); + h.FixQuadraticElements( error, false ); } } // fix nodes on geom faces @@ -3076,10 +3473,13 @@ void SMESH_MesherHelper::FixQuadraticElements(bool volumeOnly) MSG("FIX FACE " << nbfaces-- << " #" << GetMeshDS()->ShapeToIndex(fIt.Key())); SMESH_MesherHelper h(*myMesh); h.SetSubShape( fIt.Key() ); - h.FixQuadraticElements(true); + h.FixQuadraticElements( error, true); h.ToFixNodeParameters(true); } //perf_print_all_meters(1); + if ( error && error->myName == EDITERR_NO_MEDIUM_ON_GEOM ) + error->myComment = "during conversion to quadratic, " + "some medium nodes were not placed on geometry to avoid distorting elements"; return; } @@ -3118,6 +3518,11 @@ void SMESH_MesherHelper::FixQuadraticElements(bool volumeOnly) TIDSortedNodeSet apexOfPyramid; const int apexIndex = 4; + // Issue 0020982 + // Move medium nodes to the link middle for elements whose corner nodes + // are out of geometrical boundary to fix distorted elements. + force3DOutOfBoundary( *this, error ); + if ( elemType == SMDSAbs_Volume ) { while ( elemIt->more() ) // loop on volumes @@ -3392,109 +3797,73 @@ void SMESH_MesherHelper::FixQuadraticElements(bool volumeOnly) } // loop on chains of links } // loop on 2 directions of propagation from quadrangle } // loop on faces - } + } // fix faces and/or volumes // 4. Move nodes // ------------- -// vector vols( 100 ); -// vector volSize( 100 ); -// int nbVols; -// bool ok; for ( pLink = links.begin(); pLink != links.end(); ++pLink ) { if ( pLink->IsMoved() ) { gp_Pnt p = pLink->MiddlePnt() + pLink->Move(); GetMeshDS()->MoveNode( pLink->_mediumNode, p.X(), p.Y(), p.Z()); - // -// gp_Pnt pNew = pLink->MiddlePnt() + pLink->Move(); -// if ( pLink->MediumPos() != SMDS_TOP_3DSPACE ) -// { -// // avoid making distorted volumes near boundary -// SMDS_ElemIteratorPtr volIt = -// (*pLink)._mediumNode->GetInverseElementIterator( SMDSAbs_Volume ); -// for ( nbVols = 0; volIt->more() && volTool.Set( volIt->next() ); ++nbVols ) -// { -// vols [ nbVols ] = volTool.Element(); -// volSize[ nbVols ] = volTool.GetSize(); -// } -// gp_Pnt pOld = pLink->MediumPnt(); -// const_cast( pLink->_mediumNode )->setXYZ( pNew.X(), pNew.Y(), pNew.Z() ); -// ok = true; -// while ( nbVols-- && ok ) -// { -// volTool.Set( vols[ nbVols ]); -// ok = ( volSize[ nbVols ] * volTool.GetSize() > 1e-20 ); -// } -// if ( !ok ) -// { -// const_cast( pLink->_mediumNode )->setXYZ( pOld.X(), pOld.Y(), pOld.Z() ); -// MSG( "Do NOT move \t" << pLink->_mediumNode->GetID() -// << " because of distortion of volume " << vols[ nbVols+1 ]->GetID()); -// continue; -// } -// } -// GetMeshDS()->MoveNode( pLink->_mediumNode, pNew.X(), pNew.Y(), pNew.Z() ); - } - } - - //return; - - // issue 0020982 - // Move the apex of pyramid together with the most curved link - - TIDSortedNodeSet::iterator apexIt = apexOfPyramid.begin(); - for ( ; apexIt != apexOfPyramid.end(); ++apexIt ) - { - SMESH_TNodeXYZ apex = *apexIt; - - gp_Vec maxMove( 0,0,0 ); - double maxMoveSize2 = 0; - - // shift of node index to get medium nodes between the base nodes - const int base2MediumShift = 5; - - // find maximal movement of medium node - SMDS_ElemIteratorPtr volIt = apex._node->GetInverseElementIterator( SMDSAbs_Volume ); - vector< const SMDS_MeshElement* > pyramids; - while ( volIt->more() ) - { - const SMDS_MeshElement* pyram = volIt->next(); - if ( pyram->GetEntityType() != SMDSEntity_Quad_Pyramid ) continue; - pyramids.push_back( pyram ); - - for ( int iBase = 0; iBase < apexIndex; ++iBase ) - { - SMESH_TNodeXYZ medium = pyram->GetNode( iBase + base2MediumShift ); - if ( medium._node->GetPosition()->GetTypeOfPosition() != SMDS_TOP_3DSPACE ) - { - SMESH_TNodeXYZ n1 = pyram->GetNode( iBase ); - SMESH_TNodeXYZ n2 = pyram->GetNode( ( iBase+1 ) % 4 ); - gp_Pnt middle = 0.5 * ( n1 + n2 ); - gp_Vec move( middle, medium ); - double moveSize2 = move.SquareMagnitude(); - if ( moveSize2 > maxMoveSize2 ) - maxMove = move, maxMoveSize2 = moveSize2; - } - } - } - - // move the apex - if ( maxMoveSize2 > 1e-20 ) - { - apex += maxMove.XYZ(); - GetMeshDS()->MoveNode( apex._node, apex.X(), apex.Y(), apex.Z()); - - // move medium nodes neighboring the apex to the middle - const int base2MediumShift_2 = 9; - for ( unsigned i = 0; i < pyramids.size(); ++i ) - for ( int iBase = 0; iBase < apexIndex; ++iBase ) - { - SMESH_TNodeXYZ base = pyramids[i]->GetNode( iBase ); - const SMDS_MeshNode* medium = pyramids[i]->GetNode( iBase + base2MediumShift_2 ); - gp_XYZ middle = 0.5 * ( apex + base ); - GetMeshDS()->MoveNode( medium, middle.X(), middle.Y(), middle.Z()); - } } } + + // Issue 0020982 + // Move the apex of pyramid together with the most curved link. + // TIDSortedNodeSet::iterator apexIt = apexOfPyramid.begin(); + // for ( ; apexIt != apexOfPyramid.end(); ++apexIt ) + // { + // SMESH_TNodeXYZ apex = *apexIt; + + // gp_Vec maxMove( 0,0,0 ); + // double maxMoveSize2 = 0; + + // // shift of node index to get medium nodes between the base nodes + // const int base2MediumShift = 5; + + // // find maximal movement of medium node + // SMDS_ElemIteratorPtr volIt = apex._node->GetInverseElementIterator( SMDSAbs_Volume ); + // vector< const SMDS_MeshElement* > pyramids; + // while ( volIt->more() ) + // { + // const SMDS_MeshElement* pyram = volIt->next(); + // if ( pyram->GetEntityType() != SMDSEntity_Quad_Pyramid ) continue; + // pyramids.push_back( pyram ); + + // for ( int iBase = 0; iBase < apexIndex; ++iBase ) + // { + // SMESH_TNodeXYZ medium = pyram->GetNode( iBase + base2MediumShift ); + // if ( medium._node->GetPosition()->GetTypeOfPosition() != SMDS_TOP_3DSPACE ) + // { + // SMESH_TNodeXYZ n1 = pyram->GetNode( iBase ); + // SMESH_TNodeXYZ n2 = pyram->GetNode( ( iBase+1 ) % 4 ); + // gp_Pnt middle = 0.5 * ( n1 + n2 ); + // gp_Vec move( middle, medium ); + // double moveSize2 = move.SquareMagnitude(); + // if ( moveSize2 > maxMoveSize2 ) + // maxMove = move, maxMoveSize2 = moveSize2; + // } + // } + // } + + // // move the apex + // if ( maxMoveSize2 > 1e-20 ) + // { + // apex += maxMove.XYZ(); + // GetMeshDS()->MoveNode( apex._node, apex.X(), apex.Y(), apex.Z()); + + // // move medium nodes neighboring the apex to the middle + // const int base2MediumShift_2 = 9; + // for ( unsigned i = 0; i < pyramids.size(); ++i ) + // for ( int iBase = 0; iBase < apexIndex; ++iBase ) + // { + // SMESH_TNodeXYZ base = pyramids[i]->GetNode( iBase ); + // const SMDS_MeshNode* medium = pyramids[i]->GetNode( iBase + base2MediumShift_2 ); + // gp_XYZ middle = 0.5 * ( apex + base ); + // GetMeshDS()->MoveNode( medium, middle.X(), middle.Y(), middle.Z()); + // } + // } + // } } diff --git a/src/SMESH/SMESH_MesherHelper.hxx b/src/SMESH/SMESH_MesherHelper.hxx index c74dfb858..da6cfcbfb 100644 --- a/src/SMESH/SMESH_MesherHelper.hxx +++ b/src/SMESH/SMESH_MesherHelper.hxx @@ -164,6 +164,9 @@ public: static TopoDS_Vertex IthVertex( const bool is2nd, TopoDS_Edge anEdge, const bool CumOri=true ); + static TopAbs_ShapeEnum GetGroupType(const TopoDS_Shape& group, + const bool avoidCompound=false); + public: // ---------- PUBLIC INSTANCE METHODS ---------- @@ -192,9 +195,10 @@ public: /*! * \brief Move medium nodes of faces and volumes to fix distorted elements + * \param error - container of fixed distorted elements * \param volumeOnly - fix nodes on geom faces or not if the shape is solid */ - void FixQuadraticElements(bool volumeOnly=true); + void FixQuadraticElements(SMESH_ComputeErrorPtr& error, bool volumeOnly=true); /*! * \brief To set created elements on the shape set by IsQuadraticSubMesh() diff --git a/src/SMESH/SMESH_subMesh.cxx b/src/SMESH/SMESH_subMesh.cxx index 65ffac712..d048ce2b0 100644 --- a/src/SMESH/SMESH_subMesh.cxx +++ b/src/SMESH/SMESH_subMesh.cxx @@ -406,6 +406,10 @@ const map < int, SMESH_subMesh * >& SMESH_subMesh::DependsOn() { insertDependence(exp.Current()); } + for (TopExp_Explorer exp(_subShape, TopAbs_VERTEX, TopAbs_EDGE); exp.More();exp.Next()) + { + insertDependence(exp.Current()); + } break; } case TopAbs_COMPSOLID: @@ -1462,16 +1466,18 @@ bool SMESH_subMesh::ComputeStateEngine(int event) else ret = false; } + // check if an error reported on any sub-shape + bool isComputeErrorSet = !checkComputeError( algo, ret, shape ); + // check if anything was built TopExp_Explorer subS(shape, _subShape.ShapeType()); - if (ret) // check if anything was built + if (ret) { for (; ret && subS.More(); subS.Next()) ret = _father->GetSubMesh( subS.Current() )->IsMeshComputed(); } - bool isComputeErrorSet = !checkComputeError( algo, shape ); + // Set _computeError if (!ret && !isComputeErrorSet) { - // Set _computeError for (subS.ReInit(); subS.More(); subS.Next()) { SMESH_subMesh* sm = _father->GetSubMesh( subS.Current() ); @@ -1723,7 +1729,9 @@ bool SMESH_subMesh::Evaluate(MapShapeNbElems& aResMap) */ //======================================================================= -bool SMESH_subMesh::checkComputeError(SMESH_Algo* theAlgo, const TopoDS_Shape& theShape) +bool SMESH_subMesh::checkComputeError(SMESH_Algo* theAlgo, + const bool theComputeOK, + const TopoDS_Shape& theShape) { bool noErrors = true; @@ -1734,7 +1742,7 @@ bool SMESH_subMesh::checkComputeError(SMESH_Algo* theAlgo, const TopoDS_Shape& t { SMESH_subMeshIteratorPtr smIt = getDependsOnIterator(false,false); while ( smIt->more() ) - if ( !smIt->next()->checkComputeError( theAlgo )) + if ( !smIt->next()->checkComputeError( theAlgo, theComputeOK )) noErrors = false; } @@ -1746,7 +1754,7 @@ bool SMESH_subMesh::checkComputeError(SMESH_Algo* theAlgo, const TopoDS_Shape& t for (TopoDS_Iterator subIt( theShape ); subIt.More(); subIt.Next()) { SMESH_subMesh* sm = _father->GetSubMesh( subIt.Value() ); if ( sm != this ) { - if ( !sm->checkComputeError( theAlgo, sm->GetSubShape() )) + if ( !sm->checkComputeError( theAlgo, theComputeOK, sm->GetSubShape() )) noErrors = false; updateDependantsState( SUBMESH_COMPUTED ); // send event SUBMESH_COMPUTED } @@ -1754,13 +1762,24 @@ bool SMESH_subMesh::checkComputeError(SMESH_Algo* theAlgo, const TopoDS_Shape& t } } { - // Check my state + + // Set my _computeState + if ( !_computeError || _computeError->IsOK() ) { // no error description is set to this sub-mesh, check if any mesh is computed _computeState = IsMeshComputed() ? COMPUTE_OK : FAILED_TO_COMPUTE; + if ( _computeState != COMPUTE_OK ) + { + if ( _subShape.ShapeType() == TopAbs_EDGE && + BRep_Tool::Degenerated( TopoDS::Edge( _subShape )) ) + _computeState = COMPUTE_OK; + else if ( theComputeOK ) + _computeError = SMESH_ComputeError::New(COMPERR_NO_MESH_ON_SHAPE,"",theAlgo); + } } - else + + if ( _computeError && !_computeError->IsOK() ) { if ( !_computeError->myAlgo ) _computeError->myAlgo = theAlgo; @@ -2078,6 +2097,23 @@ EventListenerData* SMESH_subMesh::GetEventListenerData(EventListener* listener) return 0; } +//================================================================================ +/*! + * \brief Return an event listener data + * \param listenerName - the listener name + * \retval EventListenerData* - found data, maybe NULL + */ +//================================================================================ + +EventListenerData* SMESH_subMesh::GetEventListenerData(const string& listenerName) const +{ + map< EventListener*, EventListenerData* >::const_iterator l_d = _eventListeners.begin(); + for ( ; l_d != _eventListeners.end(); ++l_d ) + if ( listenerName == l_d->first->GetName() ) + return l_d->second; + return 0; +} + //================================================================================ /*! * \brief Notify stored event listeners on the occured event @@ -2118,8 +2154,15 @@ void SMESH_subMesh::DeleteEventListener(EventListener* listener) map< EventListener*, EventListenerData* >::iterator l_d = _eventListeners.find( listener ); if ( l_d != _eventListeners.end() ) { - if ( l_d->first && l_d->first->IsDeletable() ) delete l_d->first; - if ( l_d->second && l_d->second->IsDeletable() ) delete l_d->second; + if ( l_d->first && l_d->first->IsDeletable() ) + { + l_d->first->BeforeDelete( this, l_d->second ); + delete l_d->first; + } + if ( l_d->second && l_d->second->IsDeletable() ) + { + delete l_d->second; + } _eventListeners.erase( l_d ); } } diff --git a/src/SMESH/SMESH_subMesh.hxx b/src/SMESH/SMESH_subMesh.hxx index ee4b96658..057f532a7 100644 --- a/src/SMESH/SMESH_subMesh.hxx +++ b/src/SMESH/SMESH_subMesh.hxx @@ -138,6 +138,13 @@ class SMESH_EXPORT SMESH_subMesh */ EventListenerData* GetEventListenerData(EventListener* listener) const; + /*! + * \brief Return an event listener data + * \param listenerName - the listener name + * \retval EventListenerData* - found data, maybe NULL + */ + EventListenerData* GetEventListenerData(const std::string& listenerName) const; + /*! * \brief Unregister the listener and delete it and it's data * \param listener - the event listener to delete @@ -278,7 +285,9 @@ protected: * \brief Update compute_state by _computeError * \retval bool - false if there are errors */ - bool checkComputeError(SMESH_Algo* theAlgo, const TopoDS_Shape& theShape=TopoDS_Shape()); + bool checkComputeError(SMESH_Algo* theAlgo, + const bool theComputeOK, + const TopoDS_Shape& theShape=TopoDS_Shape()); /*! * \brief Return a hypothesis attached to theShape. diff --git a/src/SMESH/SMESH_subMeshEventListener.hxx b/src/SMESH/SMESH_subMeshEventListener.hxx index ae911cfef..bbba78702 100644 --- a/src/SMESH/SMESH_subMeshEventListener.hxx +++ b/src/SMESH/SMESH_subMeshEventListener.hxx @@ -46,18 +46,18 @@ class SMESH_EXPORT SMESH_subMeshEventListener { bool myIsDeletable; //!< if true, it will be deleted by SMESH_subMesh mutable std::set myBusySM; //!< to avoid infinite recursion via events + const char* myName; //!< identifier friend class SMESH_subMesh; -#ifdef _DEBUG_ - const char* myName; //!< identifier used for debug -#endif public: - SMESH_subMeshEventListener(bool isDeletable, const char* name) :myIsDeletable(isDeletable) -#ifdef _DEBUG_ - ,myName(name) -#endif + SMESH_subMeshEventListener(bool isDeletable, const char* name) + :myIsDeletable(isDeletable), myName(name) {} + virtual ~SMESH_subMeshEventListener() {} + bool IsDeletable() const { return myIsDeletable; } + const char* GetName() const { return myName; } + virtual void BeforeDelete(SMESH_subMesh* subMesh, + SMESH_subMeshEventListenerData* data) {} - bool IsDeletable() const { return myIsDeletable; } /*! * \brief Do something on a certain event * \param event - algo_event or compute_event itself (of SMESH_subMesh) diff --git a/src/SMESHClient/Makefile.am b/src/SMESHClient/Makefile.am index d89d95fa1..7e3902eec 100644 --- a/src/SMESHClient/Makefile.am +++ b/src/SMESHClient/Makefile.am @@ -57,6 +57,7 @@ libSMESHClient_la_CPPFLAGS = \ -I$(srcdir)/../SMDS \ -I$(srcdir)/../SMESHDS \ -I$(srcdir)/../SMESH \ + -I$(srcdir)/../SMESHUtils \ -I$(top_builddir)/idl libSMESHClient_la_LDFLAGS = \ diff --git a/src/SMESHDS/SMESHDS_Document.hxx b/src/SMESHDS/SMESHDS_Document.hxx index 182581256..4b7f1fcd1 100644 --- a/src/SMESHDS/SMESHDS_Document.hxx +++ b/src/SMESHDS/SMESHDS_Document.hxx @@ -38,27 +38,27 @@ class SMESHDS_EXPORT SMESHDS_Document { public: SMESHDS_Document(int UserID); - int NewMesh(bool theIsEmbeddedMode); - void RemoveMesh(int MeshID); - SMESHDS_Mesh * GetMesh(int MeshID); - void AddHypothesis(SMESHDS_Hypothesis * H); - void RemoveHypothesis(int HypID); + ~SMESHDS_Document(); + int NewMesh(bool theIsEmbeddedMode); + void RemoveMesh(int MeshID); + SMESHDS_Mesh * GetMesh(int MeshID); + void AddHypothesis(SMESHDS_Hypothesis * H); + void RemoveHypothesis(int HypID); SMESHDS_Hypothesis * GetHypothesis(int HypID); - int NbMeshes(); - int NbHypothesis(); - void InitMeshesIterator(); - SMESHDS_Mesh * NextMesh(); - bool MoreMesh(); - void InitHypothesisIterator(); + int NbMeshes(); + int NbHypothesis(); + void InitMeshesIterator(); + SMESHDS_Mesh * NextMesh(); + bool MoreMesh(); + void InitHypothesisIterator(); SMESHDS_Hypothesis * NextHypothesis(); - bool MoreHypothesis(); - ~SMESHDS_Document(); + bool MoreHypothesis(); private: - int myUserID; - std::map myMeshes; - std::map myHypothesis; - std::map::iterator myMeshesIt; + int myUserID; + std::map myMeshes; + std::map myHypothesis; + std::map::iterator myMeshesIt; std::map::iterator myHypothesisIt; }; diff --git a/src/SMESHDS/SMESHDS_Hypothesis.hxx b/src/SMESHDS/SMESHDS_Hypothesis.hxx index d819684af..85e115c05 100644 --- a/src/SMESHDS/SMESHDS_Hypothesis.hxx +++ b/src/SMESHDS/SMESHDS_Hypothesis.hxx @@ -24,7 +24,6 @@ // File : SMESHDS_Hypothesis.hxx // Author : Paul RASCLE, EDF // Module : SMESH -// $Header$ // #ifndef _SMESHDS_HYPOTHESIS_HXX_ #define _SMESHDS_HYPOTHESIS_HXX_ @@ -36,7 +35,7 @@ class SMESHDS_EXPORT SMESHDS_Hypothesis { -public: + public: SMESHDS_Hypothesis(int hypId); virtual ~SMESHDS_Hypothesis(); @@ -50,12 +49,12 @@ public: virtual bool operator==(const SMESHDS_Hypothesis& other) const; bool operator!=(const SMESHDS_Hypothesis& other) const { return !(*this==other); } -enum hypothesis_type {PARAM_ALGO, ALGO_0D, ALGO_1D, ALGO_2D, ALGO_3D}; + enum hypothesis_type { PARAM_ALGO, ALGO_0D, ALGO_1D, ALGO_2D, ALGO_3D }; -protected: - std::string _name; - int _hypId; - int _type; + protected: + std::string _name; // identifier if hypothesis type + int _hypId; // ID unique within application session + int _type; // enum hypothesis_type }; #endif diff --git a/src/SMESHGUI/Makefile.am b/src/SMESHGUI/Makefile.am index 15925385f..9bfd599b3 100644 --- a/src/SMESHGUI/Makefile.am +++ b/src/SMESHGUI/Makefile.am @@ -49,7 +49,6 @@ salomeinclude_HEADERS = \ SMESHGUI_RemoveElementsDlg.h \ SMESHGUI_MeshInfo.h \ SMESHGUI_Measurements.h \ - SMESHGUI_Preferences_ColorDlg.h \ SMESHGUI_Preferences_ScalarBarDlg.h \ SMESHGUI_AddMeshElementDlg.h \ SMESHGUI_XmlHandler.h \ @@ -97,6 +96,7 @@ salomeinclude_HEADERS = \ SMESHGUI_CopyMeshDlg.h \ SMESHGUI_PreviewDlg.h \ SMESHGUI_ReorientFacesDlg.h \ + SMESHGUI_PropertiesDlg.h \ SMESH_SMESHGUI.hxx # Libraries targets @@ -115,7 +115,6 @@ dist_libSMESH_la_SOURCES = \ SMESHGUI_RemoveElementsDlg.cxx \ SMESHGUI_MeshInfo.cxx \ SMESHGUI_Measurements.cxx \ - SMESHGUI_Preferences_ColorDlg.cxx \ SMESHGUI_Preferences_ScalarBarDlg.cxx \ SMESHGUI_AddMeshElementDlg.cxx \ SMESHGUI_XmlHandler.cxx \ @@ -173,7 +172,8 @@ dist_libSMESH_la_SOURCES = \ SMESHGUI_CopyMeshDlg.cxx \ SMESHGUI_FileValidator.cxx \ SMESHGUI_PreviewDlg.cxx \ - SMESHGUI_ReorientFacesDlg.cxx + SMESHGUI_ReorientFacesDlg.cxx \ + SMESHGUI_PropertiesDlg.cxx MOC_FILES = \ SMESHGUI_moc.cxx \ @@ -189,7 +189,6 @@ MOC_FILES = \ SMESHGUI_RemoveElementsDlg_moc.cxx \ SMESHGUI_MeshInfo_moc.cxx \ SMESHGUI_Measurements_moc.cxx \ - SMESHGUI_Preferences_ColorDlg_moc.cxx \ SMESHGUI_Preferences_ScalarBarDlg_moc.cxx \ SMESHGUI_AddMeshElementDlg_moc.cxx \ SMESHGUI_FilterDlg_moc.cxx \ @@ -233,7 +232,8 @@ MOC_FILES = \ SMESHGUI_CopyMeshDlg_moc.cxx \ SMESHGUI_MeshOrderOp_moc.cxx \ SMESHGUI_PreviewDlg_moc.cxx \ - SMESHGUI_ReorientFacesDlg_moc.cxx + SMESHGUI_ReorientFacesDlg_moc.cxx \ + SMESHGUI_PropertiesDlg_moc.cxx nodist_libSMESH_la_SOURCES= \ $(MOC_FILES) diff --git a/src/SMESHGUI/SMESHGUI.cxx b/src/SMESHGUI/SMESHGUI.cxx index 52f3180ad..28df5fdbf 100644 --- a/src/SMESHGUI/SMESHGUI.cxx +++ b/src/SMESHGUI/SMESHGUI.cxx @@ -59,8 +59,8 @@ #include "SMESHGUI_MeshPatternDlg.h" #include "SMESHGUI_MultiEditDlg.h" #include "SMESHGUI_NodesDlg.h" -#include "SMESHGUI_Preferences_ColorDlg.h" #include "SMESHGUI_Preferences_ScalarBarDlg.h" +#include "SMESHGUI_PropertiesDlg.h" #include "SMESHGUI_RemoveElementsDlg.h" #include "SMESHGUI_RemoveNodesDlg.h" #include "SMESHGUI_RenumberingDlg.h" @@ -212,6 +212,10 @@ filter.append( QObject::tr( "SAUV files (*.sauv*)" ) ); filter.append( QObject::tr( "All files (*)" ) ); } + else if ( theCommandID == 118 ) { + filter.append( QObject::tr( "GMF_ASCII_FILES_FILTER" ) + " (*.mesh)" ); + filter.append( QObject::tr( "GMF_BINARY_FILES_FILTER") + " (*.meshb)" ); + } QString anInitialPath = ""; if ( SUIT_FileDlg::getLastVisitedPath().isEmpty() ) @@ -294,6 +298,22 @@ } break; } + case 118: + { + // GMF format + SMESH::ComputeError_var res; + aMeshes->length( 1 ); + aMeshes[0] = theComponentMesh->CreateMeshesFromGMF( filename.toLatin1().constData(), res.out() ); + if ( res->code != SMESH::DRS_OK ) { + errors.append( QString( "%1 :\n\t%2" ).arg( filename ). + arg( QObject::tr( QString( "SMESH_DRS_%1" ).arg( res->code ).toLatin1().data() ) ) ); + if ( strlen( res->comment.in() ) > 0 ) { + errors.back() += ": "; + errors.back() += res->comment.in(); + } + } + break; + } } } catch ( const SALOME::SALOME_Exception& S_ex ) { @@ -368,6 +388,7 @@ const bool isSTL = ( theCommandID == 140 || theCommandID == 141 ); const bool isCGNS= ( theCommandID == 142 || theCommandID == 143 ); const bool isSAUV= ( theCommandID == 144 || theCommandID == 145 ); + const bool isGMF = ( theCommandID == 146 || theCommandID == 147 ); // actually, the following condition can't be met (added for insurance) if( selected.Extent() == 0 || @@ -416,10 +437,10 @@ aMeshIter = aMeshList.begin(); SMESH::SMESH_IDSource_var aMeshOrGroup = (*aMeshIter).first; - SMESH::SMESH_Mesh_var aMesh = aMeshOrGroup->GetMesh(); - QString aMeshName = (*aMeshIter).second; + SMESH::SMESH_Mesh_var aMesh = aMeshOrGroup->GetMesh(); + QString aMeshName = (*aMeshIter).second; - if ( isMED || isCGNS || isSAUV ) + if ( isMED || isCGNS || isSAUV ) // formats where group names must be unique { // check for equal group names within each mesh for( aMeshIter = aMeshList.begin(); aMeshIter != aMeshList.end(); aMeshIter++ ) { @@ -495,6 +516,21 @@ notSupportedElemTypes.push_back( SMESH::Entity_Polygon ); notSupportedElemTypes.push_back( SMESH::Entity_Polyhedra ); } + else if ( isGMF ) + { + format = "GMF"; + notSupportedElemTypes.push_back( SMESH::Entity_0D ); + notSupportedElemTypes.push_back( SMESH::Entity_Quad_Quadrangle ); + notSupportedElemTypes.push_back( SMESH::Entity_Polygon ); + notSupportedElemTypes.push_back( SMESH::Entity_Quad_Polygon ); + notSupportedElemTypes.push_back( SMESH::Entity_Quad_Pyramid ); + notSupportedElemTypes.push_back( SMESH::Entity_Quad_Hexa ); + notSupportedElemTypes.push_back( SMESH::Entity_Quad_Penta ); + notSupportedElemTypes.push_back( SMESH::Entity_Hexagonal_Prism ); + notSupportedElemTypes.push_back( SMESH::Entity_Polyhedra ); + notSupportedElemTypes.push_back( SMESH::Entity_Quad_Polyhedra ); + notSupportedElemTypes.push_back( SMESH::Entity_Ball ); + } if ( ! notSupportedElemTypes.empty() ) { SMESH::long_array_var nbElems = aMeshOrGroup->GetMeshInfo(); @@ -532,10 +568,10 @@ // Get parameters of export operation - QString aFilename; + QString aFilename; SMESH::MED_VERSION aFormat; // Init the parameters with the default values - bool aIsASCII_STL = true; + bool aIsASCII_STL = true; bool toCreateGroups = false; SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr(); if ( resMgr ) @@ -547,12 +583,16 @@ if ( SUIT_FileDlg::getLastVisitedPath().isEmpty() ) anInitialPath = QDir::currentPath(); - if ( isUNV || isDAT ) + // Get a file name to write in and additional otions + if ( isUNV || isDAT || isGMF ) // Export w/o options { if ( isUNV ) aFilter = QObject::tr( "IDEAS_FILES_FILTER" ) + " (*.unv)"; - else + else if ( isDAT ) aFilter = QObject::tr( "DAT_FILES_FILTER" ) + " (*.dat)"; + else if ( isGMF ) + aFilter = QObject::tr( "GMF_ASCII_FILES_FILTER" ) + " (*.mesh)" + + ";;" + QObject::tr( "GMF_BINARY_FILES_FILTER" ) + " (*.meshb)"; if ( anInitialPath.isEmpty() ) anInitialPath = SUIT_FileDlg::getLastVisitedPath(); aFilename = SUIT_FileDlg::getFileName(SMESHGUI::desktop(), anInitialPath + QString("/") + aMeshName, @@ -801,6 +841,10 @@ toOverwrite && aMeshIndex == 0 ); } } + else if ( isGMF ) + { + aMesh->ExportGMF( aMeshOrGroup, aFilename.toLatin1().data() ); + } } catch (const SALOME::SALOME_Exception& S_ex){ wc.suspend(); @@ -895,6 +939,8 @@ SALOMEDS::Color aColor = aGroupObject->GetColor(); _PTR(SObject) aGroupSObject = SMESH::FindSObject(aGroupObject); if (aGroupSObject) { + QColor c; + int delta; if(SMESH_Actor *anActor = SMESH::FindActorByEntry(aGroupSObject->GetID().c_str())) { switch ( aGroupObject->GetType ()) { case SMESH::NODE: @@ -905,9 +951,11 @@ anActor->Set0DColor( aColor.R, aColor.G, aColor.B ); break; case SMESH::BALL: anActor->SetBallColor( aColor.R, aColor.G, aColor.B ); break; + case SMESH::VOLUME: + SMESH::GetColor("SMESH", "volume_color", c, delta, "255,0,170|-100"); + anActor->SetVolumeColor( aColor.R, aColor.G, aColor.B, delta ); break; + case SMESH::FACE: default: - QColor c; - int delta; SMESH::GetColor("SMESH", "fill_color", c, delta, "0,170,255|-100"); anActor->SetSufaceColor( aColor.R, aColor.G, aColor.B, delta ); } @@ -1158,250 +1206,224 @@ (new SMESHGUI_TransparencyDlg( SMESHGUI::GetSMESHGUI() ))->show(); return; } - case 1132:{ - QColor c, e, b, n, c0D, cBall, o, outl, selection, preselection; - int delta; - int size0D = 0, ballSize = 0; - int Edgewidth = 0; - vtkFloatingPointType Shrink = 0.0; - vtkFloatingPointType faces_orientation_scale = 0.0; - bool faces_orientation_3dvectors = false; - - VTK::MarkerType aMarkerTypeCurrent = VTK::MT_NONE; - VTK::MarkerScale aMarkerScaleCurrent = VTK::MS_NONE; - int aMarkerTextureCurrent = 0; + case 1132: { + vtkFloatingPointType color[3]; + QColor faceColor, edgeColor, nodeColor, elem0dColor, ballColor; + QColor orientationColor, outlineColor, volumeColor; + int deltaF = 0, deltaV = 0; + int elem0dSize = 1; + int ballSize = 1; + int edgeWidth = 1; + int outlineWidth = 1; + vtkFloatingPointType shrinkCoef = 0.0; + vtkFloatingPointType orientationScale = 0.0; + bool orientation3d = false; + VTK::MarkerType markerType = VTK::MT_NONE; + VTK::MarkerScale markerScale = VTK::MS_NONE; + int markerId = 0; + bool hasNodes = false; + int presentEntities = 0; + bool firstTime = true; SALOME_ListIteratorOfListIO It( selected ); - for( ; It.More(); It.Next()){ + for ( ; It.More(); It.Next() ) { Handle(SALOME_InteractiveObject) IObject = It.Value(); - if(IObject->hasEntry()){ - if(SMESH_Actor *anActor = SMESH::FindActorByEntry(IObject->getEntry())){ - vtkFloatingPointType color[3]; - anActor->GetSufaceColor(color[0], color[1], color[2],delta); - int c0 = int (color[0] * 255); - int c1 = int (color[1] * 255); - int c2 = int (color[2] * 255); - c.setRgb(c0, c1, c2); - - vtkFloatingPointType edgecolor[3]; - anActor->GetEdgeColor(edgecolor[0], edgecolor[1], edgecolor[2]); - c0 = int (edgecolor[0] * 255); - c1 = int (edgecolor[1] * 255); - c2 = int (edgecolor[2] * 255); - e.setRgb(c0, c1, c2); - - vtkFloatingPointType nodecolor[3]; - anActor->GetNodeColor(nodecolor[0], nodecolor[1], nodecolor[2]); - c0 = int (nodecolor[0] * 255); - c1 = int (nodecolor[1] * 255); - c2 = int (nodecolor[2] * 255); - n.setRgb(c0, c1, c2); - - vtkFloatingPointType color0D[3]; - anActor->Get0DColor(color0D[0], color0D[1], color0D[2]); - c0 = int (color0D[0] * 255); - c1 = int (color0D[1] * 255); - c2 = int (color0D[2] * 255); - c0D.setRgb(c0, c1, c2); - - vtkFloatingPointType ballcolor[3]; - anActor->GetBallColor(ballcolor[0], ballcolor[1], ballcolor[2]); - c0 = int (ballcolor[0] * 255); - c1 = int (ballcolor[1] * 255); - c2 = int (ballcolor[2] * 255); - cBall.setRgb(c0, c1, c2); - - vtkFloatingPointType outlineColor[3]; - anActor->GetOutlineColor(outlineColor[0], outlineColor[1], outlineColor[2]); - c0 = int (outlineColor[0] * 255); - c1 = int (outlineColor[1] * 255); - c2 = int (outlineColor[2] * 255); - outl.setRgb(c0, c1, c2); - - vtkFloatingPointType hColor[3]; - anActor->GetHighlightColor(hColor[0], hColor[1], hColor[2]); - c0 = int (hColor[0] * 255); - c1 = int (hColor[1] * 255); - c2 = int (hColor[2] * 255); - selection.setRgb(c0, c1, c2); - - vtkFloatingPointType phColor[3]; - anActor->GetPreHighlightColor(phColor[0], phColor[1], phColor[2]); - c0 = int (phColor[0] * 255); - c1 = int (phColor[1] * 255); - c2 = int (phColor[2] * 255); - preselection.setRgb(c0, c1, c2); - - size0D = (int)anActor->Get0DSize(); - if(size0D == 0) - size0D = 1; - ballSize = (int)anActor->GetBallSize(); - if(ballSize == 0) - ballSize = 1; - Edgewidth = (int)anActor->GetLineWidth(); - if(Edgewidth == 0) - Edgewidth = 1; - Shrink = anActor->GetShrinkFactor(); - - vtkFloatingPointType faces_orientation_color[3]; - anActor->GetFacesOrientationColor(faces_orientation_color); - c0 = int (faces_orientation_color[0] * 255); - c1 = int (faces_orientation_color[1] * 255); - c2 = int (faces_orientation_color[2] * 255); - o.setRgb(c0, c1, c2); - - faces_orientation_scale = anActor->GetFacesOrientationScale(); - faces_orientation_3dvectors = anActor->GetFacesOrientation3DVectors(); - - aMarkerTypeCurrent = anActor->GetMarkerType(); - aMarkerScaleCurrent = anActor->GetMarkerScale(); - aMarkerTextureCurrent = anActor->GetMarkerTexture(); - - // even if there are multiple objects in the selection, - // we need only the first one to get values for the dialog - break; - } + if ( !IObject->hasEntry() ) continue; + SMESH_Actor* anActor = SMESH::FindActorByEntry( IObject->getEntry() ); + if ( !anActor || !anActor->GetObject() ) continue; + + if ( firstTime ) { + // nodes: color, marker + anActor->GetNodeColor( color[0], color[1], color[2] ); + nodeColor.setRgbF( color[0], color[1], color[2] ); + markerType = anActor->GetMarkerType(); + markerScale = anActor->GetMarkerScale(); + markerId = anActor->GetMarkerTexture(); + // edges: color, width + anActor->GetEdgeColor( color[0], color[1], color[2] ); + edgeColor.setRgbF( color[0], color[1], color[2] ); + edgeWidth = qMax( (int)anActor->GetLineWidth(), 1 ); // minimum allowed width is 1 + // faces: front color, back color (delta) + anActor->GetSufaceColor( color[0], color[1], color[2], deltaF ); + faceColor.setRgbF( color[0], color[1], color[2] ); + // faces: front color, back color (delta) + anActor->GetVolumeColor( color[0], color[1], color[2], deltaV ); + volumeColor.setRgbF( color[0], color[1], color[2] ); + // 0d elements: color, size + anActor->Get0DColor( color[0], color[1], color[2] ); + elem0dColor.setRgbF( color[0], color[1], color[2] ); + elem0dSize = qMax( (int)anActor->Get0DSize(), 1 ); // minimum allowed size is 1 + // balls: color, size + anActor->GetBallColor( color[0], color[1], color[2] ); + ballColor.setRgbF( color[0], color[1], color[2] ); + ballSize = qMax( (int)anActor->GetBallSize(), 1 ); // minimum allowed size is 1 + // outlines: color + anActor->GetOutlineColor( color[0], color[1], color[2] ); + outlineColor.setRgbF( color[0], color[1], color[2] ); + outlineWidth = qMax( (int)anActor->GetOutlineWidth(), 1 ); // minimum allowed width is 1 + // orientation vectors: color, scale, 3d flag + anActor->GetFacesOrientationColor( color[0], color[1], color[2] ); + orientationColor.setRgbF( color[0], color[1], color[2] ); + orientationScale = anActor->GetFacesOrientationScale(); + orientation3d = anActor->GetFacesOrientation3DVectors(); + // shrink factor + shrinkCoef = anActor->GetShrinkFactor(); } + + firstTime = false; // we only take properties from first object (for performance reasons) + + if ( !hasNodes ) + hasNodes = anActor->GetObject()->GetNbEntities( SMDSAbs_Node ); + if ( !(presentEntities & SMESH_Actor::eEdges) && anActor->GetObject()->GetNbEntities( SMDSAbs_Edge ) ) + presentEntities = presentEntities | SMESH_Actor::eEdges; + if ( !(presentEntities & SMESH_Actor::eFaces) && anActor->GetObject()->GetNbEntities( SMDSAbs_Face ) ) + presentEntities = presentEntities | SMESH_Actor::eFaces; + if ( !(presentEntities & SMESH_Actor::eVolumes) && anActor->GetObject()->GetNbEntities( SMDSAbs_Volume ) ) + presentEntities = presentEntities | SMESH_Actor::eVolumes; + if ( !(presentEntities & SMESH_Actor::e0DElements) && anActor->GetObject()->GetNbEntities( SMDSAbs_0DElement ) ) + presentEntities = presentEntities | SMESH_Actor::e0DElements; + if ( !(presentEntities & SMESH_Actor::eBallElem) && anActor->GetObject()->GetNbEntities( SMDSAbs_Ball ) ) + presentEntities = presentEntities | SMESH_Actor::eBallElem; + + // as we know that all types of elements are present, we can exit the loop + if ( presentEntities == SMESH_Actor::eAllEntity ) + break; } - SMESHGUI_Preferences_ColorDlg *aDlg = - new SMESHGUI_Preferences_ColorDlg( SMESHGUI::GetSMESHGUI() ); - aDlg->SetBooleanValue(1, faces_orientation_3dvectors); - aDlg->SetColor(1, c); - aDlg->SetColor(2, e); - aDlg->SetColor(3, n); - aDlg->SetColor(4, outl); - aDlg->SetColor(5, c0D); - aDlg->SetColor(6, cBall); - aDlg->SetColor(7, o); - aDlg->SetColor(8, selection); - aDlg->SetColor(9, preselection); - aDlg->SetDeltaBrightness(delta); - aDlg->SetDoubleValue(1, faces_orientation_scale); - aDlg->SetIntValue(1, Edgewidth); - aDlg->SetIntValue(2, int(Shrink*100.)); - aDlg->SetIntValue(3, size0D); - aDlg->SetIntValue(4, ballSize); - - aDlg->setCustomMarkerMap( theMarkerMap[ aStudy->StudyId() ] ); - - if( aMarkerTypeCurrent != VTK::MT_USER ) - aDlg->setStandardMarker( aMarkerTypeCurrent, aMarkerScaleCurrent ); + SMESHGUI_PropertiesDlg dlg( theMarkerMap[ aStudy->StudyId() ], SMESHGUI::desktop() ); + // nodes: color, marker + dlg.setNodeColor( nodeColor ); + if( markerType != VTK::MT_USER ) + dlg.setNodeMarker( markerType, markerScale ); else - aDlg->setCustomMarker( aMarkerTextureCurrent ); - - if(aDlg->exec()){ - QColor color = aDlg->GetColor(1); - QColor edgecolor = aDlg->GetColor(2); - QColor nodecolor = aDlg->GetColor(3); - QColor outlinecolor = aDlg->GetColor(4); - QColor color0D = aDlg->GetColor(5); - QColor ballcolor = aDlg->GetColor(6); - QColor faces_orientation_color = aDlg->GetColor(7); - QColor selectioncolor = aDlg->GetColor(8); - QColor preSelectioncolor = aDlg->GetColor(9); - int delta = aDlg->GetDeltaBrightness(); - - /* Point marker */ - theMarkerMap[ aStudy->StudyId() ] = aDlg->getCustomMarkerMap(); - + dlg.setNodeCustomMarker( markerId ); + // edges: color, line width + dlg.setEdgeColor( edgeColor ); + dlg.setEdgeWidth( edgeWidth ); + // faces: front color, back color + dlg.setFaceColor( faceColor, deltaF ); + // volumes: normal color, reversed color + dlg.setVolumeColor( volumeColor, deltaV ); + // outlines: color, line width + dlg.setOutlineColor( outlineColor ); + dlg.setOutlineWidth( outlineWidth ); + // 0d elements: color, size + dlg.setElem0dColor( elem0dColor ); + dlg.setElem0dSize( elem0dSize ); + // balls: color, size + dlg.setBallColor( ballColor ); + dlg.setBallSize( ballSize ); + // orientation: color, scale, 3d flag + dlg.setOrientationColor( orientationColor ); + dlg.setOrientationSize( int( orientationScale * 100. ) ); + dlg.setOrientation3d( orientation3d ); + // shrink: scale factor + dlg.setShrinkCoef( int( shrinkCoef * 100. ) ); + // hide unused controls + dlg.showControls( presentEntities, hasNodes ); + + if ( dlg.exec() ) { + nodeColor = dlg.nodeColor(); + markerType = dlg.nodeMarkerType(); + markerScale = dlg.nodeMarkerScale(); + markerId = dlg.nodeMarkerId(); + edgeColor = dlg.edgeColor(); + edgeWidth = dlg.edgeWidth(); + faceColor = dlg.faceColor(); + deltaF = dlg.faceColorDelta(); + volumeColor = dlg.volumeColor(); + deltaV = dlg.volumeColorDelta(); + outlineColor = dlg.outlineColor(); + outlineWidth = dlg.outlineWidth(); + elem0dColor = dlg.elem0dColor(); + elem0dSize = dlg.elem0dSize(); + ballColor = dlg.ballColor(); + ballSize = dlg.ballSize(); + orientationColor = dlg.orientationColor(); + orientationScale = dlg.orientationSize() / 100.; + orientation3d = dlg.orientation3d(); + shrinkCoef = dlg.shrinkCoef() / 100.; + + // store point markers map that might be changed by the user + theMarkerMap[ aStudy->StudyId() ] = dlg.customMarkers(); + + // set properties from dialog box to the presentations SALOME_ListIteratorOfListIO It( selected ); - for( ; It.More(); It.Next()){ + for ( ; It.More(); It.Next() ) { Handle(SALOME_InteractiveObject) IObject = It.Value(); - if(IObject->hasEntry()){ - if(SMESH_Actor *anActor = SMESH::FindActorByEntry(IObject->getEntry())){ - /* actor color and backface color */ - anActor->SetSufaceColor(vtkFloatingPointType (color.red()) / 255., - vtkFloatingPointType (color.green()) / 255., - vtkFloatingPointType (color.blue()) / 255., - delta); - /* edge color */ - anActor->SetEdgeColor(vtkFloatingPointType (edgecolor.red()) / 255., - vtkFloatingPointType (edgecolor.green()) / 255., - vtkFloatingPointType (edgecolor.blue()) / 255.); - /* edge outline */ - anActor->SetOutlineColor(vtkFloatingPointType (outlinecolor.red()) / 255., - vtkFloatingPointType (outlinecolor.green()) / 255., - vtkFloatingPointType (outlinecolor.blue()) / 255.); - - /* selection */ - anActor->SetHighlightColor(vtkFloatingPointType (selectioncolor.red()) / 255., - vtkFloatingPointType (selectioncolor.green()) / 255., - vtkFloatingPointType (selectioncolor.blue()) / 255.); - /* pre-selection */ - anActor->SetPreHighlightColor(vtkFloatingPointType (preSelectioncolor.red()) / 255., - vtkFloatingPointType (preSelectioncolor.green()) / 255., - vtkFloatingPointType (preSelectioncolor.blue()) / 255.); - - - /* Shrink factor and size edges */ - anActor->SetShrinkFactor(aDlg->GetIntValue(2) / 100.); - anActor->SetLineWidth(aDlg->GetIntValue(1)); - - /* Nodes color and size */ - anActor->SetNodeColor(vtkFloatingPointType (nodecolor.red()) / 255., - vtkFloatingPointType (nodecolor.green()) / 255., - vtkFloatingPointType (nodecolor.blue()) / 255.); - - /* 0D elements */ - anActor->Set0DColor(vtkFloatingPointType (color0D.red()) / 255., - vtkFloatingPointType (color0D.green()) / 255., - vtkFloatingPointType (color0D.blue()) / 255.); - anActor->Set0DSize(aDlg->GetIntValue(3)); - - /* Ball elements */ - anActor->SetBallColor(vtkFloatingPointType (ballcolor.red()) / 255., - vtkFloatingPointType (ballcolor.green()) / 255., - vtkFloatingPointType (ballcolor.blue()) / 255.); - anActor->SetBallSize(aDlg->GetIntValue(4)); - - /* Faces orientation */ - vtkFloatingPointType c[3] = {vtkFloatingPointType(faces_orientation_color.redF()), - vtkFloatingPointType(faces_orientation_color.greenF()), - vtkFloatingPointType(faces_orientation_color.blueF())}; - anActor->SetFacesOrientationColor(c); - anActor->SetFacesOrientationScale(aDlg->GetDoubleValue(1)); - anActor->SetFacesOrientation3DVectors(aDlg->GetBooleanValue(1)); - - VTK::MarkerType aMarkerTypeNew = aDlg->getMarkerType(); - VTK::MarkerScale aMarkerScaleNew = aDlg->getStandardMarkerScale(); - int aMarkerTextureNew = aDlg->getCustomMarkerID(); - if( aMarkerTypeNew != VTK::MT_USER ) - anActor->SetMarkerStd( aMarkerTypeNew, aMarkerScaleNew ); - else { - const VTK::MarkerMap& aMarkerMap = theMarkerMap[ aStudy->StudyId() ]; - VTK::MarkerMap::const_iterator anIter = aMarkerMap.find( aMarkerTextureNew ); - if( anIter != aMarkerMap.end() ) - anActor->SetMarkerTexture( aMarkerTextureNew, anIter->second.second ); - } - - SMESH::SMESH_GroupBase_var aGroupObject = SMESH::IObjectToInterface(IObject); - if( !aGroupObject->_is_nil() ) - { - SMESH::ElementType anElementType = aGroupObject->GetType(); - QColor aColor; - switch( anElementType ) - { - case SMESH::NODE: aColor = nodecolor; break; - case SMESH::EDGE: aColor = edgecolor; break; - default: aColor = color; break; - } - - SALOMEDS::Color aGroupColor; - aGroupColor.R = (float)aColor.red() / 255.0; - aGroupColor.G = (float)aColor.green() / 255.0; - aGroupColor.B = (float)aColor.blue() / 255.0; - aGroupObject->SetColor( aGroupColor ); - } - } + if ( !IObject->hasEntry() ) continue; + SMESH_Actor* anActor = SMESH::FindActorByEntry( IObject->getEntry() ); + if ( !anActor ) continue; + + // nodes: color, marker + anActor->SetNodeColor( nodeColor.redF(), nodeColor.greenF(), nodeColor.blueF() ); + if ( markerType != VTK::MT_USER ) { + anActor->SetMarkerStd( markerType, markerScale ); } - } + else { + const VTK::MarkerMap& markerMap = theMarkerMap[ aStudy->StudyId() ]; + VTK::MarkerMap::const_iterator iter = markerMap.find( markerId ); + if ( iter != markerMap.end() ) + anActor->SetMarkerTexture( markerId, iter->second.second ); + } + // volumes: normal color, reversed color (delta) + anActor->SetVolumeColor( volumeColor.redF(), volumeColor.greenF(), volumeColor.blueF(), deltaV ); + // faces: front color, back color (delta) + anActor->SetSufaceColor( faceColor.redF(), faceColor.greenF(), faceColor.blueF(), deltaF ); + // edges: color, width + anActor->SetEdgeColor( edgeColor.redF(), edgeColor.greenF(), edgeColor.blueF() ); + anActor->SetLineWidth( edgeWidth ); + // outlines: color + anActor->SetOutlineColor( outlineColor.redF(), outlineColor.greenF(), outlineColor.blueF() ); + anActor->SetOutlineWidth( outlineWidth ); + // 0D elements: color, size + anActor->Set0DColor( elem0dColor.redF(), elem0dColor.greenF(), elem0dColor.blueF() ); + anActor->Set0DSize( elem0dSize ); + // balls: color, size + anActor->SetBallColor( ballColor.redF(), ballColor.greenF(), ballColor.blueF() ); + anActor->SetBallSize( ballSize ); + // orientation: color, scale, 3d flag + anActor->SetFacesOrientationColor( orientationColor.redF(), orientationColor.greenF(), orientationColor.blueF() ); + anActor->SetFacesOrientationScale( orientationScale ); + anActor->SetFacesOrientation3DVectors( orientation3d ); + // shrink factor + anActor->SetShrinkFactor( shrinkCoef ); + + // for groups, set also proper color + SMESH::SMESH_GroupBase_var aGroupObject = SMESH::IObjectToInterface(IObject); + if ( !aGroupObject->_is_nil() ) { + SMESH::ElementType anElementType = aGroupObject->GetType(); + QColor aColor; + switch( anElementType ) { + case SMESH::NODE: + aColor = nodeColor; break; + case SMESH::EDGE: + aColor = edgeColor; break; + case SMESH::FACE: + aColor = faceColor; break; + case SMESH::VOLUME: + aColor = volumeColor; break; + case SMESH::ELEM0D: + aColor = elem0dColor; break; + case SMESH::BALL: + aColor = ballColor; break; + default: break; + } + + if ( aColor.isValid() ) { + SALOMEDS::Color aGroupColor; + aGroupColor.R = aColor.redF(); + aGroupColor.G = aColor.greenF(); + aGroupColor.B = aColor.blueF(); + aGroupObject->SetColor( aGroupColor ); + } + } // if ( !aGroupObject->_is_nil() ) + } // for ( ; It.More(); It.Next() ) SMESH::RepaintCurrentView(); - } - delete aDlg; + } // if ( dlg.exec() ) return; - } - } + } // case 1132: + } // switch(theCommandID) SALOME_ListIteratorOfListIO It( selected ); for( ; It.More(); It.Next()){ Handle(SALOME_InteractiveObject) IObject = It.Value(); @@ -2160,6 +2182,7 @@ bool SMESHGUI::OnGUIEvent( int theCommandID ) case 116: case 115: case 117: + case 118: case 113: case 112: case 111: // IMPORT @@ -2200,6 +2223,8 @@ bool SMESHGUI::OnGUIEvent( int theCommandID ) case 143: case 144: case 145: + case 146: + case 147: { ::ExportMeshToFile(theCommandID); break; @@ -3509,25 +3534,28 @@ void SMESHGUI::initialize( CAM_Application* app ) // ----- create actions -------------- - createSMESHAction( 111, "IMPORT_DAT", "", (Qt::CTRL+Qt::Key_B) ); + //createSMESHAction( 111, "IMPORT_DAT", "", (Qt::CTRL+Qt::Key_B) ); createSMESHAction( 112, "IMPORT_UNV", "", (Qt::CTRL+Qt::Key_U) ); createSMESHAction( 113, "IMPORT_MED", "", (Qt::CTRL+Qt::Key_M) ); createSMESHAction( 114, "NUM" ); - createSMESHAction( 115, "IMPORT_STL" ); + createSMESHAction( 115, "IMPORT_STL" ); createSMESHAction( 116, "IMPORT_CGNS" ); createSMESHAction( 117, "IMPORT_SAUV" ); + createSMESHAction( 118, "IMPORT_GMF" ); createSMESHAction( 121, "DAT" ); createSMESHAction( 122, "MED" ); createSMESHAction( 123, "UNV" ); createSMESHAction( 140, "STL" ); - createSMESHAction( 142, "CGNS" ); - createSMESHAction( 144, "SAUV" ); + createSMESHAction( 142, "CGNS"); + createSMESHAction( 144, "SAUV"); + createSMESHAction( 146, "GMF" ); createSMESHAction( 124, "EXPORT_DAT" ); createSMESHAction( 125, "EXPORT_MED" ); createSMESHAction( 126, "EXPORT_UNV" ); createSMESHAction( 141, "EXPORT_STL" ); - createSMESHAction( 143, "EXPORT_CGNS" ); - createSMESHAction( 145, "EXPORT_SAUV" ); + createSMESHAction( 143, "EXPORT_CGNS"); + createSMESHAction( 145, "EXPORT_SAUV"); + createSMESHAction( 147, "EXPORT_GMF" ); createSMESHAction( 150, "FILE_INFO" ); createSMESHAction( 33, "DELETE", "ICON_DELETE", Qt::Key_Delete ); createSMESHAction( 5105, "SEL_FILTER_LIB" ); @@ -3699,7 +3727,7 @@ void SMESHGUI::initialize( CAM_Application* app ) renumId = createMenu( tr( "MEN_RENUM" ), modifyId, 404 ), transfId = createMenu( tr( "MEN_TRANSF" ), modifyId, 405 ); - createMenu( 111, importId, -1 ); + //createMenu( 111, importId, -1 ); createMenu( 112, importId, -1 ); createMenu( 113, importId, -1 ); createMenu( 115, importId, -1 ); @@ -3707,6 +3735,7 @@ void SMESHGUI::initialize( CAM_Application* app ) createMenu( 116, importId, -1 ); #endif createMenu( 117, importId, -1 ); + createMenu( 118, importId, -1 ); createMenu( 121, exportId, -1 ); createMenu( 122, exportId, -1 ); createMenu( 123, exportId, -1 ); @@ -3715,6 +3744,7 @@ void SMESHGUI::initialize( CAM_Application* app ) createMenu( 142, exportId, -1 ); // export to CGNS #endif createMenu( 144, exportId, -1 ); // export to SAUV + createMenu( 146, exportId, -1 ); // export to GMF createMenu( separator(), fileId, 10 ); createMenu( 33, editId, -1 ); @@ -4042,6 +4072,7 @@ void SMESHGUI::initialize( CAM_Application* app ) createPopupItem( 143, OB, mesh_group, multiple_non_empty ); // EXPORT_CGNS #endif createPopupItem( 145, OB, mesh_group, multiple_non_empty ); // EXPORT_SAUV + createPopupItem( 147, OB, mesh_group, multiple_non_empty ); // EXPORT_GMF createPopupItem( 33, OB, mesh_part + " " + hyp_alg ); // DELETE createPopupItem( 813, OB, group ); // DEL_GROUP with contents popupMgr()->insert( separator(), -1, 0 ); @@ -4407,7 +4438,7 @@ bool SMESHGUI::activateModule( SUIT_Study* study ) // end of GEOM plugins loading // Reset actions accelerator keys - action(111)->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_B)); // Import DAT + //action(111)->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_B)); // Import DAT action(112)->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_U)); // Import UNV action(113)->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_M)); // Import MED @@ -4442,7 +4473,7 @@ bool SMESHGUI::deactivateModule( SUIT_Study* study ) EmitSignalCloseAllDialogs(); // Unset actions accelerator keys - action(111)->setShortcut(QKeySequence()); // Import DAT + //action(111)->setShortcut(QKeySequence()); // Import DAT action(112)->setShortcut(QKeySequence()); // Import UNV action(113)->setShortcut(QKeySequence()); // Import MED @@ -4761,20 +4792,23 @@ void SMESHGUI::createPreferences() setPreferenceProperty( markerScale, "indexes", aMarkerScaleIndicesList ); int elemGroup = addPreference( tr( "PREF_GROUP_ELEMENTS" ), meshTab ); - setPreferenceProperty( elemGroup, "columns", 2 ); + //setPreferenceProperty( elemGroup, "columns", 2 ); - int ColorId = addPreference( tr( "PREF_FILL" ), elemGroup, LightApp_Preferences::BiColor, "SMESH", "fill_color" ); + int ColorId = addPreference( tr( "PREF_FILL" ), elemGroup, LightApp_Preferences::BiColor, "SMESH", "fill_color" ); + setPreferenceProperty( ColorId, "text", tr("PREF_BACKFACE") ); + ColorId = addPreference( tr( "PREF_VOLUME" ), elemGroup, LightApp_Preferences::BiColor, "SMESH", "volume_color" ); + setPreferenceProperty( ColorId, "text", tr("PREF_REVERSEDVOLUME") ); addPreference( tr( "PREF_COLOR_0D" ), elemGroup, LightApp_Preferences::Color, "SMESH", "elem0d_color" ); addPreference( tr( "PREF_BALL_COLOR" ), elemGroup, LightApp_Preferences::Color, "SMESH", "ball_elem_color" ); addPreference( tr( "PREF_OUTLINE" ), elemGroup, LightApp_Preferences::Color, "SMESH", "outline_color" ); addPreference( tr( "PREF_WIREFRAME" ), elemGroup, LightApp_Preferences::Color, "SMESH", "wireframe_color" ); - setPreferenceProperty( ColorId, "text", tr("PREF_BACKFACE") ); int grpGroup = addPreference( tr( "PREF_GROUP_GROUPS" ), meshTab ); setPreferenceProperty( grpGroup, "columns", 2 ); addPreference( tr( "PREF_GRP_NAMES" ), grpGroup, LightApp_Preferences::Color, "SMESH", "group_name_color" ); + addPreference( tr( "PREF_GRP_DEF_COLOR" ), grpGroup, LightApp_Preferences::Color, "SMESH", "default_grp_color" ); int size0d = addPreference(tr("PREF_SIZE_0D"), elemGroup, LightApp_Preferences::IntSpin, "SMESH", "elem0d_size"); @@ -4782,6 +4816,8 @@ void SMESHGUI::createPreferences() LightApp_Preferences::IntSpin, "SMESH", "ball_elem_size"); int elemW = addPreference(tr("PREF_WIDTH"), elemGroup, LightApp_Preferences::IntSpin, "SMESH", "element_width"); + int outW = addPreference(tr("PREF_OUTLINE_WIDTH"), elemGroup, + LightApp_Preferences::IntSpin, "SMESH", "outline_width"); int shrink = addPreference(tr("PREF_SHRINK_COEFF"), elemGroup, LightApp_Preferences::IntSpin, "SMESH", "shrink_coeff"); @@ -4794,6 +4830,9 @@ void SMESHGUI::createPreferences() setPreferenceProperty( elemW, "min", 1 ); setPreferenceProperty( elemW, "max", 5 ); + setPreferenceProperty( outW, "min", 1 ); + setPreferenceProperty( outW, "max", 5 ); + setPreferenceProperty( shrink, "min", 0 ); setPreferenceProperty( shrink, "max", 100 ); @@ -5169,9 +5208,9 @@ SALOMEDS::Color SMESHGUI::getUniqueColor( const QList& theReser aColor.setHsv( aHue, 255, 255 ); SALOMEDS::Color aSColor; - aSColor.R = (double)aColor.red() / 255.0; - aSColor.G = (double)aColor.green() / 255.0; - aSColor.B = (double)aColor.blue() / 255.0; + aSColor.R = aColor.redF(); + aSColor.G = aColor.greenF(); + aSColor.B = aColor.blueF(); return aSColor; } diff --git a/src/SMESHGUI/SMESHGUI_AddMeshElementDlg.cxx b/src/SMESHGUI/SMESHGUI_AddMeshElementDlg.cxx index 2febf76f8..4ce7522d5 100644 --- a/src/SMESHGUI/SMESHGUI_AddMeshElementDlg.cxx +++ b/src/SMESHGUI/SMESHGUI_AddMeshElementDlg.cxx @@ -498,12 +498,12 @@ void SMESHGUI_AddMeshElementDlg::ClickOnApply() int idx = 0; if( addToGroup ) { aGroupName = ComboBox_GroupName->currentText(); - for ( int i = 1; i < ComboBox_GroupName->count(); i++ ) { + for ( int i = 1; i <= ComboBox_GroupName->count(); i++ ) { QString aName = ComboBox_GroupName->itemText( i ); if ( aGroupName == aName && ( i == ComboBox_GroupName->currentIndex() || idx == 0 ) ) idx = i; } - if ( idx > 0 && idx < myGroups.count() ) { + if ( idx > 0 && idx <= myGroups.count() ) { SMESH::SMESH_GroupOnGeom_var aGeomGroup = SMESH::SMESH_GroupOnGeom::_narrow( myGroups[idx-1] ); if ( !aGeomGroup->_is_nil() ) { int res = SUIT_MessageBox::question( this, tr( "SMESH_WRN_WARNING" ), diff --git a/src/SMESHGUI/SMESHGUI_AddQuadraticElementDlg.cxx b/src/SMESHGUI/SMESHGUI_AddQuadraticElementDlg.cxx index 0472de715..c4bc516ad 100644 --- a/src/SMESHGUI/SMESHGUI_AddQuadraticElementDlg.cxx +++ b/src/SMESHGUI/SMESHGUI_AddQuadraticElementDlg.cxx @@ -711,12 +711,12 @@ void SMESHGUI_AddQuadraticElementDlg::ClickOnApply() int idx = 0; if( addToGroup ) { aGroupName = ComboBox_GroupName->currentText(); - for ( int i = 1; i < ComboBox_GroupName->count(); i++ ) { + for ( int i = 1; i <= ComboBox_GroupName->count(); i++ ) { QString aName = ComboBox_GroupName->itemText( i ); if ( aGroupName == aName && ( i == ComboBox_GroupName->currentIndex() || idx == 0 ) ) idx = i; } - if ( idx > 0 && idx < myGroups.count() ) { + if ( idx > 0 && idx <= myGroups.count() ) { SMESH::SMESH_GroupOnGeom_var aGeomGroup = SMESH::SMESH_GroupOnGeom::_narrow( myGroups[idx-1] ); if ( !aGeomGroup->_is_nil() ) { int res = SUIT_MessageBox::question( this, tr( "SMESH_WRN_WARNING" ), diff --git a/src/SMESHGUI/SMESHGUI_ClippingDlg.cxx b/src/SMESHGUI/SMESHGUI_ClippingDlg.cxx index 3143626c6..82638364b 100644 --- a/src/SMESHGUI/SMESHGUI_ClippingDlg.cxx +++ b/src/SMESHGUI/SMESHGUI_ClippingDlg.cxx @@ -370,7 +370,7 @@ SMESHGUI_ClippingDlg::SMESHGUI_ClippingDlg( SMESHGUI* theModule, SVTK_ViewWindow ActorList = new QListWidget(GroupPlanes); ActorList->setSelectionMode(QAbstractItemView::SingleSelection); - + SelectAllCheckBox = new QCheckBox(tr("SELECT_ALL"), GroupPlanes); GroupPlanesLayout->addWidget(ComboBoxPlanes, 0, 0); @@ -477,7 +477,7 @@ SMESHGUI_ClippingDlg::SMESHGUI_ClippingDlg( SMESHGUI* theModule, SVTK_ViewWindow connect(SpinBoxRot1, SIGNAL(valueChanged(double)), this, SLOT(SetCurrentPlaneParam())); connect(SpinBoxRot2, SIGNAL(valueChanged(double)), this, SLOT(SetCurrentPlaneParam())); connect(PreviewCheckBox, SIGNAL(toggled(bool)), this, SLOT(OnPreviewToggle(bool))); - connect(AutoApplyCheckBox, SIGNAL(toggled(bool)), this, SLOT(ClickOnApply())); + connect(AutoApplyCheckBox, SIGNAL(toggled(bool)), this, SLOT(onAutoApply(bool))); connect(buttonOk, SIGNAL(clicked()), this, SLOT(ClickOnOk())); connect(buttonCancel, SIGNAL(clicked()), this, SLOT(ClickOnCancel())); connect(buttonApply, SIGNAL(clicked()), this, SLOT(ClickOnApply())); @@ -1063,7 +1063,9 @@ void SMESHGUI_ClippingDlg::initializePlaneData() SMESHGUI_ClippingPlaneInfoList::const_iterator anIter2 = aClippingPlaneInfoList.begin(); for( ; anIter2 != aClippingPlaneInfoList.end(); anIter2++ ) { const SMESH::ClippingPlaneInfo& aClippingPlaneInfo = *anIter2; - SMESH::TPlane aTPlane( aClippingPlaneInfo.Plane ); + SMESH::OrientedPlane* anOrientedPlane = SMESH::OrientedPlane::New(myViewWindow); + anOrientedPlane->ShallowCopy(aClippingPlaneInfo.Plane); + SMESH::TPlane aTPlane( anOrientedPlane ); SMESH::TPlaneData aPlaneData( aTPlane, aClippingPlaneInfo.ActorList ); myPlanes.push_back( aPlaneData ); } @@ -1170,3 +1172,8 @@ void SMESHGUI_ClippingDlg::dumpPlaneData() const } printf( "----------------------------------\n" ); } + +void SMESHGUI_ClippingDlg::onAutoApply(bool toggled) +{ + if ( toggled ) ClickOnApply(); +} diff --git a/src/SMESHGUI/SMESHGUI_ClippingDlg.h b/src/SMESHGUI/SMESHGUI_ClippingDlg.h index 70bd03b89..e8cb095f8 100644 --- a/src/SMESHGUI/SMESHGUI_ClippingDlg.h +++ b/src/SMESHGUI/SMESHGUI_ClippingDlg.h @@ -201,6 +201,7 @@ public slots: void onSelectOrientation( int ); void SetCurrentPlaneParam(); void OnPreviewToggle( bool ); + void onAutoApply(bool); void ClickOnOk(); void ClickOnCancel(); void ClickOnApply(); diff --git a/src/SMESHGUI/SMESHGUI_ComputeDlg.cxx b/src/SMESHGUI/SMESHGUI_ComputeDlg.cxx index 0bb2fa5ef..7bf81c56c 100644 --- a/src/SMESHGUI/SMESHGUI_ComputeDlg.cxx +++ b/src/SMESHGUI/SMESHGUI_ComputeDlg.cxx @@ -337,15 +337,16 @@ namespace SMESH { QString text; switch ( errCode ) { - CASE2TEXT( COMPERR_OK ); - CASE2TEXT( COMPERR_BAD_INPUT_MESH); - CASE2TEXT( COMPERR_STD_EXCEPTION ); - CASE2TEXT( COMPERR_OCC_EXCEPTION ); + CASE2TEXT( COMPERR_OK ); + CASE2TEXT( COMPERR_BAD_INPUT_MESH ); + CASE2TEXT( COMPERR_STD_EXCEPTION ); + CASE2TEXT( COMPERR_OCC_EXCEPTION ); case SMESH::COMPERR_SLM_EXCEPTION: break; // avoid double "Salome exception" - CASE2TEXT( COMPERR_EXCEPTION ); - CASE2TEXT( COMPERR_MEMORY_PB ); - CASE2TEXT( COMPERR_BAD_SHAPE ); - CASE2TEXT( COMPERR_CANCELED ); + CASE2TEXT( COMPERR_EXCEPTION ); + CASE2TEXT( COMPERR_MEMORY_PB ); + CASE2TEXT( COMPERR_BAD_SHAPE ); + CASE2TEXT( COMPERR_CANCELED ); + CASE2TEXT( COMPERR_NO_MESH_ON_SHAPE ); case SMESH::COMPERR_ALGO_FAILED: if ( strlen(comment) == 0 ) text = QObject::tr("COMPERR_ALGO_FAILED"); @@ -550,6 +551,9 @@ QFrame* SMESHGUI_ComputeDlg::createMainFrame (QWidget* theParent, bool ForEval) myTable->hideColumn( COL_SHAPEID ); myTable->hideColumn( COL_BAD_MESH ); myTable->horizontalHeader()->setResizeMode( COL_ERROR, QHeaderView::Interactive ); + myTable->setWordWrap( true ); + myTable->horizontalHeader()->setStretchLastSection( true ); + myTable->setMinimumWidth( 500 ); QStringList headers; headers << tr( "COL_ALGO_HEADER" ); @@ -564,12 +568,12 @@ QFrame* SMESHGUI_ComputeDlg::createMainFrame (QWidget* theParent, bool ForEval) QGridLayout* grpLayout = new QGridLayout(myCompErrorGroup); grpLayout->setSpacing(SPACING); grpLayout->setMargin(MARGIN); - grpLayout->addWidget( myWarningLabel, 0, 0 ); - grpLayout->addWidget( myTable, 1, 0, 4, 1 ); - grpLayout->addWidget( myShowBtn, 1, 1 ); + grpLayout->addWidget( myWarningLabel, 0, 0, 1, 4 ); + grpLayout->addWidget( myTable, 1, 0, 1, 4 ); + grpLayout->addWidget( myShowBtn, 2, 0 ); grpLayout->addWidget( myPublishBtn, 2, 1 ); - grpLayout->addWidget( myBadMeshBtn, 3, 1 ); - grpLayout->setRowStretch( 4, 1 ); + grpLayout->addWidget( myBadMeshBtn, 2, 2 ); + grpLayout->setColumnStretch( 3, 1 ); // Hypothesis definition errors @@ -948,7 +952,8 @@ void SMESHGUI_BaseComputeOp::showComputeResult( const bool theMemoryLack, { bool onlyWarnings = !theNoCompError; // == valid mesh computed but there are errors reported for ( int i = 0; i < theCompErrors->length() && onlyWarnings; ++i ) - onlyWarnings = ( theCompErrors[ i ].code == SMESH::COMPERR_WARNING ); + onlyWarnings = ( theCompErrors[ i ].code == SMESH::COMPERR_WARNING || + theCompErrors[ i ].code == SMESH::COMPERR_NO_MESH_ON_SHAPE ); // full or brief mesh info SMESH::long_array_var aRes = myMesh->GetMeshInfo(); @@ -1035,6 +1040,7 @@ void SMESHGUI_BaseComputeOp::showComputeResult( const bool theMemoryLack, } tbl->resizeColumnToContents( COL_ALGO ); tbl->resizeColumnToContents( COL_SHAPE ); + tbl->setWordWrap( true ); if ( hasBadMesh ) aCompDlg->myBadMeshBtn->show(); @@ -1142,13 +1148,13 @@ void SMESHGUI_BaseComputeOp::onShowBadMesh() SMESH::MeshPreviewStruct_var aMeshData = gen->GetBadInputElements(myMesh,curSub); vtkFloatingPointType aPointSize = SMESH::GetFloat("SMESH:node_size",3); vtkFloatingPointType aLineWidth = SMESH::GetFloat("SMESH:element_width",1); - // delete property !!!!!!!!!! vtkProperty* prop = vtkProperty::New(); prop->SetLineWidth( aLineWidth * 3 ); prop->SetPointSize( aPointSize * 3 ); prop->SetColor( 250, 0, 250 ); myBadMeshDisplayer->GetActor()->SetProperty( prop ); myBadMeshDisplayer->SetData( aMeshData._retn() ); + prop->Delete(); } } } @@ -2084,6 +2090,7 @@ void SMESHGUI_BaseComputeOp::showEvaluateResult(const SMESH::long_array& theRes, } tbl->resizeColumnToContents( COL_ALGO ); tbl->resizeColumnToContents( COL_SHAPE ); + tbl->setWordWrap( true ); if ( hasBadMesh ) aCompDlg->myBadMeshBtn->show(); diff --git a/src/SMESHGUI/SMESHGUI_ConvToQuadOp.cxx b/src/SMESHGUI/SMESHGUI_ConvToQuadOp.cxx index a62d0b949..a5575b879 100644 --- a/src/SMESHGUI/SMESHGUI_ConvToQuadOp.cxx +++ b/src/SMESHGUI/SMESHGUI_ConvToQuadOp.cxx @@ -29,21 +29,26 @@ #include "SMESHGUI.h" #include "SMESHGUI_ConvToQuadDlg.h" +#include "SMESHGUI_MeshEditPreview.h" #include "SMESHGUI_Utils.h" -#include "SMDSAbs_ElementType.hxx" - +#include "SMESH_ActorUtils.h" #include "SMESH_TypeFilter.hxx" +#include "SMDSAbs_ElementType.hxx" // SALOME GUI includes #include #include #include #include +#include // IDL includes #include #include CORBA_SERVER_HEADER(SMESH_MeshEditor) +// VTK includes +#include + //================================================================================ /*! * \brief Constructor @@ -53,7 +58,8 @@ //================================================================================ SMESHGUI_ConvToQuadOp::SMESHGUI_ConvToQuadOp() : SMESHGUI_SelectionOp(), - myDlg( 0 ) + myDlg( 0 ), + myBadElemsPreview(0) { } @@ -64,8 +70,8 @@ SMESHGUI_ConvToQuadOp::SMESHGUI_ConvToQuadOp() //================================================================================ SMESHGUI_ConvToQuadOp::~SMESHGUI_ConvToQuadOp() { - if ( myDlg ) - delete myDlg; + if ( myDlg ) delete myDlg; + if ( myBadElemsPreview ) delete myBadElemsPreview; } //================================================================================ @@ -237,14 +243,47 @@ bool SMESHGUI_ConvToQuadOp::onApply() SMESH::SMESH_Mesh_var sourceMesh = SMESH::SObjectToInterface( pObj ); if( !myDlg->CurrentRB() ) { - bool aParam = true; + bool force3d = true; if( myDlg->IsEnabledCheck() ) - aParam = myDlg->IsMediumNdsOnGeom(); + force3d = myDlg->IsMediumNdsOnGeom(); if ( sourceMesh->_is_nil() ) - aEditor->ConvertToQuadraticObject( aParam, idSource ); + aEditor->ConvertToQuadraticObject( force3d, idSource ); else - aEditor->ConvertToQuadratic( aParam ); + aEditor->ConvertToQuadratic( force3d ); + + if ( !force3d ) + { + SMESH::ComputeError_var error = aEditor->GetLastError(); + if ( error->hasBadMesh ) + { + if ( myBadElemsPreview ) delete myBadElemsPreview; // viewWindow may change + myBadElemsPreview = new SMESHGUI_MeshEditPreview( viewWindow() ); + + vtkFloatingPointType aPointSize = SMESH::GetFloat("SMESH:node_size",3); + vtkFloatingPointType aLineWidth = SMESH::GetFloat("SMESH:element_width",1); + vtkProperty* prop = vtkProperty::New(); + prop->SetLineWidth( aLineWidth * 3 ); + prop->SetPointSize( aPointSize * 3 ); + prop->SetColor( 250, 0, 250 ); + myBadElemsPreview->GetActor()->SetProperty( prop ); + prop->Delete(); + + SMESH::MeshPreviewStruct_var previewData = aEditor->GetPreviewData(); + myBadElemsPreview->SetData( & previewData.in() ); + myBadElemsPreview->SetVisibility(true); + + SUIT_MessageBox* mb = new SUIT_MessageBox(SUIT_MessageBox::Warning, + tr( "SMESH_WRN_WARNING" ), + tr("EDITERR_NO_MEDIUM_ON_GEOM"), + SUIT_MessageBox::Ok, myDlg); + mb->setWindowModality( Qt::NonModal ); + mb->setAttribute( Qt::WA_DeleteOnClose ); + mb->show(); + connect ( mb, SIGNAL( finished(int) ), this, SLOT( onWarningWinFinished() )); + //connect ( mb, SIGNAL( rejected() ), this, SLOT( onWarningWinFinished() )); + } + } } else { @@ -272,6 +311,18 @@ bool SMESHGUI_ConvToQuadOp::onApply() return aResult; } +//================================================================================ +/*! + * \brief SLOT called when a warning window is closed + */ +//================================================================================ + +void SMESHGUI_ConvToQuadOp::onWarningWinFinished() +{ + if ( myBadElemsPreview ) + myBadElemsPreview->SetVisibility(false); +} + //================================================================================ /*! ConsistMesh * Determines, what elements this mesh contains. diff --git a/src/SMESHGUI/SMESHGUI_ConvToQuadOp.h b/src/SMESHGUI/SMESHGUI_ConvToQuadOp.h index 9e2cbb129..ba30b15e1 100644 --- a/src/SMESHGUI/SMESHGUI_ConvToQuadOp.h +++ b/src/SMESHGUI/SMESHGUI_ConvToQuadOp.h @@ -37,6 +37,7 @@ #include CORBA_SERVER_HEADER(SMESH_Mesh) class SMESHGUI_ConvToQuadDlg; +class SMESHGUI_MeshEditPreview; class SMESHGUI_EXPORT SMESHGUI_ConvToQuadOp : public SMESHGUI_SelectionOp { @@ -60,9 +61,11 @@ protected: protected slots: virtual bool onApply(); void ConnectRadioButtons( int ); + void onWarningWinFinished(); private: SMESHGUI_ConvToQuadDlg* myDlg; + SMESHGUI_MeshEditPreview* myBadElemsPreview; }; #endif // SMESHGUI_CONVTOQUADOP_H diff --git a/src/SMESHGUI/SMESHGUI_CreatePolyhedralVolumeDlg.cxx b/src/SMESHGUI/SMESHGUI_CreatePolyhedralVolumeDlg.cxx index ffc22ecdb..73eae4dd2 100644 --- a/src/SMESHGUI/SMESHGUI_CreatePolyhedralVolumeDlg.cxx +++ b/src/SMESHGUI/SMESHGUI_CreatePolyhedralVolumeDlg.cxx @@ -458,12 +458,12 @@ void SMESHGUI_CreatePolyhedralVolumeDlg::ClickOnApply() int idx = 0; if( addToGroup ) { aGroupName = ComboBox_GroupName->currentText(); - for ( int i = 1; i < ComboBox_GroupName->count(); i++ ) { + for ( int i = 1; i <= ComboBox_GroupName->count(); i++ ) { QString aName = ComboBox_GroupName->itemText( i ); if ( aGroupName == aName && ( i == ComboBox_GroupName->currentIndex() || idx == 0 ) ) idx = i; } - if ( idx > 0 && idx < myGroups.count() ) { + if ( idx > 0 && idx <= myGroups.count() ) { SMESH::SMESH_GroupOnGeom_var aGeomGroup = SMESH::SMESH_GroupOnGeom::_narrow( myGroups[idx-1] ); if ( !aGeomGroup->_is_nil() ) { int res = SUIT_MessageBox::question( this, tr( "SMESH_WRN_WARNING" ), diff --git a/src/SMESHGUI/SMESHGUI_ExtrusionDlg.cxx b/src/SMESHGUI/SMESHGUI_ExtrusionDlg.cxx index c75af4f45..fa367fd51 100644 --- a/src/SMESHGUI/SMESHGUI_ExtrusionDlg.cxx +++ b/src/SMESHGUI/SMESHGUI_ExtrusionDlg.cxx @@ -280,15 +280,22 @@ SMESHGUI_ExtrusionDlg::SMESHGUI_ExtrusionDlg (SMESHGUI* theModule) mySMESHGUI->SetActiveDialogBox(this); // Costruction of the logical filter for the elements: mesh/sub-mesh/group - SMESH_TypeFilter* aMeshOrSubMeshFilter = new SMESH_TypeFilter (MESHorSUBMESH); - SMESH_TypeFilter* aSmeshGroupFilter = new SMESH_TypeFilter (GROUP); - QList aListOfFilters; - if (aMeshOrSubMeshFilter) aListOfFilters.append(aMeshOrSubMeshFilter); - if (aSmeshGroupFilter) aListOfFilters.append(aSmeshGroupFilter); - - myMeshOrSubMeshOrGroupFilter = - new SMESH_LogicalFilter (aListOfFilters, SMESH_LogicalFilter::LO_OR); + aListOfFilters.append(new SMESH_TypeFilter (MESH)); + aListOfFilters.append(new SMESH_TypeFilter (SUBMESH_VERTEX)); + aListOfFilters.append(new SMESH_TypeFilter (GROUP_NODE)); + myMeshOrSubMeshOrGroupFilter0D = + new SMESH_LogicalFilter (aListOfFilters, SMESH_LogicalFilter::LO_OR, /*takeOwnership=*/true); + aListOfFilters[0] = new SMESH_TypeFilter (MESH); + aListOfFilters[1] = new SMESH_TypeFilter (SUBMESH_EDGE); + aListOfFilters[2] = new SMESH_TypeFilter (GROUP_EDGE); + myMeshOrSubMeshOrGroupFilter1D = + new SMESH_LogicalFilter (aListOfFilters, SMESH_LogicalFilter::LO_OR, /*takeOwnership=*/true); + aListOfFilters[0] = new SMESH_TypeFilter (MESH); + aListOfFilters[1] = new SMESH_TypeFilter (SUBMESH_FACE); + aListOfFilters[2] = new SMESH_TypeFilter (GROUP_FACE); + myMeshOrSubMeshOrGroupFilter2D = + new SMESH_LogicalFilter (aListOfFilters, SMESH_LogicalFilter::LO_OR, /*takeOwnership=*/true); myHelpFileName = "extrusion_page.html"; @@ -351,6 +358,9 @@ SMESHGUI_ExtrusionDlg::~SMESHGUI_ExtrusionDlg() myFilterDlg->setParent( 0 ); delete myFilterDlg; } + if ( myMeshOrSubMeshOrGroupFilter0D ) delete myMeshOrSubMeshOrGroupFilter0D; + if ( myMeshOrSubMeshOrGroupFilter1D ) delete myMeshOrSubMeshOrGroupFilter1D; + if ( myMeshOrSubMeshOrGroupFilter2D ) delete myMeshOrSubMeshOrGroupFilter2D; } //================================================================================= @@ -898,31 +908,38 @@ void SMESHGUI_ExtrusionDlg::SetEditCurrentArgument() if (send == SelectElementsButton) { myEditCurrentArgument = (QWidget*)LineEditElements; - if (CheckBoxMesh->isChecked()) { + if (CheckBoxMesh->isChecked()) + { if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI )) aViewWindow->SetSelectionMode(ActorSelection); - mySelectionMgr->installFilter(myMeshOrSubMeshOrGroupFilter); - } else { + switch( GetConstructorId() ) { + case 0: mySelectionMgr->installFilter(myMeshOrSubMeshOrGroupFilter0D); break; + case 1: mySelectionMgr->installFilter(myMeshOrSubMeshOrGroupFilter1D); break; + case 2: mySelectionMgr->installFilter(myMeshOrSubMeshOrGroupFilter2D); break; + } + } + else + { int aConstructorId = GetConstructorId(); switch(aConstructorId) { - case 0: - { - if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI )) - aViewWindow->SetSelectionMode(NodeSelection); - break; - } - case 1: - { - if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI )) - aViewWindow->SetSelectionMode(EdgeSelection); - break; - } - case 2: - { - if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI )) + case 0: + { + if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI )) + aViewWindow->SetSelectionMode(NodeSelection); + break; + } + case 1: + { + if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI )) + aViewWindow->SetSelectionMode(EdgeSelection); + break; + } + case 2: + { + if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI )) aViewWindow->SetSelectionMode(FaceSelection); - break; - } + break; + } } } } @@ -1028,13 +1045,20 @@ void SMESHGUI_ExtrusionDlg::onSelectMesh (bool toSelectMesh) mySelectionMgr->clearFilters(); - if (toSelectMesh) { + if (toSelectMesh) + { if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI )) aViewWindow->SetSelectionMode(ActorSelection); - mySelectionMgr->installFilter(myMeshOrSubMeshOrGroupFilter); + switch( GetConstructorId() ) { + case 0: mySelectionMgr->installFilter(myMeshOrSubMeshOrGroupFilter0D); break; + case 1: mySelectionMgr->installFilter(myMeshOrSubMeshOrGroupFilter1D); break; + case 2: mySelectionMgr->installFilter(myMeshOrSubMeshOrGroupFilter2D); break; + } LineEditElements->setReadOnly(true); LineEditElements->setValidator(0); - } else { + } + else + { int aConstructorId = GetConstructorId(); switch(aConstructorId) { case 0: diff --git a/src/SMESHGUI/SMESHGUI_ExtrusionDlg.h b/src/SMESHGUI/SMESHGUI_ExtrusionDlg.h index dd0b741a0..330951397 100644 --- a/src/SMESHGUI/SMESHGUI_ExtrusionDlg.h +++ b/src/SMESHGUI/SMESHGUI_ExtrusionDlg.h @@ -94,7 +94,9 @@ private: SMESH::long_array_var myElementsId; SMESH_Actor* myActor; Handle(SALOME_InteractiveObject) myIO; - SUIT_SelectionFilter* myMeshOrSubMeshOrGroupFilter; + SUIT_SelectionFilter* myMeshOrSubMeshOrGroupFilter0D; + SUIT_SelectionFilter* myMeshOrSubMeshOrGroupFilter1D; + SUIT_SelectionFilter* myMeshOrSubMeshOrGroupFilter2D; // widgets QGroupBox* ConstructorsBox; diff --git a/src/SMESHGUI/SMESHGUI_FilterDlg.cxx b/src/SMESHGUI/SMESHGUI_FilterDlg.cxx index ac756a16c..d29ae2c82 100755 --- a/src/SMESHGUI/SMESHGUI_FilterDlg.cxx +++ b/src/SMESHGUI/SMESHGUI_FilterDlg.cxx @@ -2647,18 +2647,18 @@ SMESHGUI_FilterDlg::~SMESHGUI_FilterDlg() // name : SMESHGUI_FilterDlg::Init // Purpose : Init dialog fields, connect signals and slots, show dialog //======================================================================= -void SMESHGUI_FilterDlg::Init (const int type) +void SMESHGUI_FilterDlg::Init (const int type, const bool setInViewer) { QList aTypes; aTypes.append(type); - Init(aTypes); + Init(aTypes,setInViewer); } //======================================================================= // name : SMESHGUI_FilterDlg::Init // Purpose : Init dialog fields, connect signals and slots, show dialog //======================================================================= -void SMESHGUI_FilterDlg::Init (const QList& theTypes) +void SMESHGUI_FilterDlg::Init (const QList& theTypes, const bool setInViewer) { mySourceWg = 0; myTypes = theTypes; @@ -2713,7 +2713,7 @@ void SMESHGUI_FilterDlg::Init (const QList& theTypes) if (myInsertState.contains(theTypes.first())) mySetInViewer->setChecked(myInsertState[ theTypes.first() ]); else - mySetInViewer->setChecked(true); + mySetInViewer->setChecked(setInViewer); mySourceGrp->button(myApplyToState.contains(theTypes.first()) ? myApplyToState[ theTypes.first() ] : @@ -3008,7 +3008,7 @@ bool SMESHGUI_FilterDlg::isValid() const //======================================================================= // name : SMESHGUI_FilterDlg::SetSourceWg -// Purpose : Set widget of parent dialog containing idsto be filtered if +// Purpose : Set widget of parent dialog containing ids to be filtered if // user select corresponding source radio button //======================================================================= void SMESHGUI_FilterDlg::SetSourceWg (QWidget* theWg, @@ -3501,6 +3501,8 @@ void SMESHGUI_FilterDlg::updateSelection() } else { + mySelector->SetSelectionMode( getSelMode( myTable->GetType() )); + if (myIsSelectionChanged) { // 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_FilterDlg.h b/src/SMESHGUI/SMESHGUI_FilterDlg.h index ace63067b..4501a9d37 100755 --- a/src/SMESHGUI/SMESHGUI_FilterDlg.h +++ b/src/SMESHGUI/SMESHGUI_FilterDlg.h @@ -222,8 +222,8 @@ public: SMESHGUI_FilterDlg( SMESHGUI*, const int ); virtual ~SMESHGUI_FilterDlg(); - void Init( const QList& ); - void Init( const int ); + void Init( const QList&, const bool setInViewer=true ); + void Init( const int, const bool setInViewer=true ); void SetSelection(); void SetMesh (SMESH::SMESH_Mesh_var); diff --git a/src/SMESHGUI/SMESHGUI_GroupDlg.cxx b/src/SMESHGUI/SMESHGUI_GroupDlg.cxx index 10995de19..668681496 100644 --- a/src/SMESHGUI/SMESHGUI_GroupDlg.cxx +++ b/src/SMESHGUI/SMESHGUI_GroupDlg.cxx @@ -805,7 +805,7 @@ void SMESHGUI_GroupDlg::setSelectionMode (int theMode) if ( aViewWindow ) aViewWindow->SetSelectionMode(isSelectAll ? ActorSelection : EdgeSelection); break; case grpBallSelection: - //if ( aViewWindow ) aViewWindow->SetSelectionMode(isSelectAll ? ActorSelection : BallSelection); + if ( aViewWindow ) aViewWindow->SetSelectionMode(isSelectAll ? ActorSelection : BallSelection); break; case grpFaceSelection: if ( aViewWindow ) aViewWindow->SetSelectionMode(isSelectAll ? ActorSelection : FaceSelection); @@ -1126,17 +1126,21 @@ bool SMESHGUI_GroupDlg::onApply() if ( aMeshGroupSO ) if(SMESH_Actor *anActor = SMESH::FindActorByEntry(aMeshGroupSO->GetID().c_str())) { anActor->setName(myName->text().toLatin1().data()); + QColor c; + int delta; switch ( myTypeId ) { case grpNodeSelection: anActor->SetNodeColor( aColor.R, aColor.G, aColor.B ); break; case grpBallSelection: anActor->SetBallColor( aColor.R, aColor.G, aColor.B ); break; case grpEdgeSelection: anActor->SetEdgeColor( aColor.R, aColor.G, aColor.B ); break; - case grpFaceSelection: case grpVolumeSelection: + SMESH::GetColor("SMESH", "volume_color", c , delta, "255,0,170|-100"); + anActor->SetVolumeColor( aColor.R, aColor.G, aColor.B, delta ); break; + break; + case grpFaceSelection: default: - QColor c; - int delta; SMESH::GetColor("SMESH", "fill_color", c , delta, "0,170,255|-100"); anActor->SetSufaceColor( aColor.R, aColor.G, aColor.B, delta ); break; + break; } } } @@ -1759,7 +1763,7 @@ void SMESHGUI_GroupDlg::onAdd() break; case grpBallSelection: aType = SMESH::BALL; - //mySelector->SetSelectionMode(BallSelection); + mySelector->SetSelectionMode(BallSelection); break; case grpEdgeSelection: aType = SMESH::EDGE; @@ -2438,7 +2442,7 @@ void SMESHGUI_GroupDlg::setDefaultGroupColor() if( !isAutoColor ) { int r = 0, g = 0, b = 0; - SMESH::GetColor( "SMESH", "fill_color", r, g, b, QColor( 0, 170, 255 ) ); + SMESH::GetColor( "SMESH", "default_grp_color", r, g, b, QColor( 255, 170, 0 ) ); aQColor.setRgb( r, g, b ); } else diff --git a/src/SMESHGUI/SMESHGUI_GroupOnShapeDlg.cxx b/src/SMESHGUI/SMESHGUI_GroupOnShapeDlg.cxx index 2bfdd1bc9..e62b015c2 100644 --- a/src/SMESHGUI/SMESHGUI_GroupOnShapeDlg.cxx +++ b/src/SMESHGUI/SMESHGUI_GroupOnShapeDlg.cxx @@ -353,10 +353,10 @@ bool SMESHGUI_GroupOnShapeOp::onApply() anEntryList.append( aSObject->GetID().c_str() ); } } - update( UF_ObjBrowser | UF_Model ); - SMESHGUI::Modified(); + update( UF_ObjBrowser | UF_Model ); + // Re-init controls to create the next group myElemGeoIDs.clear(); myNodeGeoIDs.clear(); @@ -367,8 +367,6 @@ bool SMESHGUI_GroupOnShapeOp::onApply() myDlg->myNodeGeomBtn->setChecked(false); myDlg->updateButtons(); - update( UF_ObjBrowser | UF_Model ); - if( LightApp_Application* anApp = dynamic_cast( SUIT_Session::session()->activeApplication() ) ) anApp->browseObjects( anEntryList, isApplyAndClose() ); diff --git a/src/SMESHGUI/SMESHGUI_Hypotheses.cxx b/src/SMESHGUI/SMESHGUI_Hypotheses.cxx index 3d0baf890..c42a940d4 100644 --- a/src/SMESHGUI/SMESHGUI_Hypotheses.cxx +++ b/src/SMESHGUI/SMESHGUI_Hypotheses.cxx @@ -653,10 +653,10 @@ void SMESHGUI_HypothesisDlg::onHelp() if(myCreator) { QVariant pluginName = myCreator->property( PLUGIN_NAME ); if( pluginName.isValid() ) { - QString rootDir = pluginName.toString() + "PLUGIN_ROOT_DIR"; - QString varValue = QString( getenv(rootDir.toLatin1().constData())); - if(!varValue.isEmpty()) - name = pluginName.toString() + "PLUGIN"; + QString rootDir = pluginName.toString() + "PLUGIN_ROOT_DIR"; + QString varValue = QString( getenv(rootDir.toLatin1().constData())); + if(!varValue.isEmpty()) + name = pluginName.toString() + "PLUGIN"; } } app->onHelpContextModule(name, myHelpFileName); diff --git a/src/SMESHGUI/SMESHGUI_HypothesesUtils.cxx b/src/SMESHGUI/SMESHGUI_HypothesesUtils.cxx index d7e3e6ce6..fde2ae609 100644 --- a/src/SMESHGUI/SMESHGUI_HypothesesUtils.cxx +++ b/src/SMESHGUI/SMESHGUI_HypothesesUtils.cxx @@ -452,11 +452,11 @@ namespace SMESH // BUG 0020378 //myHypCreatorMap[aHypType] = aCreator; - //rnv : This dynamic property of the QObject stores the name of the plugin. - // It is used to obtain plugin root dir environment variable + //rnv : This dynamic property of the QObject stores the name of the plugin. + // It is used to obtain plugin root dir environment variable // in the SMESHGUI_HypothesisDlg class. Plugin root dir environment - // variable is used to display documentation. - aCreator->setProperty(PLUGIN_NAME,aHypData->PluginName); + // variable is used to display documentation. + aCreator->setProperty(PLUGIN_NAME,aHypData->PluginName); } } } diff --git a/src/SMESHGUI/SMESHGUI_MeshInfosBox.cxx b/src/SMESHGUI/SMESHGUI_MeshInfosBox.cxx index 17f653938..a56fa2c5e 100644 --- a/src/SMESHGUI/SMESHGUI_MeshInfosBox.cxx +++ b/src/SMESHGUI/SMESHGUI_MeshInfosBox.cxx @@ -319,6 +319,15 @@ SMESHGUI_MeshInfosBox::SMESHGUI_MeshInfosBox(const bool full, QWidget* theParent my0DElem = new QLabel( this ); l->addWidget( my0DElem, row, 1 ); + // balls + row = l->rowCount(); // retrieve current row count + // -- + lab = new QLabel(COLONIZE(tr("SMESH_MESHINFO_BALLS")), this ); + l->addWidget( lab, row, 0 ); + // -- + myBall = new QLabel( this ); + l->addWidget( myBall, row, 1 ); + addSeparator(this); // add separator // edges diff --git a/src/SMESHGUI/SMESHGUI_NodesDlg.cxx b/src/SMESHGUI/SMESHGUI_NodesDlg.cxx index 3f369e790..d82ec9c1d 100644 --- a/src/SMESHGUI/SMESHGUI_NodesDlg.cxx +++ b/src/SMESHGUI/SMESHGUI_NodesDlg.cxx @@ -452,12 +452,12 @@ bool SMESHGUI_NodesDlg::ClickOnApply() int idx = 0; if( addToGroup ) { aGroupName = ComboBox_GroupName->currentText(); - for ( int i = 1; i < ComboBox_GroupName->count(); i++ ) { + for ( int i = 1; i <= ComboBox_GroupName->count(); i++ ) { QString aName = ComboBox_GroupName->itemText( i ); if ( aGroupName == aName && ( i == ComboBox_GroupName->currentIndex() || idx == 0 ) ) idx = i; } - if ( idx > 0 && idx < myGroups.count() ) { + if ( idx > 0 && idx <= myGroups.count() ) { SMESH::SMESH_GroupOnGeom_var aGeomGroup = SMESH::SMESH_GroupOnGeom::_narrow( myGroups[idx-1] ); if ( !aGeomGroup->_is_nil() ) { int res = SUIT_MessageBox::question( this, tr( "SMESH_WRN_WARNING" ), diff --git a/src/SMESHGUI/SMESHGUI_Preferences_ColorDlg.cxx b/src/SMESHGUI/SMESHGUI_Preferences_ColorDlg.cxx deleted file mode 100644 index c7b6d5e7d..000000000 --- a/src/SMESHGUI/SMESHGUI_Preferences_ColorDlg.cxx +++ /dev/null @@ -1,570 +0,0 @@ -// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE -// -// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, -// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License. -// -// 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 -// - -// SMESH SMESHGUI : GUI for SMESH component -// File : SMESHGUI_Preferences_ColorDlg.cxx -// Author : Nicolas REJNERI, Open CASCADE S.A.S. -// SMESH includes -// -#include "SMESHGUI_Preferences_ColorDlg.h" - -#include "SMESHGUI.h" -#include "SMESHGUI_SpinBox.h" -#include "SMESHGUI_Utils.h" - -// SALOME GUI includes -#include -#include -#include -#include -#include -#include -#include -#include - -// Qt includes -#include -#include -#include -#include -#include -#include -#include -#include - -#define SPACING 6 -#define MARGIN 11 - -//================================================================================= -// function : SMESHGUI_Preferences_ColorDlg() -// purpose : Constructs a SMESHGUI_Preferences_ColorDlg which is a child -// of 'parent', with the name 'name' and widget flags set to 'f' -// The dialog will by default be modeless, unless you -// set'modal' to true to construct a modal dialog. -//================================================================================= -SMESHGUI_Preferences_ColorDlg::SMESHGUI_Preferences_ColorDlg( SMESHGUI* theModule ) - : QDialog( SMESH::GetDesktop( theModule ) ), - mySMESHGUI( theModule ) -{ - setModal( true ); - setWindowTitle( tr( "DIALOG_TITLE" ) ); - setSizeGripEnabled( true ); - - // ------------------------------- - QVBoxLayout* topLayout = new QVBoxLayout( this ); - topLayout->setSpacing( SPACING ); - topLayout->setMargin( MARGIN ); - - // ------------------------------- - QGroupBox* ButtonGroup1 = new QGroupBox( tr( "GRP_ELEMENTS" ), this ); - QGridLayout* ButtonGroup1Layout = new QGridLayout( ButtonGroup1 ); - ButtonGroup1Layout->setSpacing( SPACING ); - ButtonGroup1Layout->setMargin( MARGIN ); - - QLabel* TextLabel_Fill = new QLabel( tr( "SURFACE_COLOR_LBL" ), ButtonGroup1 ); - - toolSurfColor = new QtxBiColorTool(ButtonGroup1); - toolSurfColor->setText( tr( "BACKSURFACE_COLOR_LBL" )); - - QLabel* TextLabel_Outline = new QLabel( tr( "OUTLINE_COLOR_LBL" ), ButtonGroup1 ); - btnOutlineColor = new QtxColorButton( ButtonGroup1 ); - - QLabel* TextLabel_Wireframe = new QLabel( tr( "WIREFRAME_COLOR_LBL" ), ButtonGroup1 ); - btnWireframeColor = new QtxColorButton( ButtonGroup1 ); - - QLabel* TextLabel_0DElements_Color = new QLabel( tr( "0D_ELEMENTS_COLOR_LBL" ), ButtonGroup1 ); - btn0DElementsColor = new QtxColorButton( ButtonGroup1 ); - - QLabel* TextLabel_0DElements_Size = new QLabel( tr( "0D_ELEMENTS_SIZE_LBL" ), ButtonGroup1 ); - SpinBox_0DElements_Size = new SalomeApp_IntSpinBox( ButtonGroup1 ); - SpinBox_0DElements_Size->setAcceptNames( false ); // No Notebook variables allowed - SpinBox_0DElements_Size->setRange( 1, 10 ); - SpinBox_0DElements_Size->setSingleStep( 1 ); - SpinBox_0DElements_Size->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) ); - SpinBox_0DElements_Size->setButtonSymbols( QSpinBox::PlusMinus ); - - QLabel* TextLabel_BallElem_Color = new QLabel( tr( "0D_ELEMENTS_COLOR_LBL" ), ButtonGroup1 ); - btnBallElemColor = new QtxColorButton( ButtonGroup1 ); - - QLabel* TextLabel_BallElem_Size = new QLabel( tr( "BALLELEM_SIZE_LBL" ), ButtonGroup1 ); - SpinBox_BallElem_Size = new SalomeApp_IntSpinBox( ButtonGroup1 ); - SpinBox_BallElem_Size->setAcceptNames( false ); // No Notebook variables allowed - SpinBox_BallElem_Size->setRange( 1, 10 ); - SpinBox_BallElem_Size->setSingleStep( 1 ); - SpinBox_BallElem_Size->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) ); - SpinBox_BallElem_Size->setButtonSymbols( QSpinBox::PlusMinus ); - - QLabel* TextLabel_Width = new QLabel( tr( "LINE_WIDTH_LBL" ), ButtonGroup1 ); - SpinBox_Width = new SalomeApp_IntSpinBox( ButtonGroup1 ); - SpinBox_Width->setAcceptNames( false ); // No Notebook variables allowed - SpinBox_Width->setRange( 1, 5 ); - SpinBox_Width->setSingleStep( 1 ); - SpinBox_Width->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) ); - SpinBox_Width->setButtonSymbols( QSpinBox::PlusMinus ); - - QLabel* TextLabel_ShrinkCoeff = new QLabel( tr( "SHRINK_COEF_LBL" ), ButtonGroup1 ); - SpinBox_Shrink = new SalomeApp_IntSpinBox( ButtonGroup1 ); - SpinBox_Shrink->setAcceptNames( false ); // No Notebook variables allowed - SpinBox_Shrink->setRange( 20, 100 ); - SpinBox_Shrink->setSingleStep( 1 ); - SpinBox_Shrink->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) ); - SpinBox_Shrink->setButtonSymbols( QSpinBox::PlusMinus ); - - ButtonGroup1Layout->addWidget( TextLabel_Fill, 0, 0 ); - ButtonGroup1Layout->addWidget( toolSurfColor, 0, 1, 1, 3 ); - - ButtonGroup1Layout->addWidget( TextLabel_Outline, 1, 0 ); - ButtonGroup1Layout->addWidget( btnOutlineColor, 1, 1 ); - ButtonGroup1Layout->addWidget( TextLabel_Wireframe, 1, 2 ); - ButtonGroup1Layout->addWidget( btnWireframeColor, 1, 3 ); - - ButtonGroup1Layout->addWidget( TextLabel_0DElements_Color, 2, 0 ); - ButtonGroup1Layout->addWidget( btn0DElementsColor, 2, 1 ); - - ButtonGroup1Layout->addWidget( TextLabel_0DElements_Size, 2, 2 ); - ButtonGroup1Layout->addWidget( SpinBox_0DElements_Size, 2, 3 ); - - ButtonGroup1Layout->addWidget( TextLabel_BallElem_Color, 2, 0 ); - ButtonGroup1Layout->addWidget( btnBallElemColor, 2, 1 ); - - ButtonGroup1Layout->addWidget( TextLabel_BallElem_Size, 2, 2 ); - ButtonGroup1Layout->addWidget( SpinBox_BallElem_Size, 2, 3 ); - - ButtonGroup1Layout->addWidget( TextLabel_Width, 3, 0 ); - ButtonGroup1Layout->addWidget( SpinBox_Width, 3, 1 ); - ButtonGroup1Layout->addWidget( TextLabel_ShrinkCoeff, 3, 2 ); - ButtonGroup1Layout->addWidget( SpinBox_Shrink, 3, 3 ); - - // ------------------------------- - QGroupBox* ButtonGroup2 = new QGroupBox( tr( "GRP_NODES" ), this ); - QGridLayout* ButtonGroup2Layout = new QGridLayout( ButtonGroup2 ); - ButtonGroup2Layout->setSpacing( SPACING ); - ButtonGroup2Layout->setMargin( MARGIN ); - - QLabel* TextLabel_Nodes_Color = new QLabel( tr( "NODES_COLOR_LBL" ), ButtonGroup2 ); - btnNodeColor = new QtxColorButton( ButtonGroup2 ); - - QGroupBox* MarkerGroup = new QGroupBox( tr( "NODES_MARKER_LBL" ), ButtonGroup2 ); - QVBoxLayout* MarkerGroupLayout = new QVBoxLayout( MarkerGroup ); - MarkerGroupLayout->setSpacing( 0 ); - MarkerGroupLayout->setMargin( 0 ); - - MarkerWidget = new VTKViewer_MarkerWidget( MarkerGroup ); - - MarkerGroupLayout->addWidget( MarkerWidget ); - - ButtonGroup2Layout->addWidget( TextLabel_Nodes_Color, 0, 0 ); - ButtonGroup2Layout->addWidget( btnNodeColor, 0, 1 ); - ButtonGroup2Layout->addWidget( MarkerGroup, 1, 0, 1, 3 ); - ButtonGroup2Layout->setColumnStretch( 2, 1 ); - - // ------------------------------- - QGroupBox* ButtonGroup3 = new QGroupBox( tr( "GRP_ORIENTATION" ), this ); - QGridLayout* ButtonGroup3Layout = new QGridLayout( ButtonGroup3 ); - ButtonGroup3Layout->setSpacing( SPACING ); - ButtonGroup3Layout->setMargin( MARGIN ); - - QLabel* TextLabel_Orientation_Color = new QLabel( tr( "ORIENTATION_COLOR_LBL" ), ButtonGroup3 ); - btnOrientationColor = new QtxColorButton( ButtonGroup3 ); - - QLabel* TextLabel_Orientation_Scale = new QLabel( tr( "ORIENTATION_SCALE_LBL" ), ButtonGroup3 ); - SpinBox_Orientation_Scale = new SMESHGUI_SpinBox( ButtonGroup3 ); - SpinBox_Orientation_Scale->setAcceptNames( false ); // No Notebook variables allowed - SpinBox_Orientation_Scale->RangeStepAndValidator( .05, .5, .05, "parametric_precision" ); - SpinBox_Orientation_Scale->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) ); - SpinBox_Orientation_Scale->setButtonSymbols( QSpinBox::PlusMinus ); - - CheckBox_Orientation_3DVectors = new QCheckBox( tr( "3D_VECTORS_LBL" ), ButtonGroup3 ); - - ButtonGroup3Layout->addWidget( TextLabel_Orientation_Color, 0, 0 ); - ButtonGroup3Layout->addWidget( btnOrientationColor, 0, 1 ); - ButtonGroup3Layout->addWidget( TextLabel_Orientation_Scale, 0, 2 ); - ButtonGroup3Layout->addWidget( SpinBox_Orientation_Scale, 0, 3 ); - ButtonGroup3Layout->addWidget( CheckBox_Orientation_3DVectors, 1, 0, 1, 4 ); - - // ------------------------------- - QGroupBox* ButtonGroup4 = new QGroupBox( tr( "GRP_SELECTION" ), this ); - QGridLayout* ButtonGroup4Layout = new QGridLayout( ButtonGroup4 ); - ButtonGroup3Layout->setSpacing( SPACING ); - ButtonGroup3Layout->setMargin( MARGIN ); - - QLabel* TextLabel_Selection_Color = new QLabel( tr( "SELECTION_COLOR_LBL" ), ButtonGroup4 ); - btnSelectionColor = new QtxColorButton( ButtonGroup4 ); - - QLabel* TextLabel_Preselection_Color = new QLabel( tr( "PRESELECTION_COLOR_LBL" ), ButtonGroup4 ); - btnPreselectionColor = new QtxColorButton( ButtonGroup4 ); - - ButtonGroup4Layout->addWidget( TextLabel_Selection_Color, 0, 0 ); - ButtonGroup4Layout->addWidget( btnSelectionColor, 0, 1 ); - ButtonGroup4Layout->addWidget( TextLabel_Preselection_Color, 0, 2 ); - ButtonGroup4Layout->addWidget( btnPreselectionColor, 0, 3 ); - - // ------------------------------- - QGroupBox* GroupButtons = new QGroupBox( this ); - QHBoxLayout* GroupButtonsLayout = new QHBoxLayout( GroupButtons ); - GroupButtonsLayout->setSpacing( SPACING ); - GroupButtonsLayout->setMargin( MARGIN ); - - QPushButton* buttonOk = new QPushButton( tr( "SMESH_BUT_OK" ), GroupButtons ); - buttonOk->setAutoDefault( true ); - buttonOk->setDefault( true ); - - QPushButton* buttonCancel = new QPushButton( tr( "SMESH_BUT_CANCEL" ), GroupButtons ); - buttonCancel->setAutoDefault( true ); - - QPushButton* buttonHelp = new QPushButton( tr( "SMESH_BUT_HELP" ), GroupButtons ); - buttonHelp->setAutoDefault( true ); - - GroupButtonsLayout->addWidget( buttonOk ); - GroupButtonsLayout->addSpacing( 10 ); - GroupButtonsLayout->addStretch(); - GroupButtonsLayout->addWidget( buttonCancel ); - GroupButtonsLayout->addWidget( buttonHelp ); - - // ------------------------------- - topLayout->addWidget( ButtonGroup1 ); - topLayout->addWidget( ButtonGroup2 ); - topLayout->addWidget( ButtonGroup3 ); - // rnv: Selection and preselection colors are defined only in the Preferences - // topLayout->addWidget( ButtonGroup4 ); - ButtonGroup4->hide(); - topLayout->addWidget( GroupButtons ); - - // ------------------------------- - mySMESHGUI->SetActiveDialogBox( this ); - - myHelpFileName = "colors_size_page.html"; - - /* signals and slots connections */ - connect( buttonOk, SIGNAL( clicked() ), this, SLOT( ClickOnOk() ) ); - connect( buttonCancel, SIGNAL( clicked() ), this, SLOT( ClickOnCancel() ) ); - connect( buttonHelp, SIGNAL( clicked() ), this, SLOT( ClickOnHelp() ) ); - - connect( mySMESHGUI, SIGNAL ( SignalDeactivateActiveDialog() ), - this, SLOT( DeactivateActiveDialog() ) ); - /* to close dialog if study change */ - connect( mySMESHGUI, SIGNAL ( SignalCloseAllDialogs() ), - this, SLOT( ClickOnCancel() ) ); -} - -//================================================================================= -// function : ~SMESHGUI_Preferences_ColorDlg() -// purpose : Destructor -//================================================================================= -SMESHGUI_Preferences_ColorDlg::~SMESHGUI_Preferences_ColorDlg() -{ -} - -//================================================================================= -// function : ClickOnOk() -// purpose : -//================================================================================= -void SMESHGUI_Preferences_ColorDlg::ClickOnOk() -{ - mySMESHGUI->ResetState(); - accept(); -} - -//================================================================================= -// function : ClickOnCancel() -// purpose : -//================================================================================= -void SMESHGUI_Preferences_ColorDlg::ClickOnCancel() -{ - mySMESHGUI->ResetState(); - reject(); -} - -//================================================================================= -// function : ClickOnHelp() -// purpose : -//================================================================================= -void SMESHGUI_Preferences_ColorDlg::ClickOnHelp() -{ - LightApp_Application* app = (LightApp_Application*)(SUIT_Session::session()->activeApplication()); - if (app) - app->onHelpContextModule(mySMESHGUI ? app->moduleName(mySMESHGUI->moduleName()) : QString(""), myHelpFileName); - else { - QString platform; -#ifdef WIN32 - platform = "winapplication"; -#else - platform = "application"; -#endif - SUIT_MessageBox::warning(this, tr("WRN_WARNING"), - tr("EXTERNAL_BROWSER_CANNOT_SHOW_PAGE"). - arg(app->resourceMgr()->stringValue("ExternalBrowser", - platform)). - arg(myHelpFileName)); - } -} - -//================================================================================= -// function : DeactivateActiveDialog() -// purpose : -//================================================================================= -void SMESHGUI_Preferences_ColorDlg::DeactivateActiveDialog() -{ -} - -//================================================================================= -// function : closeEvent() -// purpose : -//================================================================================= -void SMESHGUI_Preferences_ColorDlg::closeEvent( QCloseEvent* ) -{ - ClickOnCancel(); /* same than click on cancel button */ -} - -//================================================================================= -// function : ActivateThisDialog() -// purpose : -//================================================================================= -void SMESHGUI_Preferences_ColorDlg::ActivateThisDialog() -{ - /* Emit a signal to deactivate any active dialog */ - mySMESHGUI->EmitSignalDeactivateDialog(); -} - -//================================================================================= -// function : SetColor() -// purpose : -//================================================================================= -void SMESHGUI_Preferences_ColorDlg::SetColor( int type, const QColor& color ) -{ - switch ( type ) { - case 1 : toolSurfColor->setMainColor( color ); break; // fill - case 2 : btnWireframeColor->setColor( color ); break; // wireframe - case 3 : btnNodeColor->setColor( color ); break; // node - case 4 : btnOutlineColor->setColor( color ); break; // outline - case 5 : btn0DElementsColor->setColor( color ); break; // 0d elements - case 6 : btnBallElemColor->setColor( color ); break; // ball elements - case 7 : btnOrientationColor->setColor( color ); break; // orientation of faces - case 8 : btnSelectionColor->setColor( color ); break; // selection color - case 9 : btnPreselectionColor->setColor( color ); break; // pre-selection color - default: break; - } -} - -//================================================================================= -// function : GetColor() -// purpose : -//================================================================================= -QColor SMESHGUI_Preferences_ColorDlg::GetColor( int type ) -{ - QColor color; - switch ( type ) { - case 1 : color = toolSurfColor->mainColor(); break; // fill - case 2 : color = btnWireframeColor->color(); break; // outline - case 3 : color = btnNodeColor->color(); break; // node - case 4 : color = btnOutlineColor->color(); break; // node - case 5 : color = btn0DElementsColor->color(); break; // 0d elements - case 6 : color = btnBallElemColor->color(); break; // 0d elements - case 7 : color = btnOrientationColor->color(); break; // orientation of faces - case 8 : color = btnSelectionColor->color(); break; // selection color - case 9 : color = btnPreselectionColor->color(); break; // pre-selection color - - default: break; - } - return color; -} - -//================================================================================= -// function : SetIntValue() -// purpose : -//================================================================================= -void SMESHGUI_Preferences_ColorDlg::SetIntValue( int type, int value ) -{ - switch ( type ) { - case 1 : SpinBox_Width->setValue( value ); break; // width - case 2 : SpinBox_Shrink->setValue( value ); break; // shrink coeff - case 3 : SpinBox_0DElements_Size->setValue( value ); break; // 0d elements - case 4 : SpinBox_BallElem_Size->setValue( value ); break; // 0d elements - default: break; - } -} - -//================================================================================= -// function : GetIntValue() -// purpose : -//================================================================================= -int SMESHGUI_Preferences_ColorDlg::GetIntValue( int type ) -{ - int res = 0; - switch ( type ) { - case 1 : res = SpinBox_Width->value(); break; // width - case 2 : res = SpinBox_Shrink->value(); break; // shrink coeff - case 3 : res = SpinBox_0DElements_Size->value(); break; // 0d elements - case 4 : res = SpinBox_BallElem_Size->value(); break; // 0d elements - default: break; - } - return res; -} - -//================================================================================= -// function : SetDoubleValue() -// purpose : -//================================================================================= -void SMESHGUI_Preferences_ColorDlg::SetDoubleValue( int type, double value ) -{ - switch ( type ) { - case 1 : SpinBox_Orientation_Scale->setValue( value ); break; // orientation scale - default: break; - } -} - -//================================================================================= -// function : GetDoubleValue() -// purpose : -//================================================================================= -double SMESHGUI_Preferences_ColorDlg::GetDoubleValue( int type ) -{ - double res = 0; - switch ( type ) { - case 1 : res = SpinBox_Orientation_Scale->value(); break; // orientation scale - default: break; - } - return res; -} - -//================================================================================= -// function : SetBooleanValue() -// purpose : -//================================================================================= -void SMESHGUI_Preferences_ColorDlg::SetBooleanValue( int type, bool value ) -{ - switch ( type ) { - case 1 : CheckBox_Orientation_3DVectors->setChecked( value ); break; // 3D vectors - default: break; - } -} - -//================================================================================= -// function : GetBooleanValue() -// purpose : -//================================================================================= -bool SMESHGUI_Preferences_ColorDlg::GetBooleanValue( int type ) -{ - bool res = false; - switch ( type ) { - case 1 : res = CheckBox_Orientation_3DVectors->isChecked(); break; // 3D vectors - default: break; - } - return res; -} - -//================================================================================= -// function : setCustomMarkerMap() -// purpose : -//================================================================================= -void SMESHGUI_Preferences_ColorDlg::setCustomMarkerMap( VTK::MarkerMap theMarkerMap ) -{ - MarkerWidget->setCustomMarkerMap( theMarkerMap ); -} - -//================================================================================= -// function : getCustomMarkerMap() -// purpose : -//================================================================================= -VTK::MarkerMap SMESHGUI_Preferences_ColorDlg::getCustomMarkerMap() -{ - return MarkerWidget->getCustomMarkerMap(); -} - -//================================================================================= -// function : setStandardMarker() -// purpose : -//================================================================================= -void SMESHGUI_Preferences_ColorDlg::setStandardMarker( VTK::MarkerType theMarkerType, - VTK::MarkerScale theMarkerScale ) -{ - MarkerWidget->setStandardMarker( theMarkerType, theMarkerScale ); -} - -//================================================================================= -// function : setCustomMarker() -// purpose : -//================================================================================= -void SMESHGUI_Preferences_ColorDlg::setCustomMarker( int theId ) -{ - MarkerWidget->setCustomMarker( theId ); -} - -//================================================================================= -// function : getMarkerType() -// purpose : -//================================================================================= -VTK::MarkerType SMESHGUI_Preferences_ColorDlg::getMarkerType() const -{ - return MarkerWidget->getMarkerType(); -} - -//================================================================================= -// function : getStandardMarkerScale() -// purpose : -//================================================================================= -VTK::MarkerScale SMESHGUI_Preferences_ColorDlg::getStandardMarkerScale() const -{ - return MarkerWidget->getStandardMarkerScale(); -} - -//================================================================================= -// function : getCustomMarkerID() -// purpose : -//================================================================================= -int SMESHGUI_Preferences_ColorDlg::getCustomMarkerID() const -{ - return MarkerWidget->getCustomMarkerID(); -} - -//================================================================================= -// function : SetDeltaBrightness(int) -// purpose : -//================================================================================= -void SMESHGUI_Preferences_ColorDlg::SetDeltaBrightness(int delta) -{ - toolSurfColor->setDelta(delta); -} -//================================================================================= -// function : GetDeltaBrightness() -// purpose : -//================================================================================= -int SMESHGUI_Preferences_ColorDlg::GetDeltaBrightness() -{ - return toolSurfColor->delta(); -} - -//================================================================================= -// function : keyPressEvent() -// purpose : -//================================================================================= -void SMESHGUI_Preferences_ColorDlg::keyPressEvent( QKeyEvent* e ) -{ - QDialog::keyPressEvent( e ); - if ( e->isAccepted() ) - return; - - if ( e->key() == Qt::Key_F1 ) { - e->accept(); - ClickOnHelp(); - } -} diff --git a/src/SMESHGUI/SMESHGUI_Preferences_ColorDlg.h b/src/SMESHGUI/SMESHGUI_Preferences_ColorDlg.h deleted file mode 100644 index 9533ca748..000000000 --- a/src/SMESHGUI/SMESHGUI_Preferences_ColorDlg.h +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE -// -// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, -// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License. -// -// 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 -// - -// SMESH SMESHGUI : GUI for SMESH component -// File : SMESHGUI_Preferences_ColorDlg.h -// Author : Nicolas REJNERI, Open CASCADE S.A.S. -// -#ifndef SMESHGUI_PREFERENCES_COLORDLG_H -#define SMESHGUI_PREFERENCES_COLORDLG_H - -// SMESH includes -#include "SMESH_SMESHGUI.hxx" - -// SALOME GUI includes -#include -#include - -// Qt includes -#include - -class QCheckBox; -class SMESHGUI; -class SMESHGUI_SpinBox; -class SalomeApp_IntSpinBox; -class QtxColorButton; -class VTKViewer_MarkerWidget; - -class SMESHGUI_EXPORT SMESHGUI_Preferences_ColorDlg : public QDialog -{ - Q_OBJECT - -public: - SMESHGUI_Preferences_ColorDlg( SMESHGUI* ); - ~SMESHGUI_Preferences_ColorDlg(); - - void SetColor( int, const QColor& ); - QColor GetColor( int ); - void SetIntValue( int, int ); - int GetIntValue( int ); - void SetDoubleValue( int, double ); - double GetDoubleValue( int ); - void SetBooleanValue( int, bool ); - bool GetBooleanValue( int ); - - void setCustomMarkerMap( VTK::MarkerMap ); - VTK::MarkerMap getCustomMarkerMap(); - - void SetDeltaBrightness(int); - int GetDeltaBrightness(); - - void setStandardMarker( VTK::MarkerType, VTK::MarkerScale ); - void setCustomMarker( int ); - VTK::MarkerType getMarkerType() const; - VTK::MarkerScale getStandardMarkerScale() const; - int getCustomMarkerID() const; - -protected: - void closeEvent( QCloseEvent* ); - void keyPressEvent( QKeyEvent* ); - -private slots: - void ClickOnOk(); - void ClickOnCancel(); - void ClickOnHelp(); - void DeactivateActiveDialog(); - void ActivateThisDialog(); - -private: - SMESHGUI* mySMESHGUI; - - QtxBiColorTool* toolSurfColor; - QtxColorButton* btnWireframeColor; - QtxColorButton* btnOutlineColor; - QtxColorButton* btn0DElementsColor; - QtxColorButton* btnBallElemColor; - SalomeApp_IntSpinBox* SpinBox_0DElements_Size; - SalomeApp_IntSpinBox* SpinBox_BallElem_Size; - SalomeApp_IntSpinBox* SpinBox_Width; - SalomeApp_IntSpinBox* SpinBox_Shrink; - QtxColorButton* btnNodeColor; - VTKViewer_MarkerWidget* MarkerWidget; - QtxColorButton* btnOrientationColor; - SMESHGUI_SpinBox* SpinBox_Orientation_Scale; - QCheckBox* CheckBox_Orientation_3DVectors; - QtxColorButton* btnPreselectionColor; - QtxColorButton* btnSelectionColor; - - QString myHelpFileName; -}; - -#endif // SMESHGUI_PREFERENCES_COLORDLG_H diff --git a/src/SMESHGUI/SMESHGUI_PropertiesDlg.cxx b/src/SMESHGUI/SMESHGUI_PropertiesDlg.cxx new file mode 100644 index 000000000..1e9874b08 --- /dev/null +++ b/src/SMESHGUI/SMESHGUI_PropertiesDlg.cxx @@ -0,0 +1,649 @@ +// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// 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 : SMESHGUI_PropertiesDlg.cxx +// Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com) + +#include "SMESHGUI_PropertiesDlg.h" +#include "SMESH_Actor.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +const int MARGIN = 9; +const int SPACING = 6; + +/*! + \class SMESHGUI_PropertiesDlg + \brief Dialog box to set-up mesh presentation properties: colors, + sizes of elements, width of lines etc +*/ + +/* + \brief Constructor + \param customMarkers custom node markers + \param parent parent widget +*/ +SMESHGUI_PropertiesDlg::SMESHGUI_PropertiesDlg( const VTK::MarkerMap& customMarkers, QWidget* parent ) + : SMESHGUI_Dialog( parent, true, true, Standard ) +{ + // set title + setWindowTitle( tr( "TITLE" ) ); + + // create widgets + + QHBoxLayout* hl; + int widthLab1 = 0, widthLab2 = 0; + + // -- node controls + myNodeGrp = new QGroupBox( tr( "NODES" ), mainFrame() ); + QLabel* nodeColorLab = new QLabel( tr( "COLOR" ), myNodeGrp ); + myNodeColor = new QtxColorButton( myNodeGrp ); + myNodeMarker = new VTKViewer_MarkerWidget( myNodeGrp ); + hl = new QHBoxLayout( myNodeGrp ); + hl->setMargin( MARGIN ); + hl->setSpacing( SPACING ); + hl->addWidget( nodeColorLab ); + hl->addWidget( myNodeColor ); + hl->addWidget( myNodeMarker ); + widthLab1 = qMax( widthLab1, nodeColorLab->minimumSizeHint().width() ); + widthLab2 = qMax( widthLab2, myNodeMarker->typeLabel()->minimumSizeHint().width() ); + + // -- edge controls + myEdgeGrp = new QGroupBox( tr( "EDGES" ), mainFrame() ); + QLabel* edgeColorLab = new QLabel( tr( "COLOR" ), myEdgeGrp ); + myEdgeColor = new QtxColorButton( myEdgeGrp ); + QLabel* edgeWidthLab = new QLabel( tr( "WIDTH" ), myEdgeGrp ); + myEdgeWidth = new QtxIntSpinBox( myEdgeGrp ); + hl = new QHBoxLayout( myEdgeGrp ); + hl->setMargin( MARGIN ); + hl->setSpacing( SPACING ); + hl->addWidget( edgeColorLab ); + hl->addWidget( myEdgeColor ); + hl->addWidget( edgeWidthLab ); + hl->addWidget( myEdgeWidth ); + widthLab1 = qMax( widthLab1, edgeColorLab->minimumSizeHint().width() ); + widthLab2 = qMax( widthLab2, edgeWidthLab->minimumSizeHint().width() ); + + // -- face controls + myFaceGrp = new QGroupBox( tr( "FACES" ), mainFrame() ); + QLabel* faceColorLab = new QLabel( tr( "FACE_FRONT" ), myFaceGrp ); + myFaceColor = new QtxBiColorTool( myFaceGrp ); + myFaceColor->label()->setText( tr( "FACE_BACK" ) ); + hl = new QHBoxLayout( myFaceGrp ); + hl->setMargin( MARGIN ); + hl->setSpacing( SPACING ); + hl->addWidget( faceColorLab ); + hl->addWidget( myFaceColor ); + widthLab1 = qMax( widthLab1, faceColorLab->minimumSizeHint().width() ); + widthLab2 = qMax( widthLab2, myFaceColor->label()->minimumSizeHint().width() ); + + // -- volumes + myVolumeGrp = new QGroupBox( tr( "VOLUMES" ), mainFrame() ); + QLabel* volumeColorLab = new QLabel( tr( "VOLUME_NORMAL" ), myVolumeGrp ); + myVolumeColor = new QtxBiColorTool( myVolumeGrp ); + myVolumeColor->label()->setText( tr( "VOLUME_REVERSED" ) ); + hl = new QHBoxLayout( myVolumeGrp ); + hl->setMargin( MARGIN ); + hl->setSpacing( SPACING ); + hl->addWidget( volumeColorLab ); + hl->addWidget( myVolumeColor ); + widthLab1 = qMax( widthLab1, volumeColorLab->minimumSizeHint().width() ); + widthLab2 = qMax( widthLab2, myVolumeColor->label()->minimumSizeHint().width() ); + + // -- outline controls + myOutlineGrp = new QGroupBox( tr( "OUTLINES" ), mainFrame() ); + QLabel* outlineColorLab = new QLabel( tr( "COLOR" ), myOutlineGrp ); + myOutlineColor = new QtxColorButton( myOutlineGrp ); + QLabel* outlineWidthLab = new QLabel( tr( "WIDTH" ), myOutlineGrp ); + myOutlineWidth = new QtxIntSpinBox( myOutlineGrp ); + hl = new QHBoxLayout( myOutlineGrp ); + hl->setMargin( MARGIN ); + hl->setSpacing( SPACING ); + hl->addWidget( outlineColorLab ); + hl->addWidget( myOutlineColor ); + hl->addWidget( outlineWidthLab ); + hl->addWidget( myOutlineWidth ); + widthLab1 = qMax( widthLab1, outlineColorLab->minimumSizeHint().width() ); + widthLab2 = qMax( widthLab2, outlineWidthLab->minimumSizeHint().width() ); + + // -- 0d element controls + myElem0dGrp = new QGroupBox( tr( "0D_ELEMENTS" ), mainFrame() ); + QLabel* elem0dColorLab = new QLabel( tr( "COLOR" ), myElem0dGrp ); + myElem0dColor = new QtxColorButton( myElem0dGrp ); + QLabel* elem0dSizeLab = new QLabel( tr( "SIZE" ), myElem0dGrp ); + myElem0dSize = new QtxIntSpinBox( myElem0dGrp ); + hl = new QHBoxLayout( myElem0dGrp ); + hl->setMargin( MARGIN ); + hl->setSpacing( SPACING ); + hl->addWidget( elem0dColorLab ); + hl->addWidget( myElem0dColor ); + hl->addWidget( elem0dSizeLab ); + hl->addWidget( myElem0dSize ); + widthLab1 = qMax( widthLab1, elem0dColorLab->minimumSizeHint().width() ); + widthLab2 = qMax( widthLab2, elem0dSizeLab->minimumSizeHint().width() ); + + // -- ball controls + myBallGrp = new QGroupBox( tr( "BALLS" ), mainFrame() ); + QLabel* ballColorLab = new QLabel( tr( "COLOR" ), myBallGrp ); + myBallColor = new QtxColorButton( myBallGrp ); + QLabel* ballSizeLab = new QLabel( tr( "SIZE" ), myBallGrp ); + myBallSize = new QtxIntSpinBox( myBallGrp ); + hl = new QHBoxLayout( myBallGrp ); + hl->setMargin( MARGIN ); + hl->setSpacing( SPACING ); + hl->addWidget( ballColorLab ); + hl->addWidget( myBallColor ); + hl->addWidget( ballSizeLab ); + hl->addWidget( myBallSize ); + widthLab1 = qMax( widthLab1, ballColorLab->minimumSizeHint().width() ); + widthLab2 = qMax( widthLab2, ballSizeLab->minimumSizeHint().width() ); + + // -- orientation vector controls + myOrientationGrp = new QGroupBox( tr( "ORIENTATIONS" ), mainFrame() ); + QLabel* orientationColorLab = new QLabel( tr( "COLOR" ), myOrientationGrp ); + myOrientationColor = new QtxColorButton( myOrientationGrp ); + QLabel* orientationScaleLab = new QLabel( tr( "ORIENTATION_SCALE" ), myOrientationGrp ); + myOrientationSize = new QtxIntSpinBox( myOrientationGrp ); + myOrientationSize->setSuffix( "% "); + myOrientation3d = new QCheckBox( tr("ORIENTATION_3D"), myOrientationGrp ); + hl = new QHBoxLayout( myOrientationGrp ); + hl->setMargin( MARGIN ); + hl->setSpacing( SPACING ); + hl->addWidget( orientationColorLab ); + hl->addWidget( myOrientationColor ); + hl->addWidget( orientationScaleLab ); + hl->addWidget( myOrientationSize ); + hl->addWidget( myOrientation3d ); + widthLab1 = qMax( widthLab1, orientationColorLab->minimumSizeHint().width() ); + widthLab2 = qMax( widthLab2, orientationScaleLab->minimumSizeHint().width() ); + + // -- other controls + myExtraGrp = new QFrame( mainFrame() ); + QLabel* shrinkSizeLab = new QLabel( tr( "SHRINK" ), myExtraGrp ); + myShrinkSize = new QtxIntSpinBox( myExtraGrp ); + myShrinkSize->setSuffix( "% "); + hl = new QHBoxLayout( myExtraGrp ); + hl->setMargin( MARGIN ); + hl->setSpacing( SPACING ); + hl->addWidget( shrinkSizeLab ); + hl->addWidget( myShrinkSize ); + hl->addStretch(); + widthLab1 = qMax( widthLab1, shrinkSizeLab->minimumSizeHint().width() ); + + // layout widgets + QVBoxLayout* vl = new QVBoxLayout( mainFrame() ); + vl->setMargin( 0 ); + vl->setSpacing( SPACING ); + vl->addWidget( myNodeGrp ); + vl->addWidget( myEdgeGrp ); + vl->addWidget( myFaceGrp ); + vl->addWidget( myVolumeGrp ); + vl->addWidget( myOutlineGrp ); + vl->addWidget( myElem0dGrp ); + vl->addWidget( myBallGrp ); + vl->addWidget( myOrientationGrp ); + vl->addWidget( myExtraGrp ); + + nodeColorLab->setMinimumWidth( widthLab1 ); + edgeColorLab->setMinimumWidth( widthLab1 ); + faceColorLab->setMinimumWidth( widthLab1 ); + volumeColorLab->setMinimumWidth( widthLab1 ); + outlineColorLab->setMinimumWidth( widthLab1 ); + elem0dColorLab->setMinimumWidth( widthLab1 ); + ballColorLab->setMinimumWidth( widthLab1 ); + orientationColorLab->setMinimumWidth( widthLab1 ); + shrinkSizeLab->setMinimumWidth( widthLab1 ); + + myNodeMarker->typeLabel()->setMinimumWidth( widthLab2 ); + edgeWidthLab->setMinimumWidth( widthLab2 ); + myFaceColor->label()->setMinimumWidth( widthLab2 ); + myVolumeColor->label()->setMinimumWidth( widthLab2 ); + outlineWidthLab->setMinimumWidth( widthLab2 ); + elem0dSizeLab->setMinimumWidth( widthLab2 ); + ballSizeLab->setMinimumWidth( widthLab2 ); + orientationScaleLab->setMinimumWidth( widthLab2 ); + + myEdgeWidth->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ); + myOutlineWidth->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ); + myElem0dSize->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ); + myBallSize->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ); + myOrientationSize->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ); + myShrinkSize->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ); + + // initialize widgets + myNodeMarker->setCustomMarkers( customMarkers ); + myElem0dSize->setRange( 1, 10 ); + myBallSize->setRange( 1, 10 ); + myEdgeWidth->setRange( 1, 5 ); + myOutlineWidth->setRange( 1, 5 ); + myShrinkSize->setRange( 20, 100 ); + myOrientationSize->setRange( 5, 100 ); + + button( OK )->setText( tr( "SMESH_BUT_OK" ) ); + + connect( this, SIGNAL( dlgHelp() ), this, SLOT( onHelp() ) ); +} + +/* + \brief Destructor: clean-up resources if necessary +*/ +SMESHGUI_PropertiesDlg::~SMESHGUI_PropertiesDlg() +{ +} + +/*! + \brief Set nodes color + \param color nodes color +*/ +void SMESHGUI_PropertiesDlg::setNodeColor( const QColor& color ) +{ + myNodeColor->setColor( color ); +} + +/*! + \brief Get nodes color + \return current nodes color +*/ +QColor SMESHGUI_PropertiesDlg::nodeColor() const +{ + return myNodeColor->color(); +} + +/*! + \brief Set standard nodes marker + \param type standard nodes marker type + \param scale standard nodes marker scale +*/ +void SMESHGUI_PropertiesDlg::setNodeMarker( VTK::MarkerType type, VTK::MarkerScale scale ) +{ + myNodeMarker->setMarker( type, scale ); +} + +/*! + \brief Set custom nodes marker + \param id custom nodes marker id +*/ +void SMESHGUI_PropertiesDlg::setNodeCustomMarker( int id ) +{ + myNodeMarker->setCustomMarker( id ); +} + +/*! + \brief Get nodes marker type. + For custom marker, VTK::MT_USER is returned and markerId() function + then returns its identifier. + \return currently selected nodes marker type +*/ +VTK::MarkerType SMESHGUI_PropertiesDlg::nodeMarkerType() const +{ + return myNodeMarker->markerType(); +} + +/*! + \brief Get nodes marker scale. + For custom marker return value is undefined. + \return currently selected nodes marker scale +*/ +VTK::MarkerScale SMESHGUI_PropertiesDlg::nodeMarkerScale() const +{ + return myNodeMarker->markerScale(); +} + +/*! + \brief Get custom nodes marker. + For standard markers return value is VTK::MT_NONE. + \return custom nodes marker id +*/ +int SMESHGUI_PropertiesDlg::nodeMarkerId() const +{ + return myNodeMarker->markerId(); +} + +/*! + \brief Set edges (wireframe) color + \param color edges color +*/ +void SMESHGUI_PropertiesDlg::setEdgeColor( const QColor& color ) +{ + myEdgeColor->setColor( color ); +} + +/*! + \brief Get edges (wireframe) color + \return current edges color +*/ +QColor SMESHGUI_PropertiesDlg::edgeColor() const +{ + return myEdgeColor->color(); +} + +/*! + \brief Set edges width + \param width edges width +*/ +void SMESHGUI_PropertiesDlg::setEdgeWidth( int width ) +{ + myEdgeWidth->setValue( width ); +} + +/*! + \brief Get edges width + \return current edges width +*/ +int SMESHGUI_PropertiesDlg::edgeWidth() const +{ + return myEdgeWidth->value(); +} + +/*! + \brief Set faces colors + \param color front faces color + \param delta back faces coloring delta +*/ +void SMESHGUI_PropertiesDlg::setFaceColor( const QColor& color, int delta ) +{ + myFaceColor->setMainColor( color ); + myFaceColor->setDelta( delta ); +} + +/*! + \brief Get front faces color + \return current front faces color +*/ +QColor SMESHGUI_PropertiesDlg::faceColor() const +{ + return myFaceColor->mainColor(); +} + +/*! + \brief Get back faces coloring delta + \return current back faces coloring delta +*/ +int SMESHGUI_PropertiesDlg::faceColorDelta() const +{ + return myFaceColor->delta(); +} + +/*! + \brief Set volumes colors + \param color normal volumes color + \param delta reversed volumes coloring delta +*/ +void SMESHGUI_PropertiesDlg::setVolumeColor( const QColor& color, int delta ) +{ + myVolumeColor->setMainColor( color ); + myVolumeColor->setDelta( delta ); +} + +/*! + \brief Get normal volumes color + \return current normal volumes color +*/ +QColor SMESHGUI_PropertiesDlg::volumeColor() const +{ + return myVolumeColor->mainColor(); +} + +/*! + \brief Get reversed volumes coloring delta + \return current reversed volumes coloring delta +*/ +int SMESHGUI_PropertiesDlg::volumeColorDelta() const +{ + return myVolumeColor->delta(); +} + +/*! + \brief Set outlines color + \param color outlines color +*/ +void SMESHGUI_PropertiesDlg::setOutlineColor( const QColor& color ) +{ + myOutlineColor->setColor( color ); +} + +/*! + \brief Get outlines color + \return current outlines color +*/ +QColor SMESHGUI_PropertiesDlg::outlineColor() const +{ + return myOutlineColor->color(); +} + +/*! + \brief Set outlines width + \param width outlines width +*/ +void SMESHGUI_PropertiesDlg::setOutlineWidth( int width ) +{ + myOutlineWidth->setValue( width ); +} + +/*! + \brief Get outlines width + \return current outlines width +*/ +int SMESHGUI_PropertiesDlg::outlineWidth() const +{ + return myOutlineWidth->value(); +} + +/*! + \brief Set 0D elements color + \param color 0D elements color +*/ +void SMESHGUI_PropertiesDlg::setElem0dColor( const QColor& color ) +{ + myElem0dColor->setColor( color ); +} + +/*! + \brief Get 0D elements color + \return current 0D elements color +*/ +QColor SMESHGUI_PropertiesDlg::elem0dColor() const +{ + return myElem0dColor->color(); +} + +/*! + \brief Set 0D elements size + \param size 0D elements size +*/ +void SMESHGUI_PropertiesDlg::setElem0dSize( int size ) +{ + myElem0dSize->setValue( size ); +} + +/*! + \brief Get 0D elements size + \return current 0D elements size +*/ +int SMESHGUI_PropertiesDlg::elem0dSize() const +{ + return myElem0dSize->value(); +} + +/*! + \brief Set discrete elements (balls) color + \param color discrete elements (balls) color +*/ +void SMESHGUI_PropertiesDlg::setBallColor( const QColor& color ) +{ + myBallColor->setColor( color ); +} + +/*! + \brief Get discrete elements (balls) color + \return current discrete elements (balls) color +*/ +QColor SMESHGUI_PropertiesDlg::ballColor() const +{ + return myBallColor->color(); +} + +/*! + \brief Set discrete elements (balls) size + \param size discrete elements (balls) size +*/ +void SMESHGUI_PropertiesDlg::setBallSize( int size ) +{ + myBallSize->setValue( size ); +} + +/*! + \brief Get discrete elements (balls) size + \return current discrete elements (balls) size +*/ +int SMESHGUI_PropertiesDlg::ballSize() const +{ + return myBallSize->value(); +} + +/*! + \brief Set orientation vectors color + \param color orientation vectors color +*/ +void SMESHGUI_PropertiesDlg::setOrientationColor( const QColor& color ) +{ + myOrientationColor->setColor( color ); +} + +/*! + \brief Get orientation vectors color + \return current orientation vectors color +*/ +QColor SMESHGUI_PropertiesDlg::orientationColor() const +{ + return myOrientationColor->color(); +} + +/*! + \brief Set orientation vectors scale (percent) + \param scale orientation vectors scale +*/ +void SMESHGUI_PropertiesDlg::setOrientationSize( int scale ) +{ + myOrientationSize->setValue( scale ); +} + +/*! + \brief Get orientation vectors scale (percent) + \return current orientation vectors scale +*/ +int SMESHGUI_PropertiesDlg::orientationSize() const +{ + return myOrientationSize->value(); +} + +/*! + \brief Set orientation vectors 3d flag + \param on orientation vectors 3d flag value +*/ +void SMESHGUI_PropertiesDlg::setOrientation3d( bool on ) +{ + myOrientation3d->setChecked( on ); +} + +/*! + \brief Get orientation vectors 3d flag + \return orientation vectors 3d flag value +*/ +bool SMESHGUI_PropertiesDlg::orientation3d() const +{ + return myOrientation3d->isChecked(); +} + +/*! + \brief Set shrink coefficient (percent) + \param coef shrink coefficient +*/ +void SMESHGUI_PropertiesDlg::setShrinkCoef( int coef ) +{ + myShrinkSize->setValue( coef ); +} + +/*! + \brief Get shrink coefficient (percent) + \return current shrink coefficient +*/ +int SMESHGUI_PropertiesDlg::shrinkCoef() const +{ + return myShrinkSize->value(); +} + +/* + \brief Get custom markers + \return custom markers map +*/ +VTK::MarkerMap SMESHGUI_PropertiesDlg::customMarkers() const +{ + return myNodeMarker->customMarkers(); +} + +/*! + \brief Show / hide controls for specified entity type + \param elements mesh element types (an or-ed combination of flags) + \param nodes mesh nodes presence flag +*/ +void SMESHGUI_PropertiesDlg::showControls( int elements, bool nodes ) +{ + // node controls are supposed to be shown if at least any element type is present + // or if there are only nodes + myNodeGrp->setVisible( nodes || elements & SMESH_Actor::eAllEntity ); + // edge controls are shown only if there are edges + myEdgeGrp->setVisible( elements & SMESH_Actor::eEdges ); + // face controls are shown only if there are faces + myFaceGrp->setVisible( elements & SMESH_Actor::eFaces ); + // volume controls are shown only if there are volumes + myVolumeGrp->setVisible( elements & SMESH_Actor::eVolumes ); + // 0d elements controls are shown only if there are 0d elements + myElem0dGrp->setVisible( elements & SMESH_Actor::e0DElements ); + // ball controls are shown only if there are balls + myBallGrp->setVisible( elements & SMESH_Actor::eBallElem ); + // outline controls are needed for faces and volumes + myOutlineGrp->setVisible( elements & ( SMESH_Actor::eFaces | SMESH_Actor::eVolumes ) ); + // orientation controls are needed for faces and volumes + myOrientationGrp->setVisible( elements & ( SMESH_Actor::eFaces | SMESH_Actor::eVolumes ) ); + // shrink factor is shown if there are edges and/or faces and/or volumes + myExtraGrp->setVisible( elements & ( SMESH_Actor::eEdges | SMESH_Actor::eFaces | SMESH_Actor::eVolumes ) ); +} + +/*! + \brief Show online help on dialog box +*/ +void SMESHGUI_PropertiesDlg::onHelp() +{ + LightApp_Application* app = (LightApp_Application*)(SUIT_Session::session()->activeApplication()); + app->onHelpContextModule( "SMESH", "colors_size_page.html" ); +} diff --git a/src/SMESHGUI/SMESHGUI_PropertiesDlg.h b/src/SMESHGUI/SMESHGUI_PropertiesDlg.h new file mode 100644 index 000000000..bcdcc7287 --- /dev/null +++ b/src/SMESHGUI/SMESHGUI_PropertiesDlg.h @@ -0,0 +1,143 @@ +// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// 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 : SMESHGUI_PropertiesDlg.h +// Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com) + +#ifndef SMESHGUI_PROPERTIESDLG_H +#define SMESHGUI_PROPERTIESDLG_H + +#include "SMESH_SMESHGUI.hxx" +#include "SMESHGUI_Dialog.h" + +#include +#include +#include CORBA_CLIENT_HEADER(SMESH_Mesh) + +class QCheckBox; +class QFrame; +class QGroupBox; +class QtxColorButton; +class QtxBiColorTool; +class QtxIntSpinBox; +class VTKViewer_MarkerWidget; + +class SMESHGUI_EXPORT SMESHGUI_PropertiesDlg : public SMESHGUI_Dialog +{ + Q_OBJECT + +public: + SMESHGUI_PropertiesDlg( const VTK::MarkerMap&, QWidget* parent ); + ~SMESHGUI_PropertiesDlg(); + + void setNodeColor( const QColor& ); + QColor nodeColor() const; + void setNodeMarker( VTK::MarkerType, VTK::MarkerScale ); + void setNodeCustomMarker( int ); + VTK::MarkerType nodeMarkerType() const; + VTK::MarkerScale nodeMarkerScale() const; + int nodeMarkerId() const; + + void setEdgeColor( const QColor& ); + QColor edgeColor() const; + void setEdgeWidth( int ); + int edgeWidth() const; + + void setFaceColor( const QColor&, int ); + QColor faceColor() const; + int faceColorDelta() const; + + void setVolumeColor( const QColor&, int ); + QColor volumeColor() const; + int volumeColorDelta() const; + + void setOutlineColor( const QColor& ); + QColor outlineColor() const; + void setOutlineWidth( int ); + int outlineWidth() const; + + void setElem0dColor( const QColor& ); + QColor elem0dColor() const; + void setElem0dSize( int ); + int elem0dSize() const; + + void setBallColor( const QColor& ); + QColor ballColor() const; + void setBallSize( int ); + int ballSize() const; + + void setOrientationColor( const QColor& ); + QColor orientationColor() const; + void setOrientationSize( int ); + int orientationSize() const; + void setOrientation3d( bool ); + bool orientation3d() const; + + void setShrinkCoef( int ); + int shrinkCoef() const; + + VTK::MarkerMap customMarkers() const; + + void showControls( int, bool ); + +private slots: + void onHelp(); + +private: + // group boxes + QGroupBox* myNodeGrp; + QGroupBox* myEdgeGrp; + QGroupBox* myFaceGrp; + QGroupBox* myVolumeGrp; + QGroupBox* myOutlineGrp; + QGroupBox* myElem0dGrp; + QGroupBox* myBallGrp; + QGroupBox* myOrientationGrp; + QFrame* myExtraGrp; + // widgets + // - nodes + QtxColorButton* myNodeColor; + VTKViewer_MarkerWidget* myNodeMarker; + // - edges + QtxColorButton* myEdgeColor; + QtxIntSpinBox* myEdgeWidth; + // - faces + QtxBiColorTool* myFaceColor; + // - volumes + QtxBiColorTool* myVolumeColor; + // - outlines + QtxColorButton* myOutlineColor; + QtxIntSpinBox* myOutlineWidth; + // - 0d elements + QtxColorButton* myElem0dColor; + QtxIntSpinBox* myElem0dSize; + // - balls + QtxColorButton* myBallColor; + QtxIntSpinBox* myBallSize; + // - orientation vectors + QtxColorButton* myOrientationColor; + QtxIntSpinBox* myOrientationSize; + QCheckBox* myOrientation3d; + // - shrink coefficient + QtxIntSpinBox* myShrinkSize; +}; + +#endif // SMESHGUI_PROPERTIESDLG_H diff --git a/src/SMESHGUI/SMESHGUI_VTKUtils.cxx b/src/SMESHGUI/SMESHGUI_VTKUtils.cxx index baafa985c..0da8d3a3a 100644 --- a/src/SMESHGUI/SMESHGUI_VTKUtils.cxx +++ b/src/SMESHGUI/SMESHGUI_VTKUtils.cxx @@ -610,14 +610,17 @@ namespace SMESH SMESH::SMESH_GroupBase_var aGroup = SMESH::SMESH_GroupBase::_narrow( SMESH::SObjectToObject( aSObj )); if(!CORBA::is_nil(aGroup) && anActor) { - QColor c;int delta; - SMESH::GetColor( "SMESH", "fill_color", c, delta, "0,170,255|-100" ); + QColor c; + int deltaF, deltaV; + SMESH::GetColor( "SMESH", "fill_color", c, deltaF, "0,170,255|-100" ); + SMESH::GetColor( "SMESH", "volume_color", c, deltaV, "255,0,170|-100" ); + SMESH::GetColor( "SMESH", "default_grp_color", c ); SALOMEDS::Color aColor = aGroup->GetColor(); if( !( aColor.R > 0 || aColor.G > 0 || aColor.B > 0 )) { - aColor.R = (float)c.red() / 255.0; - aColor.G = (float)c.green() / 255.0; - aColor.B = (float)c.blue() / 255.0; + aColor.R = c.redF(); + aColor.G = c.greenF(); + aColor.B = c.blueF(); aGroup->SetColor( aColor ); } if( aGroup->GetType() == SMESH::NODE ) @@ -628,8 +631,10 @@ namespace SMESH anActor->Set0DColor( aColor.R, aColor.G, aColor.B ); else if( aGroup->GetType() == SMESH::BALL ) anActor->SetBallColor( aColor.R, aColor.G, aColor.B ); + else if( aGroup->GetType() == SMESH::VOLUME ) + anActor->SetVolumeColor( aColor.R, aColor.G, aColor.B, deltaV ); else - anActor->SetSufaceColor( aColor.R, aColor.G, aColor.B, delta ); + anActor->SetSufaceColor( aColor.R, aColor.G, aColor.B, deltaF ); } } } @@ -1337,7 +1342,7 @@ namespace SMESH if( !anIsOk ) return false; - + DistanceToPosition( theBounds, theNormal, theDist, theOrigin ); return true; } diff --git a/src/SMESHGUI/SMESHGUI_XmlHandler.cxx b/src/SMESHGUI/SMESHGUI_XmlHandler.cxx index d02d9cd02..b62244e6f 100644 --- a/src/SMESHGUI/SMESHGUI_XmlHandler.cxx +++ b/src/SMESHGUI/SMESHGUI_XmlHandler.cxx @@ -193,7 +193,8 @@ bool SMESHGUI_XmlHandler::startElement (const QString&, const QString&, } else if ( qName == "python-wrap" || qName == "algo" || - qName == "hypo" ) + qName == "hypo" || + qName == "accumulative-methods") { // elements used in SMESH_2smeshpy return true; diff --git a/src/SMESHGUI/SMESH_msg_en.ts b/src/SMESHGUI/SMESH_msg_en.ts index 2ac37e0f5..84f6c2ee1 100644 --- a/src/SMESHGUI/SMESH_msg_en.ts +++ b/src/SMESHGUI/SMESH_msg_en.ts @@ -35,6 +35,14 @@ CGNS_FILES_FILTER CGNS files + + GMF_ASCII_FILES_FILTER + GMF ASCII files + + + GMF_BINARY_FILES_FILTER + GMF binary files + STL_BIN_FILES_FILTER STL binary files @@ -127,6 +135,15 @@ COMPERR_CANCELED Computation canceled + + COMPERR_NO_MESH_ON_SHAPE + No mesh elements assigned to a Sub-shape + + + EDITERR_NO_MEDIUM_ON_GEOM + Some medium nodes not placed on geometry to avoid + distorting elements shown in magenta + SMESH_GEOM Geometry @@ -403,6 +420,10 @@ MEN_EXPORT_CGNS Export to CGNS File + + MEN_EXPORT_GMF + Export to GMF File + MEN_EXPORT_SAUV Export to SAUV file @@ -615,6 +636,14 @@ MEN_CGNS CGNS file + + MEN_IMPORT_GMF + GMF file + + + MEN_GMF + GMF file + MEN_IMPORT_SAUV SAUV file @@ -2844,6 +2873,10 @@ Please check preferences of Mesh module. STB_EXPORT_CGNS Export to CGNS file + + STB_EXPORT_GMF + Export to GMF file + STB_EXPORT_SAUV Export to SAUV file @@ -2964,6 +2997,14 @@ Please check preferences of Mesh module. STB_CGNS Export CGNS file + + STB_IMPORT_GMF + Import GMF file + + + STB_GMF + Export GMF file + STB_IMPORT_SAUV Import SAUV file @@ -3560,6 +3601,14 @@ Please check preferences of Mesh module. TOP_CGNS Export CGNS file + + TOP_IMPORT_GMF + Import GMF file + + + TOP_GMF + Export GMF file + TOP_IMPORT_SAUV Import SAUV file @@ -4014,6 +4063,14 @@ Please, create VTK viewer and try again PREF_BACKFACE Back surface color + + PREF_VOLUME + Volume color + + + PREF_REVERSEDVOLUME + Reversed volume color + PREF_WIREFRAME Wireframe color @@ -4138,6 +4195,10 @@ Please, create VTK viewer and try again PREF_GRP_NAMES Names color + + PREF_GRP_DEF_COLOR + Default color + PREF_GROUP_PRECISION Precision @@ -4252,7 +4313,11 @@ Please, create VTK viewer and try again PREF_WIDTH - Width + Line width + + + PREF_OUTLINE_WIDTH + Outline width PREF_PREVIEW_CHUNK_SIZE @@ -6807,152 +6872,140 @@ as they are of improper type: - SMESHGUI_Preferences_ColorDlg - - DIALOG_TITLE - Properties (color, line width, shrink size, ...) - - - GRP_ELEMENTS - Elements - - - SURFACE_COLOR_LBL - Surface color - + SMESHGUI_ReorientFacesDlg - BACKSURFACE_COLOR_LBL - Back surface color + CAPTION + Reorient faces by vector - OUTLINE_COLOR_LBL - Outline color + REORIENT_FACES + Reorient - WIREFRAME_COLOR_LBL - Wireframe color + DIRECTION + Direction - 0D_ELEMENTS_COLOR_LBL - 0D elements + OBJECT + Object - 0D_ELEMENTS_SIZE_LBL - Size of 0D elements + POINT + Point - BALL_ELEMENTS_COLOR_LBL - Ball elements + FACE + Face - BALL_ELEMENTS_SIZE_LBL - Size of balls + FACES + Faces source - LINE_WIDTH_LBL - Line width + ORIENTATION + Orientation + + + SMESHGUI_ReorientFacesOp - SHRINK_COEF_LBL - Shrink coef. + NO_OBJECT_SELECTED + No object selected - GRP_NODES - Nodes + NO_FACES + Object includes no faces - NODES_COLOR_LBL - Color + ZERO_SIZE_VECTOR + Zero size vector - NODES_MARKER_LBL - Marker + INVALID_FACE + Not valid face - GRP_ORIENTATION - Orientation of faces + NB_REORIENTED + %1 faces reversed + + + SMESHGUI_PropertiesDlg - ORIENTATION_COLOR_LBL - Color + TITLE + Properties - ORIENTATION_SCALE_LBL - Scale + NODES + Nodes - 3D_VECTORS_LBL - 3D vectors + EDGES + Edges / wireframe - GRP_SELECTION - Selection + FACES + Faces - SELECTION_COLOR_LBL - Selection color + VOLUMES + Volumes - PRESELECTION_COLOR_LBL - Pre-selection color + OUTLINES + Outlines - - - SMESHGUI_ReorientFacesDlg - CAPTION - Reorient faces by vector + 0D_ELEMENTS + 0D elements - REORIENT_FACES - Reorient + BALLS + Balls - DIRECTION - Direction + ORIENTATIONS + Orientation vectors - OBJECT - Object + COLOR + Color: - POINT - Point + WIDTH + Width: - FACE - Face + FACE_FRONT + Front: - FACES - Faces source + FACE_BACK + Back: - ORIENTATION - Orientation + VOLUME_NORMAL + Normal: - - - SMESHGUI_ReorientFacesOp - NO_OBJECT_SELECTED - No object selected + VOLUME_REVERSED + Reversed: - NO_FACES - Object includes no faces + SIZE + Size: - ZERO_SIZE_VECTOR - Zero size vector + ORIENTATION_SCALE + Scale: - INVALID_FACE - Not valid face + ORIENTATION_3D + 3D vectors - NB_REORIENTED - %1 faces reversed + SHRINK + Shrink coef: diff --git a/src/SMESHGUI/SMESH_msg_fr.ts b/src/SMESHGUI/SMESH_msg_fr.ts index 1672f6fbc..f4eb29edd 100755 --- a/src/SMESHGUI/SMESH_msg_fr.ts +++ b/src/SMESHGUI/SMESH_msg_fr.ts @@ -4031,6 +4031,14 @@ Ouvrez une fenêtre VTK et essayez de nouveau PREF_BACKFACE Face arrière + + PREF_VOLUME + Volume color + + + PREF_REVERSEDVOLUME + Reversed volume color + PREF_WIREFRAME Couleur de contour @@ -4155,6 +4163,10 @@ Ouvrez une fenêtre VTK et essayez de nouveau PREF_GRP_NAMES Couleur des noms + + PREF_GRP_DEF_COLOR + Couleur par défaut + PREF_GROUP_PRECISION Précision @@ -4269,7 +4281,11 @@ Ouvrez une fenêtre VTK et essayez de nouveau PREF_WIDTH - Epaisseur + Line width + + + PREF_OUTLINE_WIDTH + Outline width PREF_PREVIEW_CHUNK_SIZE @@ -6817,152 +6833,140 @@ en raison de leurs types incompatibles: - SMESHGUI_Preferences_ColorDlg - - DIALOG_TITLE - Propriétés (couleur, épaisseur des traits, taille des éléments réduits, ...) - - - GRP_ELEMENTS - Eléments - - - SURFACE_COLOR_LBL - Couleur de surface - + SMESHGUI_ReorientFacesDlg - BACKSURFACE_COLOR_LBL - Couleur arrière + CAPTION + Réorienter des faces selon un vector - OUTLINE_COLOR_LBL - Couleur de contour + REORIENT_FACES + Réorienter - WIREFRAME_COLOR_LBL - Couleur en mode fil de fer + DIRECTION + Direction - 0D_ELEMENTS_COLOR_LBL - Eléments 0D + OBJECT + Objet - 0D_ELEMENTS_SIZE_LBL - Taille des éléments 0D + POINT + Point - BALL_ELEMENTS_COLOR_LBL - Eléments particulaires + FACE + Face - BALL_ELEMENTS_SIZE_LBL - Taille des éléments particulaires + FACES + Source des faces - LINE_WIDTH_LBL - Epaisseur des traits + ORIENTATION + Orientation + + + SMESHGUI_ReorientFacesOp - SHRINK_COEF_LBL - Coef. de contraction + NO_OBJECT_SELECTED + Aucun objet sélectionné - GRP_NODES - Nœuds + NO_FACES + L'objet ne contient pas de faces - NODES_COLOR_LBL - Couleur + ZERO_SIZE_VECTOR + Vecteur de taille nulle - NODES_MARKER_LBL - Marqueur + INVALID_FACE + Face non valide - GRP_ORIENTATION - Orientation des faces + NB_REORIENTED + %1 face(s) inversée(s) + + + SMESHGUI_PropertiesDlg - ORIENTATION_COLOR_LBL - Couleur + TITLE + Properties - ORIENTATION_SCALE_LBL - Facteur d'échelle + NODES + Nodes - 3D_VECTORS_LBL - Vecteurs 3D + EDGES + Edges / wireframe - GRP_SELECTION - Sélection + FACES + Faces - SELECTION_COLOR_LBL - Couleur de sélection + VOLUMES + Volumes - PRESELECTION_COLOR_LBL - Couleur de pré-sélection + OUTLINES + Outlines - - - SMESHGUI_ReorientFacesDlg - CAPTION - Réorienter des faces selon un vector + 0D_ELEMENTS + 0D elements - REORIENT_FACES - Réorienter + BALLS + Balls - DIRECTION - Direction + ORIENTATIONS + Orientation vectors - OBJECT - Objet + COLOR + Color: - POINT - Point + WIDTH + Width: - FACE - Face + FACE_FRONT + Front: - FACES - Source des faces + FACE_BACK + Back: - ORIENTATION - Orientation + VOLUME_NORMAL + Normal: - - - SMESHGUI_ReorientFacesOp - NO_OBJECT_SELECTED - Aucun objet sélectionné + VOLUME_REVERSED + Reversed: - NO_FACES - L'objet ne contient pas de faces + SIZE + Size: - ZERO_SIZE_VECTOR - Vecteur de taille nulle + ORIENTATION_SCALE + Scale: - INVALID_FACE - Face non valide + ORIENTATION_3D + 3D vectors - NB_REORIENTED - %1 face(s) inversée(s) + SHRINK + Shrink coef: diff --git a/src/SMESHUtils/SMESH_ComputeError.hxx b/src/SMESHUtils/SMESH_ComputeError.hxx index 204427f08..6800f0d90 100644 --- a/src/SMESHUtils/SMESH_ComputeError.hxx +++ b/src/SMESHUtils/SMESH_ComputeError.hxx @@ -40,17 +40,24 @@ enum SMESH_ComputeErrorName { // If you modify it, pls update SMESH_ComputeError::CommonName() below. // Positive values are for algo specific errors - COMPERR_OK = -1, - COMPERR_BAD_INPUT_MESH = -2, //!< wrong mesh on lower submesh - COMPERR_STD_EXCEPTION = -3, //!< some std exception raised - COMPERR_OCC_EXCEPTION = -4, //!< OCC exception raised - COMPERR_SLM_EXCEPTION = -5, //!< SALOME exception raised - COMPERR_EXCEPTION = -6, //!< other exception raised - COMPERR_MEMORY_PB = -7, //!< std::bad_alloc exception - COMPERR_ALGO_FAILED = -8, //!< algo failed for some reason - COMPERR_BAD_SHAPE = -9, //!< bad geometry - COMPERR_WARNING = -10, //!< algo reports error but sub-mesh is computed anyway - COMPERR_CANCELED = -11 //!< compute canceled + COMPERR_OK = -1, + COMPERR_BAD_INPUT_MESH = -2, //!< wrong mesh on lower submesh + COMPERR_STD_EXCEPTION = -3, //!< some std exception raised + COMPERR_OCC_EXCEPTION = -4, //!< OCC exception raised + COMPERR_SLM_EXCEPTION = -5, //!< SALOME exception raised + COMPERR_EXCEPTION = -6, //!< other exception raised + COMPERR_MEMORY_PB = -7, //!< std::bad_alloc exception + COMPERR_ALGO_FAILED = -8, //!< algo failed for some reason + COMPERR_BAD_SHAPE = -9, //!< bad geometry + COMPERR_WARNING = -10, //!< algo reports error but sub-mesh is computed anyway + COMPERR_CANCELED = -11, //!< compute canceled + COMPERR_NO_MESH_ON_SHAPE = -12, //!< no mesh elements assigned to sub-shape + COMPERR_LAST_ALGO_ERROR = -100,//!< terminator of mesh computation errors + // Errors of SMESH_MeshEditor follow + EDITERR_NO_MEDIUM_ON_GEOM= -101 /* during conversion to quadratic, + some medium nodes not placed on geometry + to avoid distorting elements, which are + stored in SMESH_ComputeError::myBadElements */ }; // ============================================================= @@ -77,29 +84,32 @@ struct SMESH_ComputeError const SMESH_Algo* algo = 0) :myName(error),myComment(comment),myAlgo(algo) {} - bool IsOK() { return myName == COMPERR_OK; } - bool IsKO() { return myName != COMPERR_OK && myName != COMPERR_WARNING; } - bool IsCommon() { return myName < 0; } + bool IsOK() const { return myName == COMPERR_OK; } + bool IsKO() const { return myName != COMPERR_OK && myName != COMPERR_WARNING; } + bool IsCommon() const { return myName < 0 && myName > COMPERR_LAST_ALGO_ERROR; } + bool HasBadElems() const { return !myBadElements.empty(); } inline std::string CommonName() const; }; #define _case2char(err) case err: return #err; +// Return myName as text, to be used to dump errors in terminal std::string SMESH_ComputeError::CommonName() const { switch( myName ) { - _case2char(COMPERR_OK ); - _case2char(COMPERR_BAD_INPUT_MESH); - _case2char(COMPERR_STD_EXCEPTION ); - _case2char(COMPERR_OCC_EXCEPTION ); - _case2char(COMPERR_SLM_EXCEPTION ); - _case2char(COMPERR_EXCEPTION ); - _case2char(COMPERR_MEMORY_PB ); - _case2char(COMPERR_ALGO_FAILED ); - _case2char(COMPERR_BAD_SHAPE ); - _case2char(COMPERR_WARNING ); - _case2char(COMPERR_CANCELED ); + _case2char(COMPERR_OK ); + _case2char(COMPERR_BAD_INPUT_MESH ); + _case2char(COMPERR_STD_EXCEPTION ); + _case2char(COMPERR_OCC_EXCEPTION ); + _case2char(COMPERR_SLM_EXCEPTION ); + _case2char(COMPERR_EXCEPTION ); + _case2char(COMPERR_MEMORY_PB ); + _case2char(COMPERR_ALGO_FAILED ); + _case2char(COMPERR_BAD_SHAPE ); + _case2char(COMPERR_WARNING ); + _case2char(COMPERR_CANCELED ); + _case2char(COMPERR_NO_MESH_ON_SHAPE); default:; } return ""; diff --git a/src/SMESH_I/Makefile.am b/src/SMESH_I/Makefile.am index 2f748f7da..4f05fa7a4 100644 --- a/src/SMESH_I/Makefile.am +++ b/src/SMESH_I/Makefile.am @@ -48,6 +48,7 @@ salomeinclude_HEADERS = \ SMESH_NoteBook.hxx \ SMESH_Measurements_i.hxx \ SMESH_PreMeshInfo.hxx \ + SMESH_MeshPartDS.hxx \ SMESH.hxx # Scripts to be installed. diff --git a/src/SMESH_I/SMESH_2smeshpy.cxx b/src/SMESH_I/SMESH_2smeshpy.cxx index 88e7ba182..91f6e7eff 100644 --- a/src/SMESH_I/SMESH_2smeshpy.cxx +++ b/src/SMESH_I/SMESH_2smeshpy.cxx @@ -1539,7 +1539,8 @@ void _pyMesh::Process( const Handle(_pyCommand)& theCommand ) // ---------------------------------------------------------------------- else if ( method == "RemoveHypothesis" ) // (geom, hyp) { - _pyID hypID = theCommand->GetArg( 2 ); + _pyID hypID = theCommand->GetArg( 2 ); + _pyID geomID = theCommand->GetArg( 1 ); // check if this mesh still has corresponding addition command bool hasAddCmd = false; @@ -1547,7 +1548,8 @@ void _pyMesh::Process( const Handle(_pyCommand)& theCommand ) while ( cmd != myAddHypCmds.end() ) { // AddHypothesis(geom, hyp) - if ( hypID == (*cmd)->GetArg( 2 )) { // erase both (add and remove) commands + if ( hypID == (*cmd)->GetArg( 2 ) && + geomID == (*cmd)->GetArg( 1 )) { // erase both (add and remove) commands theCommand->Clear(); (*cmd)->Clear(); cmd = myAddHypCmds.erase( cmd ); @@ -2356,7 +2358,7 @@ void _pyHypothesis::Assign( const Handle(_pyHypothesis)& theOther, myGeom = theOther->myGeom; myMesh = theMesh; myAlgoType2CreationMethod = theOther->myAlgoType2CreationMethod; - //myArgCommands = theOther->myArgCommands; + myAccumulativeMethods = theOther->myAccumulativeMethods; //myUnusedCommands = theOther->myUnusedCommands; // init myCurCrMethod GetCreationMethod( theOther->GetAlgoType() ); @@ -2485,7 +2487,9 @@ bool _pyHypothesis::GetReferredMeshesAndGeom( list< Handle(_pyMesh) >& meshes ) void _pyHypothesis::rememberCmdOfParameter( const Handle(_pyCommand) & theCommand ) { // parameters are discriminated by method name - TCollection_AsciiString method = theCommand->GetMethod(); + _AString method = theCommand->GetMethod(); + if ( myAccumulativeMethods.count( method )) + return; // this method adds values and not override the previus value // discriminate commands setting different parameters via one method // by passing parameter names like e.g. SetOption("size", "0.2") @@ -2503,7 +2507,7 @@ void _pyHypothesis::rememberCmdOfParameter( const Handle(_pyCommand) & theComman } } // parameters are discriminated by method name - list< Handle(_pyCommand)>& cmds = myMeth2Commands[ theCommand->GetMethod() ]; + list< Handle(_pyCommand)>& cmds = myMeth2Commands[ method /*theCommand->GetMethod()*/ ]; if ( !cmds.empty() && !isCmdUsedForCompute( cmds.back() )) { cmds.back()->Clear(); // previous parameter value has not been used @@ -3304,10 +3308,10 @@ static inline bool isWord(const char c, const bool dotIsWord) */ //================================================================================ -TCollection_AsciiString _pyCommand::GetWord( const TCollection_AsciiString & theString, - int & theStartPos, - const bool theForward, - const bool dotIsWord ) +TCollection_AsciiString _pyCommand::GetWord( const _AString & theString, + int & theStartPos, + const bool theForward, + const bool dotIsWord ) { int beg = theStartPos, end = theStartPos; theStartPos = EMPTY; @@ -4023,73 +4027,8 @@ bool _pyFilter::CanClear() _pyHypothesisReader::_pyHypothesisReader() { - // Get paths to xml files of plugins - vector< string > xmlPaths; - string sep; - if ( const char* meshersList = getenv("SMESH_MeshersList") ) - { - string meshers = meshersList, plugin; - string::size_type from = 0, pos; - while ( from < meshers.size() ) - { - // cut off plugin name - pos = meshers.find( ':', from ); - if ( pos != string::npos ) - plugin = meshers.substr( from, pos-from ); - else - plugin = meshers.substr( from ), pos = meshers.size(); - from = pos + 1; - - // get PLUGIN_ROOT_DIR path - string rootDirVar, pluginSubDir = plugin; - if ( plugin == "StdMeshers" ) - rootDirVar = "SMESH", pluginSubDir = "smesh"; - else - for ( pos = 0; pos < plugin.size(); ++pos ) - rootDirVar += toupper( plugin[pos] ); - rootDirVar += "_ROOT_DIR"; - - const char* rootDir = getenv( rootDirVar.c_str() ); - if ( !rootDir || strlen(rootDir) == 0 ) - { - rootDirVar = plugin + "_ROOT_DIR"; // HexoticPLUGIN_ROOT_DIR - rootDir = getenv( rootDirVar.c_str() ); - if ( !rootDir || strlen(rootDir) == 0 ) continue; - } - - // get a separator from rootDir - for ( pos = strlen( rootDir )-1; pos >= 0 && sep.empty(); --pos ) - if ( rootDir[pos] == '/' || rootDir[pos] == '\\' ) - { - sep = rootDir[pos]; - break; - } -#ifdef WNT - if (sep.empty() ) sep = "\\"; -#else - if (sep.empty() ) sep = "/"; -#endif - - // get a path to resource file - string xmlPath = rootDir; - if ( xmlPath[ xmlPath.size()-1 ] != sep[0] ) - xmlPath += sep; - xmlPath += "share" + sep + "salome" + sep + "resources" + sep; - for ( pos = 0; pos < pluginSubDir.size(); ++pos ) - xmlPath += tolower( pluginSubDir[pos] ); - xmlPath += sep + plugin + ".xml"; - bool fileOK; -#ifdef WNT - fileOK = (GetFileAttributes(xmlPath.c_str()) != INVALID_FILE_ATTRIBUTES); -#else - fileOK = (access(xmlPath.c_str(), F_OK) == 0); -#endif - if ( fileOK ) - xmlPaths.push_back( xmlPath ); - } - } - // Read xml files + vector< string > xmlPaths = SMESH_Gen::GetPluginXMLPaths(); LDOMParser xmlParser; for ( size_t i = 0; i < xmlPaths.size(); ++i ) { @@ -4111,7 +4050,7 @@ _pyHypothesisReader::_pyHypothesisReader() LDOM_NodeList algoNodeList = xmlDoc.getElementsByTagName( "algorithm" ); for ( int i = 0; i < algoNodeList.getLength(); ++i ) { - LDOM_Node algoNode = algoNodeList.item( i ); + LDOM_Node algoNode = algoNodeList.item( i ); LDOM_Element& algoElem = (LDOM_Element&) algoNode; LDOM_NodeList pyAlgoNodeList = algoElem.getElementsByTagName( "algo" ); if ( pyAlgoNodeList.getLength() < 1 ) continue; @@ -4173,7 +4112,43 @@ _pyHypothesisReader::_pyHypothesisReader() } } } - } + // + // + // + // SetEnforcedVertex, + // SetEnforcedVertexNamed + // + // + // + // + LDOM_NodeList hypNodeList = xmlDoc.getElementsByTagName( "hypothesis" ); + for ( int i = 0; i < hypNodeList.getLength(); ++i ) + { + LDOM_Node hypNode = hypNodeList.item( i ); + LDOM_Element& hypElem = (LDOM_Element&) hypNode; + _AString hypType = hypElem.getAttribute("type"); + LDOM_NodeList methNodeList = hypElem.getElementsByTagName( "accumulative-methods" ); + if ( methNodeList.getLength() != 1 || hypType.IsEmpty() ) continue; + + map<_AString, Handle(_pyHypothesis)>::const_iterator type2hyp = myType2Hyp.find( hypType ); + if ( type2hyp == myType2Hyp.end() ) continue; + + LDOM_Node methNode = methNodeList.item( 0 ); + LDOM_Node textNode = methNode.getFirstChild(); + _AString text = textNode.getNodeValue(); + _AString method; + int pos = 1; + do { + method = _pyCommand::GetWord( text, pos, /*forward= */true ); + pos += method.Length(); + type2hyp->second->AddAccumulativeMethod( method ); + } + while ( !method.IsEmpty() ); + } + + } // loop on xmlPaths } //================================================================================ diff --git a/src/SMESH_I/SMESH_2smeshpy.hxx b/src/SMESH_I/SMESH_2smeshpy.hxx index f92c285b4..36212e068 100644 --- a/src/SMESH_I/SMESH_2smeshpy.hxx +++ b/src/SMESH_I/SMESH_2smeshpy.hxx @@ -37,6 +37,7 @@ #include #include #include +#include #include #include CORBA_CLIENT_HEADER(SALOMEDS) @@ -360,7 +361,7 @@ protected: _pyID myGeom, myMesh; struct CreationMethod { _AString myMethod; // method of algo or mesh creating a hyp - // myArgNb(i)-th arg of myArgMethods(i) of hyp becomes an i-th arg of myAlgoMethod + // myArgNb(i)-th arg of myArgMethods(i) of hyp becomes an i-th arg of myMethod std::vector<_AString> myArgMethods; std::vector myArgNb; // arg nb countered from 1 std::vector<_AString> myArgs; // creation arguments @@ -369,6 +370,7 @@ protected: // a hypothesis can be created by different algos by different methods typedef std::map<_AString, CreationMethod > TType2CrMethod; TType2CrMethod myAlgoType2CreationMethod; + std::set< _AString > myAccumulativeMethods; CreationMethod* myCurCrMethod; // used for adding to myAlgoType2CreationMethod std::list myArgCommands; std::list myUnusedCommands; @@ -389,6 +391,8 @@ public: void AddArgMethod(const _AString& method, const int argNb = 1) { myCurCrMethod->myArgMethods.push_back( method ); myCurCrMethod->myArgNb.push_back( argNb ); } + void AddAccumulativeMethod( const _AString& method) + { myAccumulativeMethods.insert( method ); } //const TColStd_SequenceOfAsciiString& GetArgs() const { return myArgs; } const std::list& GetArgCommands() const { return myArgCommands; } void ClearAllCommands(); diff --git a/src/SMESH_I/SMESH_DumpPython.cxx b/src/SMESH_I/SMESH_DumpPython.cxx index 0544cb091..e76a8a736 100644 --- a/src/SMESH_I/SMESH_DumpPython.cxx +++ b/src/SMESH_I/SMESH_DumpPython.cxx @@ -85,10 +85,8 @@ namespace SMESH TPythonDump:: operator<<(const TVar& theVarValue) { - if ( theVarValue.myVals.empty() ) return *this; - const std::vector< std::string >& varNames = SMESH_Gen_i::GetSMESHGen()->GetLastParameters(); - if ( theVarValue.myVals.size() > 1 ) + if ( theVarValue.myVals.size() != 1 ) { myStream << "[ "; for ( size_t i = 1; i <= theVarValue.myVals.size(); ++i ) diff --git a/src/SMESH_I/SMESH_Gen_i.cxx b/src/SMESH_I/SMESH_Gen_i.cxx index 24b30bb62..dc47f8a84 100644 --- a/src/SMESH_I/SMESH_Gen_i.cxx +++ b/src/SMESH_I/SMESH_Gen_i.cxx @@ -118,6 +118,7 @@ #include #include #include +#include using namespace std; using SMESH::TPythonDump; @@ -960,7 +961,7 @@ SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CreateMeshesFromUNV( const char* theFileName aStudyBuilder->CommitCommand(); if ( !aSO->_is_nil() ) { // Update Python script - TPythonDump() << aSO << " = smeshgen.CreateMeshesFromUNV(r'" << theFileName << "')"; + TPythonDump() << aSO << " = " << this << ".CreateMeshesFromUNV(r'" << theFileName << "')"; } } @@ -1222,6 +1223,47 @@ SMESH::mesh_array* SMESH_Gen_i::CreateMeshesFromCGNS( const char* theFileName, return aResult._retn(); } +//================================================================================ +/*! + * \brief Create a mesh and import data from a GMF file + */ +//================================================================================ + +SMESH::SMESH_Mesh_ptr +SMESH_Gen_i::CreateMeshesFromGMF( const char* theFileName, + SMESH::ComputeError_out theError) + throw ( SALOME::SALOME_Exception ) +{ + Unexpect aCatch(SALOME_SalomeException); + + SMESH::SMESH_Mesh_var aMesh = createMesh(); +#ifdef WIN32 + char bname[ _MAX_FNAME ]; + _splitpath( theFileName, NULL, NULL, bname, NULL ); + string aFileName = bname; +#else + string aFileName = basename( theFileName ); +#endif + // publish mesh in the study + if ( CanPublishInStudy( aMesh ) ) { + SALOMEDS::StudyBuilder_var aStudyBuilder = myCurrentStudy->NewBuilder(); + aStudyBuilder->NewCommand(); // There is a transaction + SALOMEDS::SObject_var aSO = PublishInStudy + ( myCurrentStudy, SALOMEDS::SObject::_nil(), aMesh.in(), aFileName.c_str() ); + aStudyBuilder->CommitCommand(); + if ( !aSO->_is_nil() ) { + // Update Python script + TPythonDump() << "("<< aSO << ", error) = " << this << ".CreateMeshesFromGMF(r'" << theFileName << "')"; + } + } + SMESH_Mesh_i* aServant = dynamic_cast( GetServant( aMesh ).in() ); + ASSERT( aServant ); + theError = aServant->ImportGMFFile( theFileName ); + aServant->GetImpl().GetMeshDS()->Modified(); + return aMesh._retn(); +} + + //============================================================================= /*! * SMESH_Gen_i::IsReadyToCompute @@ -4158,18 +4200,6 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent, } } - // issue 0020693. Restore _isModified flag - if( aTopGroup->ExistInternalObject( "_isModified" ) ) - { - aDataset = new HDFdataset( "_isModified", aTopGroup ); - aDataset->OpenOnDisk(); - size = aDataset->GetSize(); - int* isModified = new int[ size ]; - aDataset->ReadFromDisk( isModified ); - aDataset->CloseOnDisk(); - myNewMeshImpl->GetImpl().SetIsModified( bool(*isModified)); - } - // issue 20918. Restore Persistent Id of SMESHDS_Mesh if( aTopGroup->ExistInternalObject( "meshPersistentId" ) ) { diff --git a/src/SMESH_I/SMESH_Gen_i.hxx b/src/SMESH_I/SMESH_Gen_i.hxx index a72c466f3..1165ac142 100644 --- a/src/SMESH_I/SMESH_Gen_i.hxx +++ b/src/SMESH_I/SMESH_Gen_i.hxx @@ -238,7 +238,7 @@ public: SMESH::SMESH_Mesh_ptr CreateEmptyMesh() throw ( SALOME::SALOME_Exception ); - // Create mesh(es) and import data from UNV fileter + // Create a mesh and import data from an UNV file SMESH::SMESH_Mesh_ptr CreateMeshesFromUNV( const char* theFileName ) throw ( SALOME::SALOME_Exception ); @@ -252,7 +252,7 @@ public: SMESH::DriverMED_ReadStatus& theStatus ) throw ( SALOME::SALOME_Exception ); - // Create mesh(es) and import data from STL file + // Create a mesh and import data from a STL file SMESH::SMESH_Mesh_ptr CreateMeshesFromSTL( const char* theFileName ) throw ( SALOME::SALOME_Exception ); @@ -261,6 +261,11 @@ public: SMESH::DriverMED_ReadStatus& theStatus ) throw ( SALOME::SALOME_Exception ); + // Create a mesh and import data from a GMF file + SMESH::SMESH_Mesh_ptr CreateMeshesFromGMF( const char* theFileName, + SMESH::ComputeError_out theError) + throw ( SALOME::SALOME_Exception ); + // Copy a part of mesh SMESH::SMESH_Mesh_ptr CopyMesh(SMESH::SMESH_IDSource_ptr meshPart, const char* meshName, diff --git a/src/SMESH_I/SMESH_Hypothesis_i.cxx b/src/SMESH_I/SMESH_Hypothesis_i.cxx index 96131044b..f0fed2964 100644 --- a/src/SMESH_I/SMESH_Hypothesis_i.cxx +++ b/src/SMESH_I/SMESH_Hypothesis_i.cxx @@ -216,98 +216,98 @@ void SMESH_Hypothesis_i::setOldParameters (const char* theParameters) * */ //============================================================================= -void SMESH_Hypothesis_i::SetParameters(const char* theParameters) -{ - SMESH_Gen_i *gen = SMESH_Gen_i::GetSMESHGen(); - //char * aParameters = CORBA::string_dup(theParameters); - if(gen){ - gen->UpdateParameters(theParameters); - // if(IsPublished()) { - // SMESH_Gen_i::GetSMESHGen()->UpdateParameters(SMESH::SMESH_Hypothesis::_narrow(_this()),aParameters); - // } - // else { - // myBaseImpl->SetParameters(gen->ParseParameters(aParameters)); - // } - } -} - -//============================================================================= -/*! - * SMESH_Hypothesis_i::GetParameters() - * - */ -//============================================================================= -char* SMESH_Hypothesis_i::GetParameters() -{ - SMESH_Gen_i *gen = SMESH_Gen_i::GetSMESHGen(); - char* aResult; - if(IsPublished()) { - MESSAGE("SMESH_Hypothesis_i::GetParameters() : Get Parameters from SObject"); - aResult = gen->GetParameters(SMESH::SMESH_Hypothesis::_narrow(_this())); - } - else { - MESSAGE("SMESH_Hypothesis_i::GetParameters() : Get local parameters"); - aResult = myBaseImpl->GetParameters(); - } - return CORBA::string_dup(aResult); -} - -//============================================================================= -/*! - * SMESH_Hypothesis_i::GetLastParameters() - * - */ -//============================================================================= -SMESH::ListOfParameters* SMESH_Hypothesis_i::GetLastParameters() -{ - SMESH::ListOfParameters_var aResult = new SMESH::ListOfParameters(); - SMESH_Gen_i *gen = SMESH_Gen_i::GetSMESHGen(); - if(gen) { - char *aParameters; - if(IsPublished()) - aParameters = GetParameters(); - else - aParameters = myBaseImpl->GetLastParameters(); - - SALOMEDS::Study_ptr aStudy = gen->GetCurrentStudy(); - if(!aStudy->_is_nil()) { - SALOMEDS::ListOfListOfStrings_var aSections = aStudy->ParseVariables(aParameters); - if(aSections->length() > 0) { - SALOMEDS::ListOfStrings aVars = aSections[aSections->length()-1]; - aResult->length(aVars.length()); - for(int i = 0;i < aVars.length();i++) - aResult[i] = CORBA::string_dup( aVars[i]); - } - } - } - return aResult._retn(); -} - -//============================================================================= -/*! - * SMESH_Hypothesis_i::SetLastParameters() - * - */ -//============================================================================= -void SMESH_Hypothesis_i::SetLastParameters(const char* theParameters) -{ - if(!IsPublished()) { - myBaseImpl->SetLastParameters(theParameters); - } -} -//============================================================================= -/*! - * SMESH_Hypothesis_i::ClearParameters() - * - */ -//============================================================================= -void SMESH_Hypothesis_i::ClearParameters() -{ - myMethod2VarParams.clear(); - // if(!IsPublished()) { - // myBaseImpl->ClearParameters(); - // } -} +// void SMESH_Hypothesis_i::SetParameters(const char* theParameters) +// { +// SMESH_Gen_i *gen = SMESH_Gen_i::GetSMESHGen(); +// //char * aParameters = CORBA::string_dup(theParameters); +// if(gen){ +// gen->UpdateParameters(theParameters); +// // if(IsPublished()) { +// // SMESH_Gen_i::GetSMESHGen()->UpdateParameters(SMESH::SMESH_Hypothesis::_narrow(_this()),aParameters); +// // } +// // else { +// // myBaseImpl->SetParameters(gen->ParseParameters(aParameters)); +// // } +// } +// } + +// //============================================================================= +// /*! +// * SMESH_Hypothesis_i::GetParameters() +// * +// */ +// //============================================================================= +// char* SMESH_Hypothesis_i::GetParameters() +// { +// SMESH_Gen_i *gen = SMESH_Gen_i::GetSMESHGen(); +// char* aResult; +// if(IsPublished()) { +// MESSAGE("SMESH_Hypothesis_i::GetParameters() : Get Parameters from SObject"); +// aResult = gen->GetParameters(SMESH::SMESH_Hypothesis::_narrow(_this())); +// } +// else { +// MESSAGE("SMESH_Hypothesis_i::GetParameters() : Get local parameters"); +// aResult = myBaseImpl->GetParameters(); +// } +// return CORBA::string_dup(aResult); +// } + +// //============================================================================= +// /*! +// * SMESH_Hypothesis_i::GetLastParameters() +// * +// */ +// //============================================================================= +// SMESH::ListOfParameters* SMESH_Hypothesis_i::GetLastParameters() +// { +// SMESH::ListOfParameters_var aResult = new SMESH::ListOfParameters(); +// SMESH_Gen_i *gen = SMESH_Gen_i::GetSMESHGen(); +// if(gen) { +// char *aParameters; +// if(IsPublished()) +// aParameters = GetParameters(); +// else +// aParameters = myBaseImpl->GetLastParameters(); + +// SALOMEDS::Study_ptr aStudy = gen->GetCurrentStudy(); +// if(!aStudy->_is_nil()) { +// SALOMEDS::ListOfListOfStrings_var aSections = aStudy->ParseVariables(aParameters); +// if(aSections->length() > 0) { +// SALOMEDS::ListOfStrings aVars = aSections[aSections->length()-1]; +// aResult->length(aVars.length()); +// for(int i = 0;i < aVars.length();i++) +// aResult[i] = CORBA::string_dup( aVars[i]); +// } +// } +// } +// return aResult._retn(); +// } + +// //============================================================================= +// /*! +// * SMESH_Hypothesis_i::SetLastParameters() +// * +// */ +// //============================================================================= +// void SMESH_Hypothesis_i::SetLastParameters(const char* theParameters) +// { +// if(!IsPublished()) { +// myBaseImpl->SetLastParameters(theParameters); +// } +// } +// //============================================================================= +// /*! +// * SMESH_Hypothesis_i::ClearParameters() +// * +// */ +// //============================================================================= +// void SMESH_Hypothesis_i::ClearParameters() +// { +// myMethod2VarParams.clear(); +// // if(!IsPublished()) { +// // myBaseImpl->ClearParameters(); +// // } +// } //============================================================================= /*! diff --git a/src/SMESH_I/SMESH_Hypothesis_i.hxx b/src/SMESH_I/SMESH_Hypothesis_i.hxx index 593ed85ca..c8ff51ab3 100644 --- a/src/SMESH_I/SMESH_Hypothesis_i.hxx +++ b/src/SMESH_I/SMESH_Hypothesis_i.hxx @@ -79,20 +79,20 @@ public: char* GetVarParameter (const char* methodName); // Set list of parameters separated by ":" symbol, used for Hypothesis creation - void SetParameters (const char* theParameters); + // void SetParameters (const char* theParameters); - // Return list of notebook variables used for Hypothesis creation separated by ":" symbol - char* GetParameters(); + // // Return list of notebook variables used for Hypothesis creation separated by ":" symbol + // char* GetParameters(); - //Return list of last notebook variables used for Hypothesis creation. - SMESH::ListOfParameters* GetLastParameters(); + // //Return list of last notebook variables used for Hypothesis creation. + // SMESH::ListOfParameters* GetLastParameters(); - //Set last parameters for not published hypothesis + // //Set last parameters for not published hypothesis - void SetLastParameters(const char* theParameters); + // void SetLastParameters(const char* theParameters); - // Clear parameters list - void ClearParameters(); + // // Clear parameters list + // void ClearParameters(); //Return true if hypothesis was published in study bool IsPublished(); diff --git a/src/SMESH_I/SMESH_MeshEditor_i.cxx b/src/SMESH_I/SMESH_MeshEditor_i.cxx index 026eed079..a5b5f88c1 100644 --- a/src/SMESH_I/SMESH_MeshEditor_i.cxx +++ b/src/SMESH_I/SMESH_MeshEditor_i.cxx @@ -29,20 +29,42 @@ #include "SMESH_MeshEditor_i.hxx" +#include "DriverMED_R_SMESHDS_Mesh.h" +#include "DriverMED_W_SMESHDS_Mesh.h" +#include "SMDS_EdgePosition.hxx" +#include "SMDS_ElemIterator.hxx" +#include "SMDS_FacePosition.hxx" +#include "SMDS_IteratorOnIterators.hxx" #include "SMDS_LinearEdge.hxx" #include "SMDS_Mesh0DElement.hxx" #include "SMDS_MeshFace.hxx" #include "SMDS_MeshVolume.hxx" #include "SMDS_PolyhedralVolumeOfNodes.hxx" #include "SMDS_SetIterator.hxx" +#include "SMDS_SetIterator.hxx" +#include "SMDS_VolumeTool.hxx" +#include "SMESHDS_Command.hxx" +#include "SMESHDS_CommandType.hxx" #include "SMESHDS_Group.hxx" +#include "SMESHDS_GroupOnGeom.hxx" #include "SMESH_ControlsDef.hxx" #include "SMESH_Filter_i.hxx" +#include "SMESH_Filter_i.hxx" +#include "SMESH_Gen_i.hxx" #include "SMESH_Gen_i.hxx" +#include "SMESH_Group.hxx" #include "SMESH_Group_i.hxx" +#include "SMESH_Group_i.hxx" +#include "SMESH_MEDMesh_i.hxx" +#include "SMESH_MeshEditor.hxx" +#include "SMESH_MeshPartDS.hxx" +#include "SMESH_MesherHelper.hxx" +#include "SMESH_PreMeshInfo.hxx" +#include "SMESH_PythonDump.hxx" #include "SMESH_PythonDump.hxx" #include "SMESH_subMeshEventListener.hxx" #include "SMESH_subMesh_i.hxx" +#include "SMESH_subMesh_i.hxx" #include "utilities.h" #include "Utils_ExceptHandlers.hxx" @@ -438,6 +460,7 @@ void SMESH_MeshEditor_i::initData(bool deleteSearchers) if ( deleteSearchers ) TSearchersDeleter::Delete(); } + myEditor.GetError().reset(); } //================================================================================ @@ -458,27 +481,42 @@ void SMESH_MeshEditor_i::storeResult(::SMESH_MeshEditor& ) SMESH::MeshPreviewStruct* SMESH_MeshEditor_i::GetPreviewData() { - if ( myPreviewMode ) { // --- MeshPreviewStruct filling --- + const bool hasBadElems = ( myEditor.GetError() && myEditor.GetError()->HasBadElems() ); + + if ( myPreviewMode || hasBadElems ) { // --- MeshPreviewStruct filling --- list aNodesConnectivity; typedef map TNodesMap; TNodesMap nodesMap; - TPreviewMesh * aPreviewMesh = dynamic_cast< TPreviewMesh* >( myEditor.GetMesh() ); - SMDSAbs_ElementType previewType = aPreviewMesh->myPreviewType; - - SMESHDS_Mesh* aMeshDS = myEditor.GetMeshDS(); + SMESHDS_Mesh* aMeshDS; + std::auto_ptr< SMESH_MeshPartDS > aMeshPartDS; + if ( hasBadElems ) { + aMeshPartDS.reset( new SMESH_MeshPartDS( myEditor.GetError()->myBadElements )); + aMeshDS = aMeshPartDS.get(); + } + else { + aMeshDS = myEditor.GetMeshDS(); + } int nbEdges = aMeshDS->NbEdges(); int nbFaces = aMeshDS->NbFaces(); int nbVolum = aMeshDS->NbVolumes(); - switch ( previewType ) { - case SMDSAbs_Edge : nbFaces = nbVolum = 0; break; - case SMDSAbs_Face : nbEdges = nbVolum = 0; break; - case SMDSAbs_Volume: nbEdges = nbFaces = 0; break; - default:; - } myPreviewData = new SMESH::MeshPreviewStruct(); myPreviewData->nodesXYZ.length(aMeshDS->NbNodes()); + + + SMDSAbs_ElementType previewType = SMDSAbs_All; + if ( !hasBadElems ) + if (TPreviewMesh * aPreviewMesh = dynamic_cast< TPreviewMesh* >( myEditor.GetMesh() )) { + previewType = aPreviewMesh->myPreviewType; + switch ( previewType ) { + case SMDSAbs_Edge : nbFaces = nbVolum = 0; break; + case SMDSAbs_Face : nbEdges = nbVolum = 0; break; + case SMDSAbs_Volume: nbEdges = nbFaces = 0; break; + default:; + } + } + myPreviewData->elementTypes.length(nbEdges + nbFaces + nbVolum); int i = 0, j = 0; SMDS_ElemIteratorPtr itMeshElems = aMeshDS->elementsIterator(); @@ -561,6 +599,26 @@ SMESH::long_array* SMESH_MeshEditor_i::GetLastCreatedElems() return myLastCreatedElems._retn(); } +//======================================================================= +/* + * Returns description of an error/warning occured during the last operation + */ +//======================================================================= + +SMESH::ComputeError* SMESH_MeshEditor_i::GetLastError() +{ + SMESH::ComputeError* errOut = new SMESH::ComputeError; + SMESH_ComputeErrorPtr& errIn = myEditor.GetError(); + if ( errIn && !errIn->IsOK() ) + { + errOut->code = -( errIn->myName < 0 ? errIn->myName + 1: errIn->myName ); // -1 -> 0 + errOut->comment = errIn->myComment.c_str(); + errOut->subShapeID = -1; + errOut->hasBadMesh = !errIn->myBadElements.empty(); + } + return errOut; +} + //======================================================================= //function : MakeIDSource //purpose : Wrap a sequence of ids in a SMESH_IDSource @@ -5937,6 +5995,124 @@ SMESH_MeshEditor_i::DoubleNodeElemGroupsInRegion(const SMESH::ListOfGroups& theE return aResult; } +//================================================================================ +/*! + \brief Identify the elements that will be affected by node duplication (actual duplication is not performed. + This method is the first step of DoubleNodeElemGroupsInRegion. + \param theElems - list of groups of elements (edges or faces) to be replicated + \param theNodesNot - list of groups of nodes not to replicated + \param theShape - shape to detect affected elements (element which geometric center + located on or inside shape). + The replicated nodes should be associated to affected elements. + \return groups of affected elements + \sa DoubleNodeElemGroupsInRegion() + */ +//================================================================================ +SMESH::ListOfGroups* +SMESH_MeshEditor_i::AffectedElemGroupsInRegion( const SMESH::ListOfGroups& theElems, + const SMESH::ListOfGroups& theNodesNot, + GEOM::GEOM_Object_ptr theShape ) +{ + MESSAGE("AffectedElemGroupsInRegion"); + SMESH::ListOfGroups_var aListOfGroups = new SMESH::ListOfGroups(); + bool isEdgeGroup = false; + bool isFaceGroup = false; + bool isVolumeGroup = false; + SMESH::SMESH_Group_var aNewEdgeGroup = myMesh_i->CreateGroup(SMESH::EDGE, "affectedEdges"); + SMESH::SMESH_Group_var aNewFaceGroup = myMesh_i->CreateGroup(SMESH::FACE, "affectedFaces"); + SMESH::SMESH_Group_var aNewVolumeGroup = myMesh_i->CreateGroup(SMESH::VOLUME, "affectedVolumes"); + + initData(); + + ::SMESH_MeshEditor aMeshEditor(myMesh); + + SMESHDS_Mesh* aMeshDS = GetMeshDS(); + TIDSortedElemSet anElems, aNodes; + listOfGroupToSet(theElems, aMeshDS, anElems, false); + listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true); + + TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape(theShape); + TIDSortedElemSet anAffected; + bool aResult = aMeshEditor.AffectedElemGroupsInRegion(anElems, aNodes, aShape, anAffected); + + storeResult(aMeshEditor); + + myMesh->GetMeshDS()->Modified(); + TPythonDump pyDump; + if (aResult) + { + myMesh->SetIsModified(true); + + int lg = anAffected.size(); + MESSAGE("lg="<< lg); + SMESH::long_array_var volumeIds = new SMESH::long_array; + volumeIds->length(lg); + SMESH::long_array_var faceIds = new SMESH::long_array; + faceIds->length(lg); + SMESH::long_array_var edgeIds = new SMESH::long_array; + edgeIds->length(lg); + int ivol = 0; + int iface = 0; + int iedge = 0; + + TIDSortedElemSet::const_iterator eIt = anAffected.begin(); + for (; eIt != anAffected.end(); ++eIt) + { + const SMDS_MeshElement* anElem = *eIt; + if (!anElem) + continue; + int elemId = anElem->GetID(); + if (myMesh->GetElementType(elemId, true) == SMDSAbs_Volume) + volumeIds[ivol++] = elemId; + else if (myMesh->GetElementType(elemId, true) == SMDSAbs_Face) + faceIds[iface++] = elemId; + else if (myMesh->GetElementType(elemId, true) == SMDSAbs_Edge) + edgeIds[iedge++] = elemId; + } + volumeIds->length(ivol); + faceIds->length(iface); + edgeIds->length(iedge); + + aNewVolumeGroup->Add(volumeIds); + aNewFaceGroup->Add(faceIds); + aNewEdgeGroup->Add(edgeIds); + isVolumeGroup = (aNewVolumeGroup->Size() > 0); + isFaceGroup = (aNewFaceGroup->Size() > 0); + isEdgeGroup = (aNewEdgeGroup->Size() > 0); + } + + int nbGroups = 0; + if (isEdgeGroup) + nbGroups++; + if (isFaceGroup) + nbGroups++; + if (isVolumeGroup) + nbGroups++; + aListOfGroups->length(nbGroups); + + int i = 0; + if (isEdgeGroup) + aListOfGroups[i++] = aNewEdgeGroup._retn(); + if (isFaceGroup) + aListOfGroups[i++] = aNewFaceGroup._retn(); + if (isVolumeGroup) + aListOfGroups[i++] = aNewVolumeGroup._retn(); + + // Update Python script + + pyDump << "[ "; + if (isEdgeGroup) + pyDump << aNewEdgeGroup << ", "; + if (isFaceGroup) + pyDump << aNewFaceGroup << ", "; + if (isVolumeGroup) + pyDump << aNewVolumeGroup << ", "; + pyDump << "] = "; + pyDump << this << ".AffectedElemGroupsInRegion( " << &theElems << ", " << &theNodesNot << ", " << theShape << " )"; + + return aListOfGroups._retn(); +} + //================================================================================ /*! \brief Generated skin mesh (containing 2D cells) from 3D mesh @@ -6055,6 +6231,53 @@ CORBA::Boolean SMESH_MeshEditor_i::CreateFlatElementsOnFacesGroups( const SMESH: return aResult; } +/*! + * \brief identify all the elements around a geom shape, get the faces delimiting the hole + * Build groups of volume to remove, groups of faces to replace on the skin of the object, + * groups of faces to remove inside the object, (idem edges). + * Build ordered list of nodes at the border of each group of faces to replace (to be used to build a geom subshape) + */ +void SMESH_MeshEditor_i::CreateHoleSkin(CORBA::Double radius, + GEOM::GEOM_Object_ptr theShape, + const char* groupName, + const SMESH::double_array& theNodesCoords, + SMESH::array_of_long_array_out GroupsOfNodes) +throw (SALOME::SALOME_Exception) +{ + initData(); + std::vector > aListOfListOfNodes; + ::SMESH_MeshEditor aMeshEditor( myMesh ); + + theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other + if ( !theNodeSearcher ) + theNodeSearcher = aMeshEditor.GetNodeSearcher(); + + vector nodesCoords; + for (int i = 0; i < theNodesCoords.length(); i++) + { + nodesCoords.push_back( theNodesCoords[i] ); + } + + TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape ); + aMeshEditor.CreateHoleSkin(radius, aShape, theNodeSearcher, groupName, nodesCoords, aListOfListOfNodes); + + GroupsOfNodes = new SMESH::array_of_long_array; + GroupsOfNodes->length( aListOfListOfNodes.size() ); + std::vector >::iterator llIt = aListOfListOfNodes.begin(); + for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ ) + { + vector& aListOfNodes = *llIt; + vector::iterator lIt = aListOfNodes.begin();; + SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ]; + aGroup.length( aListOfNodes.size() ); + for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ ) + aGroup[ j ] = (*lIt); + } + TPythonDump() << "lists_nodes = " << this << ".CreateHoleSkin( " + << radius << ", " << theShape << ", " << ", " << groupName << ", " << theNodesCoords << " )"; +} + + // issue 20749 =================================================================== /*! * \brief Creates missing boundary elements diff --git a/src/SMESH_I/SMESH_MeshEditor_i.hxx b/src/SMESH_I/SMESH_MeshEditor_i.hxx index 15233798b..fa76be969 100644 --- a/src/SMESH_I/SMESH_MeshEditor_i.hxx +++ b/src/SMESH_I/SMESH_MeshEditor_i.hxx @@ -38,7 +38,6 @@ #include "SMESH_MeshEditor.hxx" #include -class SMESH_MeshEditor; class SMESH_Mesh_i; class SMESH_MeshEditor_i: public POA_SMESH::SMESH_MeshEditor @@ -47,9 +46,35 @@ public: SMESH_MeshEditor_i(SMESH_Mesh_i * theMesh, bool isPreview); virtual ~ SMESH_MeshEditor_i(); + /*! + * \brief Return edited mesh ID + * \retval int - mesh ID + */ + int GetMeshId() const { return myMesh->GetId(); } // --- CORBA + /*! + * Return data of mesh edition preview + */ + SMESH::MeshPreviewStruct* GetPreviewData(); + /*! + * If during last operation of MeshEditor some nodes were + * created this method returns list of their IDs, if new nodes + * not created - returns an empty list + */ + SMESH::long_array* GetLastCreatedNodes(); + /*! + * If during last operation of MeshEditor some elements were + * created this method returns list of their IDs, if new elements + * not created - returns an empty list + */ + SMESH::long_array* GetLastCreatedElems(); + /*! + * \brief Returns description of an error/warning occured during the last operation + */ + SMESH::ComputeError* GetLastError(); + /*! * \brief Wrap a sequence of ids in a SMESH_IDSource */ @@ -568,31 +593,6 @@ public: */ CORBA::Boolean ChangeElemNodes(CORBA::Long ide, const SMESH::long_array& newIDs); - /*! - * Return data of mesh edition preview - */ - SMESH::MeshPreviewStruct* GetPreviewData(); - - /*! - * If during last operation of MeshEditor some nodes were - * created this method returns list of it's IDs, if new nodes - * not creared - returns empty list - */ - SMESH::long_array* GetLastCreatedNodes(); - - /*! - * If during last operation of MeshEditor some elements were - * created this method returns list of it's IDs, if new elements - * not creared - returns empty list - */ - SMESH::long_array* GetLastCreatedElems(); - - /*! - * \brief Return edited mesh ID - * \retval int - mesh ID - */ - int GetMeshId() const { return myMesh->GetId(); } - CORBA::Boolean DoubleNodes( const SMESH::long_array& theNodes, const SMESH::long_array& theModifiedElems ); @@ -743,6 +743,22 @@ public: CORBA::Boolean DoubleNodeElemGroupsInRegion( const SMESH::ListOfGroups& theElems, const SMESH::ListOfGroups& theNodesNot, GEOM::GEOM_Object_ptr theShape ); + + /*! + * \brief Identify the elements that will be affected by node duplication (actual duplication is not performed. + * This method is the first step of DoubleNodeElemGroupsInRegion. + * \param theElems - list of groups of elements (edges or faces) to be replicated + * \param theNodesNot - list of groups of nodes not to replicated + * \param theShape - shape to detect affected elements (element which geometric center + * located on or inside shape). + * The replicated nodes should be associated to affected elements. + * \return groups of affected elements + * \sa DoubleNodeElemGroupsInRegion() + */ + SMESH::ListOfGroups* AffectedElemGroupsInRegion( const SMESH::ListOfGroups& theElems, + const SMESH::ListOfGroups& theNodesNot, + GEOM::GEOM_Object_ptr theShape ); + /*! * \brief Double nodes on shared faces between groups of volumes and create flat elements on demand. * The list of groups must describe a partition of the mesh volumes. @@ -767,6 +783,19 @@ public: */ CORBA::Boolean CreateFlatElementsOnFacesGroups( const SMESH::ListOfGroups& theGroupsOfFaces ); + /*! + * \brief identify all the elements around a geom shape, get the faces delimiting the hole + * Build groups of volume to remove, groups of faces to replace on the skin of the object, + * groups of faces to remove insidethe object, (idem edges). + * Build ordered list of nodes at the border of each group of faces to replace (to be used to build a geom subshape) + */ + void CreateHoleSkin(CORBA::Double radius, + GEOM::GEOM_Object_ptr theShape, + const char* groupName, + const SMESH::double_array& theNodesCoords, + SMESH::array_of_long_array_out GroupsOfNodes) + throw (SALOME::SALOME_Exception); + /*! * \brief Generated skin mesh (containing 2D cells) from 3D mesh * The created 2D mesh elements based on nodes of free faces of boundary volumes diff --git a/src/SMESH_I/SMESH_MeshPartDS.hxx b/src/SMESH_I/SMESH_MeshPartDS.hxx new file mode 100644 index 000000000..7257b71b0 --- /dev/null +++ b/src/SMESH_I/SMESH_MeshPartDS.hxx @@ -0,0 +1,70 @@ +// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// +// File : SMESH_MeshPartDS.hxx +// Created : Thu Sep 13 20:26:47 2012 +// Author : Edward AGAPOV (eap) + +#ifndef __SMESH_MeshPartDS_HXX__ +#define __SMESH_MeshPartDS_HXX__ + +#include "SMESHDS_Mesh.hxx" + +#include +#include CORBA_SERVER_HEADER(SMESH_Mesh) + +#include + +//============================================================================= +/*! + * \brief Class providing SMESHDS_Mesh API to SMESH_IDSource. + * It is used to export a part of mesh as a whole mesh. + */ +// Implementation is in SMESH_Mesh_i.cxx where this class was extracted from + +class SMESH_MeshPartDS : public SMESHDS_Mesh +{ +public: + SMESH_MeshPartDS(SMESH::SMESH_IDSource_ptr meshPart); + SMESH_MeshPartDS(const std::list< const SMDS_MeshElement* > & badElems ); + + virtual SMDS_NodeIteratorPtr nodesIterator (bool idInceasingOrder=false) const; + virtual SMDS_EdgeIteratorPtr edgesIterator (bool idInceasingOrder=false) const; + virtual SMDS_FaceIteratorPtr facesIterator (bool idInceasingOrder=false) const; + virtual SMDS_VolumeIteratorPtr volumesIterator (bool idInceasingOrder=false) const; + + virtual SMDS_ElemIteratorPtr elementsIterator(SMDSAbs_ElementType type=SMDSAbs_All) const; + virtual SMDS_ElemIteratorPtr elementGeomIterator(SMDSAbs_GeometryType type) const; + virtual SMDS_ElemIteratorPtr elementEntityIterator(SMDSAbs_EntityType type) const; + +private: + TIDSortedElemSet _elements[ SMDSAbs_NbElementTypes ]; + SMESHDS_Mesh* _meshDS; + /*! + * \brief Class used to access to protected data of SMDS_MeshInfo + */ + struct TMeshInfo : public SMDS_MeshInfo + { + void Add(const SMDS_MeshElement* e) { SMDS_MeshInfo::addWithPoly( e ); } + }; +}; + +#endif diff --git a/src/SMESH_I/SMESH_Mesh_i.cxx b/src/SMESH_I/SMESH_Mesh_i.cxx index 2e4d1772c..3bcdb181c 100644 --- a/src/SMESH_I/SMESH_Mesh_i.cxx +++ b/src/SMESH_I/SMESH_Mesh_i.cxx @@ -43,6 +43,7 @@ #include "SMESH_MEDMesh_i.hxx" #include "SMESH_MeshEditor.hxx" #include "SMESH_MeshEditor_i.hxx" +#include "SMESH_MeshPartDS.hxx" #include "SMESH_MesherHelper.hxx" #include "SMESH_PreMeshInfo.hxx" #include "SMESH_PythonDump.hxx" @@ -62,15 +63,16 @@ #include #include #include +#include #include #include #include #include #include #include -#include -#include #include +#include +#include // STL Includes #include @@ -304,7 +306,7 @@ void SMESH_Mesh_i::ClearSubMesh(CORBA::Long ShapeID) //============================================================================= /*! - * + * Convert enum Driver_Mesh::Status to SMESH::DriverMED_ReadStatus */ //============================================================================= @@ -328,6 +330,30 @@ static SMESH::DriverMED_ReadStatus ConvertDriverMEDReadStatus (int theStatus) return res; } +//============================================================================= +/*! + * Convert ::SMESH_ComputeError to SMESH::ComputeError + */ +//============================================================================= + +static SMESH::ComputeError* ConvertComputeError( SMESH_ComputeErrorPtr errorPtr ) +{ + SMESH::ComputeError_var errVar = new SMESH::ComputeError(); + errVar->subShapeID = -1; + errVar->hasBadMesh = false; + + if ( !errorPtr || errorPtr->IsOK() ) + { + errVar->code = SMESH::COMPERR_OK; + } + else + { + errVar->code = ConvertDriverMEDReadStatus( errorPtr->myName ); + errVar->comment = errorPtr->myComment.c_str(); + } + return errVar._retn(); +} + //============================================================================= /*! * ImportMEDFile @@ -451,6 +477,45 @@ int SMESH_Mesh_i::ImportSTLFile( const char* theFileName ) return 1; } +//================================================================================ +/*! + * \brief Imports data from a GMF file and returns an error description + */ +//================================================================================ + +SMESH::ComputeError* SMESH_Mesh_i::ImportGMFFile( const char* theFileName ) + throw (SALOME::SALOME_Exception) +{ + SMESH_ComputeErrorPtr error; + try { + error = _impl->GMFToMesh( theFileName ); + } + catch ( std::bad_alloc& exc ) { + error = SMESH_ComputeError::New( Driver_Mesh::DRS_FAIL, "std::bad_alloc raised" ); + } + catch ( Standard_OutOfMemory& exc ) { + error = SMESH_ComputeError::New( Driver_Mesh::DRS_FAIL, "Standard_OutOfMemory raised" ); + } + catch (Standard_Failure& ex) { + error = SMESH_ComputeError::New( Driver_Mesh::DRS_FAIL, ex.DynamicType()->Name() ); + if ( ex.GetMessageString() && strlen( ex.GetMessageString() )) + error->myComment += string(": ") + ex.GetMessageString(); + } + catch ( SALOME_Exception& S_ex ) { + error = SMESH_ComputeError::New( Driver_Mesh::DRS_FAIL, S_ex.what() ); + } + catch ( std::exception& exc ) { + error = SMESH_ComputeError::New( Driver_Mesh::DRS_FAIL, exc.what() ); + } + catch (...) { + error = SMESH_ComputeError::New( Driver_Mesh::DRS_FAIL, "Unknown exception" ); + } + + CreateGroupServants(); + + return ConvertComputeError( error ); +} + //============================================================================= /*! * @@ -2838,37 +2903,6 @@ void SMESH_Mesh_i::ExportSTL (const char *file, const bool isascii) _impl->ExportSTL(file, isascii); } -//============================================================================= -/*! - * \brief Class providing SMESHDS_Mesh API to SMESH_IDSource. - * It is used to export a part of mesh as a whole mesh. - */ -class SMESH_MeshPartDS : public SMESHDS_Mesh -{ -public: - SMESH_MeshPartDS(SMESH::SMESH_IDSource_ptr meshPart); - - virtual SMDS_NodeIteratorPtr nodesIterator (bool idInceasingOrder=false) const; - virtual SMDS_EdgeIteratorPtr edgesIterator (bool idInceasingOrder=false) const; - virtual SMDS_FaceIteratorPtr facesIterator (bool idInceasingOrder=false) const; - virtual SMDS_VolumeIteratorPtr volumesIterator (bool idInceasingOrder=false) const; - - virtual SMDS_ElemIteratorPtr elementsIterator(SMDSAbs_ElementType type=SMDSAbs_All) const; - virtual SMDS_ElemIteratorPtr elementGeomIterator(SMDSAbs_GeometryType type) const; - virtual SMDS_ElemIteratorPtr elementEntityIterator(SMDSAbs_EntityType type) const; - -private: - TIDSortedElemSet _elements[ SMDSAbs_NbElementTypes ]; - SMESHDS_Mesh* _meshDS; - /*! - * \brief Class used to access to protected data of SMDS_MeshInfo - */ - struct TMeshInfo : public SMDS_MeshInfo - { - void Add(const SMDS_MeshElement* e) { SMDS_MeshInfo::addWithPoly( e ); } - }; -}; - //================================================================================ /*! * \brief Export a part of mesh to a med file @@ -2991,13 +3025,36 @@ void SMESH_Mesh_i::ExportCGNS(::SMESH::SMESH_IDSource_ptr meshPart, SMESH_MeshPartDS partDS( meshPart ); _impl->ExportCGNS(file, &partDS); - TPythonDump() << _this() << ".ExportCGNS( " - << meshPart<< ", r'" << file << "', " << overwrite << ")"; + TPythonDump() << _this() << ".ExportCGNS( r'" + << file << "', " << overwrite << ", "<< meshPart<< ")"; #else THROW_SALOME_CORBA_EXCEPTION("CGNS library is unavailable", SALOME::INTERNAL_ERROR); #endif } +//================================================================================ +/*! + * \brief Export a part of mesh to a GMF file + */ +//================================================================================ + +void SMESH_Mesh_i::ExportGMF(::SMESH::SMESH_IDSource_ptr meshPart, + const char* file) + throw (SALOME::SALOME_Exception) +{ + Unexpect aCatch(SALOME_SalomeException); + if ( _preMeshInfo ) + _preMeshInfo->FullLoadFromFile(); + + PrepareForWriting(file,/*overwrite=*/true); + + SMESH_MeshPartDS partDS( meshPart ); + _impl->ExportGMF(file, &partDS); + + TPythonDump() << _this() << ".ExportGMF( r'" + << file << "', "<< meshPart<< ")"; +} + //============================================================================= /*! * Return implementation of SALOME_MED::MESH interfaces @@ -4083,7 +4140,7 @@ SMESH::double_array* SMESH_Mesh_i::BaryCenter(const CORBA::Long id) */ //============================================================================= -void SMESH_Mesh_i::CreateGroupServants() +void SMESH_Mesh_i::CreateGroupServants() { SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy(); @@ -4352,12 +4409,14 @@ void SMESH_Mesh_i::CollectMeshInfo(const SMDS_ElemIteratorPtr theItr, } //============================================================================= +namespace // Finding concurrent hypotheses +//============================================================================= +{ + /*! * \brief mapping of mesh dimension into shape type */ -//============================================================================= - -static TopAbs_ShapeEnum shapeTypeByDim(const int theDim) +TopAbs_ShapeEnum shapeTypeByDim(const int theDim) { TopAbs_ShapeEnum aType = TopAbs_SOLID; switch ( theDim ) { @@ -4370,7 +4429,7 @@ static TopAbs_ShapeEnum shapeTypeByDim(const int theDim) return aType; } -//============================================================================= +//----------------------------------------------------------------------------- /*! * \brief Internal structure used to find concurent submeshes * @@ -4379,8 +4438,6 @@ static TopAbs_ShapeEnum shapeTypeByDim(const int theDim) * with another submesh. In other words, it is dimension of a hypothesis assigned * to submesh. */ -//============================================================================= - class SMESH_DimHyp { public: @@ -4389,8 +4446,14 @@ class SMESH_DimHyp int _ownDim; //!< dimension of shape of _subMesh (>=_dim) TopTools_MapOfShape _shapeMap; SMESH_subMesh* _subMesh; - list _hypothesises; //!< algo is first, then its parameters + list _hypotheses; //!< algo is first, then its parameters + + //----------------------------------------------------------------------------- + // Return the algorithm + const SMESH_Algo* GetAlgo() const + { return _hypotheses.empty() ? 0 : dynamic_cast( _hypotheses.front() ); } + //----------------------------------------------------------------------------- //! Constructors SMESH_DimHyp(const SMESH_subMesh* theSubMesh, const int theDim, @@ -4400,6 +4463,7 @@ class SMESH_DimHyp SetShape( theDim, theShape ); } + //----------------------------------------------------------------------------- //! set shape void SetShape(const int theDim, const TopoDS_Shape& theShape) @@ -4415,6 +4479,7 @@ class SMESH_DimHyp } } + //----------------------------------------------------------------------------- //! Check sharing of sub-shapes static bool isShareSubShapes(const TopTools_MapOfShape& theToCheck, const TopTools_MapOfShape& theToFind, @@ -4435,11 +4500,13 @@ class SMESH_DimHyp return isShared; } + //----------------------------------------------------------------------------- //! check algorithms static bool checkAlgo(const SMESHDS_Hypothesis* theA1, const SMESHDS_Hypothesis* theA2) { - if ( theA1->GetType() == SMESHDS_Hypothesis::PARAM_ALGO || + if ( !theA1 || !theA2 || + theA1->GetType() == SMESHDS_Hypothesis::PARAM_ALGO || theA2->GetType() == SMESHDS_Hypothesis::PARAM_ALGO ) return false; // one of the hypothesis is not algorithm // check algorithm names (should be equal) @@ -4447,6 +4514,7 @@ class SMESH_DimHyp } + //----------------------------------------------------------------------------- //! Check if sub-shape hypotheses are concurrent bool IsConcurrent(const SMESH_DimHyp* theOther) const { @@ -4456,8 +4524,10 @@ class SMESH_DimHyp // if ( == && // any of the two submeshes is not on COMPOUND shape ) // -> no concurrency - bool meIsCompound = (_subMesh->GetSubMeshDS() && _subMesh->GetSubMeshDS()->IsComplexSubmesh()); - bool otherIsCompound = (theOther->_subMesh->GetSubMeshDS() && theOther->_subMesh->GetSubMeshDS()->IsComplexSubmesh()); + bool meIsCompound = (_subMesh->GetSubMeshDS() && + _subMesh->GetSubMeshDS()->IsComplexSubmesh()); + bool otherIsCompound = (theOther->_subMesh->GetSubMeshDS() && + theOther->_subMesh->GetSubMeshDS()->IsComplexSubmesh()); if ( (_ownDim == _dim || theOther->_ownDim == _dim ) && (!meIsCompound || !otherIsCompound)) return false; @@ -4469,65 +4539,102 @@ class SMESH_DimHyp return false; // check algorithms to be same - if (!checkAlgo( _hypothesises.front(), theOther->_hypothesises.front() )) - return true; // different algorithms - + if ( !checkAlgo( this->GetAlgo(), theOther->GetAlgo() )) + return true; // different algorithms -> concurrency ! + // check hypothesises for concurrence (skip first as algorithm) int nbSame = 0; - // pointers should be same, becase it is referenes from mesh hypothesis partition - list ::const_iterator hypIt = _hypothesises.begin(); - list ::const_iterator otheEndIt = theOther->_hypothesises.end(); - for ( hypIt++ /*skip first as algo*/; hypIt != _hypothesises.end(); hypIt++ ) - if ( find( theOther->_hypothesises.begin(), otheEndIt, *hypIt ) != otheEndIt ) + // pointers should be same, because it is referened from mesh hypothesis partition + list ::const_iterator hypIt = _hypotheses.begin(); + list ::const_iterator otheEndIt = theOther->_hypotheses.end(); + for ( hypIt++ /*skip first as algo*/; hypIt != _hypotheses.end(); hypIt++ ) + if ( find( theOther->_hypotheses.begin(), otheEndIt, *hypIt ) != otheEndIt ) nbSame++; // the submeshes are concurrent if their algorithms has different parameters - return nbSame != theOther->_hypothesises.size() - 1; + return nbSame != theOther->_hypotheses.size() - 1; + } + + // Return true if algorithm of this SMESH_DimHyp is used if no + // sub-mesh order is imposed by the user + bool IsHigherPriorityThan( const SMESH_DimHyp* theOther ) const + { + // NeedDiscreteBoundary() algo has a higher priority + if ( this ->GetAlgo()->NeedDiscreteBoundary() != + theOther->GetAlgo()->NeedDiscreteBoundary() ) + return !this->GetAlgo()->NeedDiscreteBoundary(); + + return ( this->_subMesh->GetId() < theOther->_subMesh->GetId() ); } }; // end of SMESH_DimHyp +//----------------------------------------------------------------------------- + +typedef list TDimHypList; -typedef list TDimHypList; +//----------------------------------------------------------------------------- -static void addDimHypInstance(const int theDim, - const TopoDS_Shape& theShape, - const SMESH_Algo* theAlgo, - const SMESH_subMesh* theSubMesh, - const list & theHypList, - TDimHypList* theDimHypListArr ) +void addDimHypInstance(const int theDim, + const TopoDS_Shape& theShape, + const SMESH_Algo* theAlgo, + const SMESH_subMesh* theSubMesh, + const list & theHypList, + TDimHypList* theDimHypListArr ) { TDimHypList& listOfdimHyp = theDimHypListArr[theDim]; if ( listOfdimHyp.empty() || listOfdimHyp.back()->_subMesh != theSubMesh ) { SMESH_DimHyp* dimHyp = new SMESH_DimHyp( theSubMesh, theDim, theShape ); + dimHyp->_hypotheses.push_front(theAlgo); listOfdimHyp.push_back( dimHyp ); } - SMESH_DimHyp* dimHyp = listOfdimHyp.back(); - dimHyp->_hypothesises.push_front(theAlgo); - list ::const_iterator hypIt = theHypList.begin(); - for( ; hypIt != theHypList.end(); hypIt++ ) - dimHyp->_hypothesises.push_back( *hypIt ); + SMESH_DimHyp* dimHyp = const_cast( listOfdimHyp.back() ); + dimHyp->_hypotheses.insert( dimHyp->_hypotheses.end(), + theHypList.begin(), theHypList.end() ); } -static void findConcurrents(const SMESH_DimHyp* theDimHyp, - const TDimHypList& theListOfDimHyp, - TListOfInt& theListOfConcurr ) +//----------------------------------------------------------------------------- +void addInOrderOfPriority( const SMESH_DimHyp* theDimHyp, + TDimHypList& theListOfConcurr) +{ + if ( theListOfConcurr.empty() ) + { + theListOfConcurr.push_back( theDimHyp ); + } + else + { + TDimHypList::iterator hypIt = theListOfConcurr.begin(); + while ( hypIt != theListOfConcurr.end() && + !theDimHyp->IsHigherPriorityThan( *hypIt )) + ++hypIt; + theListOfConcurr.insert( hypIt, theDimHyp ); + } +} + +//----------------------------------------------------------------------------- +void findConcurrents(const SMESH_DimHyp* theDimHyp, + const TDimHypList& theListOfDimHyp, + TDimHypList& theListOfConcurrHyp, + set& theSetOfConcurrId ) { TDimHypList::const_reverse_iterator rIt = theListOfDimHyp.rbegin(); - for ( ; rIt != theListOfDimHyp.rend(); rIt++ ) { + for ( ; rIt != theListOfDimHyp.rend(); rIt++ ) + { const SMESH_DimHyp* curDimHyp = *rIt; if ( curDimHyp == theDimHyp ) break; // meet own dimHyp pointer in same dimension - else if ( theDimHyp->IsConcurrent( curDimHyp ) ) - if ( find( theListOfConcurr.begin(), - theListOfConcurr.end(), - curDimHyp->_subMesh->GetId() ) == theListOfConcurr.end() ) - theListOfConcurr.push_back( curDimHyp->_subMesh->GetId() ); + + if ( theDimHyp->IsConcurrent( curDimHyp ) && + theSetOfConcurrId.insert( curDimHyp->_subMesh->GetId() ).second ) + { + addInOrderOfPriority( curDimHyp, theListOfConcurrHyp ); + } } } -static void unionLists(TListOfInt& theListOfId, - TListOfListOfInt& theListOfListOfId, - const int theIndx ) +//----------------------------------------------------------------------------- +void unionLists(TListOfInt& theListOfId, + TListOfListOfInt& theListOfListOfId, + const int theIndx ) { TListOfListOfInt::iterator it = theListOfListOfId.begin(); for ( int i = 0; it != theListOfListOfId.end(); it++, i++ ) { @@ -4549,9 +4656,10 @@ static void unionLists(TListOfInt& theListOfId, otherListOfId.clear(); } } +//----------------------------------------------------------------------------- //! free memory allocated for dimension-hypothesis objects -static void removeDimHyps( TDimHypList* theArrOfList ) +void removeDimHyps( TDimHypList* theArrOfList ) { for (int i = 0; i < 4; i++ ) { TDimHypList& listOfdimHyp = theArrOfList[i]; @@ -4561,6 +4669,28 @@ static void removeDimHyps( TDimHypList* theArrOfList ) } } +//----------------------------------------------------------------------------- +/*! + * \brief find common submeshes with given submesh + * \param theSubMeshList list of already collected submesh to check + * \param theSubMesh given submesh to intersect with other + * \param theCommonSubMeshes collected common submeshes + */ +void findCommonSubMesh (list& theSubMeshList, + const SMESH_subMesh* theSubMesh, + set& theCommon ) +{ + if ( !theSubMesh ) + return; + list::const_iterator it = theSubMeshList.begin(); + for ( ; it != theSubMeshList.end(); it++ ) + theSubMesh->FindIntersection( *it, theCommon ); + theSubMeshList.push_back( theSubMesh ); + //theCommon.insert( theSubMesh ); +} + +} // namespace + //============================================================================= /*! * \brief Return submesh objects list in meshing order @@ -4579,7 +4709,7 @@ SMESH::submesh_array_array* SMESH_Mesh_i::GetMeshOrder() TListOfListOfInt anOrder = mesh.GetMeshOrder(); // is there already defined order? if ( !anOrder.size() ) { - // collect submeshes detecting concurrent algorithms and hypothesises + // collect submeshes and detect concurrent algorithms and hypothesises TDimHypList dimHypListArr[4]; // dimHyp list for each shape dimension map::iterator i_sm = _mapSubMesh.begin(); @@ -4587,7 +4717,7 @@ SMESH::submesh_array_array* SMESH_Mesh_i::GetMeshOrder() ::SMESH_subMesh* sm = (*i_sm).second; // shape of submesh const TopoDS_Shape& aSubMeshShape = sm->GetSubShape(); - + // list of assigned hypothesises const list & hypList = mesh.GetHypothesisList(aSubMeshShape); // Find out dimensions where the submesh can be concurrent. @@ -4606,7 +4736,7 @@ SMESH::submesh_array_array* SMESH_Mesh_i::GetMeshOrder() anAlgo = mesh.GetGen()->GetAlgo( mesh, anExp.Current() ); } if (!anAlgo) - continue; // no assigned algorithm to current submesh + continue; // no algorithm assigned to a current submesh int dim = anAlgo->GetDim(); // top concurrent dimension (see comment to SMESH_DimHyp) // the submesh can concurrent at (or lower dims if !anAlgo->NeedDiscreteBoundary()) @@ -4619,20 +4749,25 @@ SMESH::submesh_array_array* SMESH_Mesh_i::GetMeshOrder() // iterate on created dimension-hypotheses and check for concurrents for ( int i = 0; i < 4; i++ ) { - const list& listOfDimHyp = dimHypListArr[i]; + const TDimHypList& listOfDimHyp = dimHypListArr[i]; // check for concurrents in own and other dimensions (step-by-step) TDimHypList::const_iterator dhIt = listOfDimHyp.begin(); for ( ; dhIt != listOfDimHyp.end(); dhIt++ ) { const SMESH_DimHyp* dimHyp = *dhIt; - TListOfInt listOfConcurr; + TDimHypList listOfConcurr; + set setOfConcurrIds; // looking for concurrents and collect into own list for ( int j = i; j < 4; j++ ) - findConcurrents( dimHyp, dimHypListArr[j], listOfConcurr ); + findConcurrents( dimHyp, dimHypListArr[j], listOfConcurr, setOfConcurrIds ); // check if any concurrents found if ( listOfConcurr.size() > 0 ) { // add own submesh to list of concurrent - listOfConcurr.push_front( dimHyp->_subMesh->GetId() ); - anOrder.push_back( listOfConcurr ); + addInOrderOfPriority( dimHyp, listOfConcurr ); + list listOfConcurrIds; + TDimHypList::iterator hypIt = listOfConcurr.begin(); + for ( ; hypIt != listOfConcurr.end(); ++hypIt ) + listOfConcurrIds.push_back( (*hypIt)->_subMesh->GetId() ); + anOrder.push_back( listOfConcurrIds ); } } } @@ -4655,28 +4790,6 @@ SMESH::submesh_array_array* SMESH_Mesh_i::GetMeshOrder() return aResult._retn(); } -//============================================================================= -/*! - * \brief find common submeshes with given submesh - * \param theSubMeshList list of already collected submesh to check - * \param theSubMesh given submesh to intersect with other - * \param theCommonSubMeshes collected common submeshes - */ -//============================================================================= - -static void findCommonSubMesh (list& theSubMeshList, - const SMESH_subMesh* theSubMesh, - set& theCommon ) -{ - if ( !theSubMesh ) - return; - list::const_iterator it = theSubMeshList.begin(); - for ( ; it != theSubMeshList.end(); it++ ) - theSubMesh->FindIntersection( *it, theCommon ); - theSubMeshList.push_back( theSubMesh ); - //theCommon.insert( theSubMesh ); -} - //============================================================================= /*! * \brief Set submesh object order @@ -4845,6 +4958,27 @@ SMESH_MeshPartDS::SMESH_MeshPartDS(SMESH::SMESH_IDSource_ptr meshPart): } } // ------------------------------------------------------------------------------------- +SMESH_MeshPartDS::SMESH_MeshPartDS(const std::list< const SMDS_MeshElement* > & meshPart): + SMESHDS_Mesh( /*meshID=*/-1, /*isEmbeddedMode=*/true), _meshDS(0) +{ + TMeshInfo tmpInfo; + list< const SMDS_MeshElement* >::const_iterator partIt = meshPart.begin(); + for ( ; partIt != meshPart.end(); ++partIt ) + if ( const SMDS_MeshElement * e = *partIt ) + if ( _elements[ e->GetType() ].insert( e ).second ) + { + tmpInfo.Add( e ); + SMDS_ElemIteratorPtr nIt = e->nodesIterator(); + while ( nIt->more() ) + { + const SMDS_MeshNode * n = (const SMDS_MeshNode*) nIt->next(); + if ( _elements[ SMDSAbs_Node ].insert( n ).second ) + tmpInfo.Add( n ); + } + } + myInfo = tmpInfo; +} +// ------------------------------------------------------------------------------------- SMDS_ElemIteratorPtr SMESH_MeshPartDS::elementGeomIterator(SMDSAbs_GeometryType geomType) const { if ( _meshDS ) return _meshDS->elementGeomIterator( geomType ); diff --git a/src/SMESH_I/SMESH_Mesh_i.hxx b/src/SMESH_I/SMESH_Mesh_i.hxx index 3c13916a4..0c2a3ca97 100644 --- a/src/SMESH_I/SMESH_Mesh_i.hxx +++ b/src/SMESH_I/SMESH_Mesh_i.hxx @@ -29,6 +29,7 @@ #include "SMESH.hxx" #include +#include CORBA_SERVER_HEADER(SMESH_Gen) #include CORBA_SERVER_HEADER(SMESH_Mesh) #include CORBA_SERVER_HEADER(SMESH_Group) #include CORBA_SERVER_HEADER(SMESH_Hypothesis) @@ -37,7 +38,6 @@ #include "SMESH_Hypothesis.hxx" #include "SMESH_Mesh.hxx" -//#include "SMESH_subMesh_i.hxx" #include "SMESH_subMesh.hxx" #include "SALOME_GenericObj_i.hh" @@ -198,6 +198,9 @@ public: int ImportSTLFile( const char* theFileName ) throw (SALOME::SALOME_Exception); + SMESH::ComputeError* ImportGMFFile( const char* theFileName ) + throw (SALOME::SALOME_Exception); + /*! * consult DriverMED_R_SMESHDS_Mesh::ReadStatus for returned value */ @@ -245,6 +248,8 @@ public: void ExportCGNS(SMESH::SMESH_IDSource_ptr meshPart, const char* file, CORBA::Boolean overwrite) throw (SALOME::SALOME_Exception); + void ExportGMF(SMESH::SMESH_IDSource_ptr meshPart, + const char* file) throw (SALOME::SALOME_Exception); void ExportPartToMED(SMESH::SMESH_IDSource_ptr meshPart, const char* file, diff --git a/src/SMESH_I/SMESH_PreMeshInfo.cxx b/src/SMESH_I/SMESH_PreMeshInfo.cxx index e56adfadf..0a3d58614 100644 --- a/src/SMESH_I/SMESH_PreMeshInfo.cxx +++ b/src/SMESH_I/SMESH_PreMeshInfo.cxx @@ -858,7 +858,7 @@ void SMESH_PreMeshInfo::FullLoadFromFile() const SMESH_PreMeshInfo* meshInfo = _mesh->changePreMeshInfo(); _mesh->changePreMeshInfo() = NULL; // to allow GUI accessing to real info - ::SMESH_Mesh& mesh = _mesh->GetImpl(); + ::SMESH_Mesh& mesh = _mesh->GetImpl(); SMESHDS_Mesh* meshDS = mesh.GetMeshDS(); PreMeshInfo_TRY; @@ -919,6 +919,18 @@ void SMESH_PreMeshInfo::readSubMeshes(DriverMED_R_SMESHDS_Mesh* reader) const SMESHDS_Mesh* meshDS = _mesh->GetImpl().GetMeshDS(); + // issue 0020693. Restore _isModified flag + if ( aTopGroup->ExistInternalObject( "_isModified" )) + { + HDFdataset* aDataset = new HDFdataset( "_isModified", aTopGroup ); + aDataset->OpenOnDisk(); + hdf_size size = aDataset->GetSize(); + int* isModified = new int[ size ]; + aDataset->ReadFromDisk( isModified ); + aDataset->CloseOnDisk(); + _mesh->GetImpl().SetIsModified( bool(*isModified)); + } + bool submeshesInFamilies = ( ! aTopGroup->ExistInternalObject( "Submeshes" )); if ( submeshesInFamilies ) // from MED { diff --git a/src/SMESH_SWIG/Makefile.am b/src/SMESH_SWIG/Makefile.am index ab94f663c..fd1f9e29c 100644 --- a/src/SMESH_SWIG/Makefile.am +++ b/src/SMESH_SWIG/Makefile.am @@ -26,9 +26,10 @@ include $(top_srcdir)/adm_local/unix/make_common_starter.am # Scripts to be installed. -dist_salomescript_DATA= \ +dist_salomescript_PYTHON = \ smesh.py \ smeshDC.py \ + smesh_algorithm.py \ StdMeshersDC.py \ batchmode_smesh.py \ batchmode_mefisto.py \ diff --git a/src/SMESH_SWIG/StdMeshersDC.py b/src/SMESH_SWIG/StdMeshersDC.py index af20cb4e2..03d598d1b 100644 --- a/src/SMESH_SWIG/StdMeshersDC.py +++ b/src/SMESH_SWIG/StdMeshersDC.py @@ -17,45 +17,72 @@ # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com # -from smesh import Mesh_Algorithm, AssureGeomPublished, IsEqual, ParseParameters +## +# @package StdMeshersDC +# Python API for the standard meshing plug-in module. + +from smesh_algorithm import Mesh_Algorithm +from smesh import AssureGeomPublished, IsEqual, ParseParameters from smesh import GetName, TreatHypoStatus from smeshDC import Mesh import StdMeshers -# Types of algorithms +#---------------------------- +# Mesh algo type identifiers +#---------------------------- + +## Algorithm type: Regular 1D algorithm, see StdMeshersDC_Segment REGULAR = "Regular_1D" +## Algorithm type: Python 1D algorithm, see StdMeshersDC_Segment_Python PYTHON = "Python_1D" +## Algorithm type: Composite segment 1D algorithm, see StdMeshersDC_CompositeSegment COMPOSITE = "CompositeSegment_1D" +## Algorithm type: Triangle MEFISTO 2D algorithm, see StdMeshersDC_Triangle_MEFISTO MEFISTO = "MEFISTO_2D" +## Algorithm type: Hexahedron 3D (i-j-k) algorithm, see StdMeshersDC_Hexahedron Hexa = "Hexa_3D" +## Algorithm type: Quadrangle 2D algorithm, see StdMeshersDC_Quadrangle QUADRANGLE = "Quadrangle_2D" +## Algorithm type: Radial Quadrangle 1D-2D algorithm, see StdMeshersDC_RadialQuadrangle1D2D RADIAL_QUAD = "RadialQuadrangle_1D2D" - # import items of enum QuadType for e in StdMeshers.QuadType._items: exec('%s = StdMeshers.%s'%(e,e)) +#---------------------- +# Algorithms +#---------------------- -# Public class: Mesh_Segment -# -------------------------- - -## Class to define a REGULAR 1D algorithm for discretization. It is created by -# calling Mesh.Segment(geom=0) +## Defines segment 1D algorithm for edges discretization. +# +# It can be created by calling smesh.Mesh.Segment(geom=0) # # @ingroup l3_algos_basic class StdMeshersDC_Segment(Mesh_Algorithm): - ## Name of method of class Mesh creating an instance of this class + ## name of the dynamic method in smesh.Mesh class + # @internal meshMethod = "Segment" - ## Name of algorithm type + ## type of algorithm used with helper function in smesh.Mesh class + # @internal algoType = REGULAR + ## flag pointing either this algorithm should be used by default in dynamic method + # of smesh.Mesh class + # @internal isDefault = True + ## doc string of the method + # @internal + docHelper = "Creates segment 1D algorithm for edges" ## Private constructor. + # @param mesh parent mesh object algorithm is assigned to + # @param geom geometry (shape/sub-shape) algorithm is assigned to; + # if it is @c 0 (default), the algorithm is assigned to the main shape def __init__(self, mesh, geom=0): Mesh_Algorithm.__init__(self) self.Create(mesh, geom, self.algoType) + pass ## Defines "LocalLength" hypothesis to cut an edge in several segments with the same length # @param l for the length of segments that cut an edge @@ -135,7 +162,8 @@ class StdMeshersDC_Segment(Mesh_Algorithm): return hyp ## Private method - ## Checks if the given "NumberOfSegments" hypothesis has the same parameters as the given arguments + # + # Checks if the given "NumberOfSegments" hypothesis has the same parameters as the given arguments def _compareNumberOfSegments(self, hyp, args): if hyp.GetNumberOfSegments() == args[0]: if len(args) == 3: @@ -282,7 +310,7 @@ class StdMeshersDC_Segment(Mesh_Algorithm): else: self.geom = vertex pass - ### 0D algorithm + # 0D algorithm if self.geom is None: raise RuntimeError, "Attemp to create SegmentAroundVertex_0D algoritm on None shape" AssureGeomPublished( self.mesh, self.geom ) @@ -294,7 +322,7 @@ class StdMeshersDC_Segment(Mesh_Algorithm): pass status = self.mesh.mesh.AddHypothesis(self.geom, algo) TreatHypoStatus(status, "SegmentAroundVertex_0D", name, True) - ### + # comFun = lambda hyp, args: IsEqual(hyp.GetLength(), args[0]) hyp = self.Hypothesis("SegmentLengthAroundVertex", [length], UseExisting=UseExisting, CompareMethod=comFun) @@ -314,44 +342,67 @@ class StdMeshersDC_Segment(Mesh_Algorithm): hyp = self.Hypothesis("QuadraticMesh", UseExisting=1, CompareMethod=self.CompareEqualHyp) return hyp -# Public class: Mesh_CompositeSegment -# -------------------------- + pass # end of StdMeshersDC_Segment class -## A regular 1D algorithm for discretization of a set of adjacent edges as one. -# It is created by calling Mesh.Segment(COMPOSITE,geom=0) +## Segment 1D algorithm for discretization of a set of adjacent edges as one edge. +# +# It is created by calling smesh.Mesh.Segment(smesh.COMPOSITE,geom=0) # # @ingroup l3_algos_basic class StdMeshersDC_CompositeSegment(StdMeshersDC_Segment): - ## Name of method of class Mesh creating an instance of this class + ## name of the dynamic method in smesh.Mesh class + # @internal meshMethod = "Segment" - ## Name of algorithm type + ## type of algorithm used with helper function in smesh.Mesh class + # @internal algoType = COMPOSITE + ## flag pointing either this algorithm should be used by default in dynamic method + # of smesh.Mesh class + # @internal isDefault = False + ## doc string of the method + # @internal + docHelper = "Creates segment 1D algorithm for edges" ## Private constructor. + # @param mesh parent mesh object algorithm is assigned to + # @param geom geometry (shape/sub-shape) algorithm is assigned to; + # if it is @c 0 (default), the algorithm is assigned to the main shape def __init__(self, mesh, geom=0): self.Create(mesh, geom, self.algoType) + pass + pass # end of StdMeshersDC_CompositeSegment class -# Public class: Mesh_Segment_Python -# --------------------------------- - -## Defines a segment 1D algorithm for discretization with python function -# It is created by calling Mesh.Segment(PYTHON,geom=0) +## Defines a segment 1D algorithm for discretization of edges with Python function +# +# It is created by calling smesh.Mesh.Segment(smesh.PYTHON,geom=0) # # @ingroup l3_algos_basic class StdMeshersDC_Segment_Python(Mesh_Algorithm): - ## Name of method of class Mesh creating an instance of this class + ## name of the dynamic method in smesh.Mesh class + # @internal meshMethod = "Segment" - ## Name of algorithm type + ## type of algorithm used with helper function in smesh.Mesh class + # @internal algoType = PYTHON + ## doc string of the method + # @internal + docHelper = "Creates tetrahedron 3D algorithm for solids" + ## doc string of the method + # @internal + docHelper = "Creates segment 1D algorithm for edges" ## Private constructor. + # @param mesh parent mesh object algorithm is assigned to + # @param geom geometry (shape/sub-shape) algorithm is assigned to; + # if it is @c 0 (default), the algorithm is assigned to the main shape def __init__(self, mesh, geom=0): import Python1dPlugin self.Create(mesh, geom, self.algoType, "libPython1dEngine.so") + pass ## Defines "PythonSplit1D" hypothesis # @param n for the number of segments that cut an edge @@ -367,25 +418,37 @@ class StdMeshersDC_Segment_Python(Mesh_Algorithm): hyp.SetPythonLog10RatioFunction(func) return hyp -# Public class: Mesh_Triangle_MEFISTO -# ----------------------------------- + pass # end of StdMeshersDC_Segment_Python class ## Triangle MEFISTO 2D algorithm -# It is created by calling Mesh.Triangle(MEFISTO,geom=0) +# +# It is created by calling smesh.Mesh.Triangle(smesh.MEFISTO,geom=0) # # @ingroup l3_algos_basic class StdMeshersDC_Triangle_MEFISTO(Mesh_Algorithm): - ## Name of method of class Mesh creating an instance of this class + ## name of the dynamic method in smesh.Mesh class + # @internal meshMethod = "Triangle" - ## Name of algorithm type + ## type of algorithm used with helper function in smesh.Mesh class + # @internal algoType = MEFISTO + ## flag pointing either this algorithm should be used by default in dynamic method + # of smesh.Mesh class + # @internal isDefault = True + ## doc string of the method + # @internal + docHelper = "Creates triangle 2D algorithm for faces" ## Private constructor. + # @param mesh parent mesh object algorithm is assigned to + # @param geom geometry (shape/sub-shape) algorithm is assigned to; + # if it is @c 0 (default), the algorithm is assigned to the main shape def __init__(self, mesh, geom=0): Mesh_Algorithm.__init__(self) self.Create(mesh, geom, self.algoType) + pass ## Defines "MaxElementArea" hypothesis basing on the definition of the maximum area of each triangle # @param area for the maximum area of each triangle @@ -408,28 +471,40 @@ class StdMeshersDC_Triangle_MEFISTO(Mesh_Algorithm): hyp = self.Hypothesis("LengthFromEdges", UseExisting=1, CompareMethod=self.CompareEqualHyp) return hyp -# Public class: Mesh_Quadrangle -# ----------------------------- + pass # end of StdMeshersDC_Triangle_MEFISTO class ## Defines a quadrangle 2D algorithm -# It is created by calling Mesh.Quadrangle(geom=0) +# +# It is created by calling smesh.Mesh.Quadrangle(geom=0) # # @ingroup l3_algos_basic class StdMeshersDC_Quadrangle(Mesh_Algorithm): - ## Name of method of class Mesh creating an instance of this class + ## name of the dynamic method in smesh.Mesh class + # @internal meshMethod = "Quadrangle" - ## Name of algorithm type + ## type of algorithm used with helper function in smesh.Mesh class + # @internal algoType = QUADRANGLE + ## flag pointing either this algorithm should be used by default in dynamic method + # of smesh.Mesh class + # @internal isDefault = True - - params=0 + ## doc string of the method + # @internal + docHelper = "Creates quadrangle 2D algorithm for faces" + ## hypothesis associated with algorithm + # @internal + params = 0 ## Private constructor. + # @param mesh parent mesh object algorithm is assigned to + # @param geom geometry (shape/sub-shape) algorithm is assigned to; + # if it is @c 0 (default), the algorithm is assigned to the main shape def __init__(self, mesh, geom=0): Mesh_Algorithm.__init__(self) self.Create(mesh, geom, self.algoType) - return + pass ## Defines "QuadrangleParameters" hypothesis # @param quadType defines the algorithm of transition between differently descretized @@ -515,47 +590,69 @@ class StdMeshersDC_Quadrangle(Mesh_Algorithm): def TriangleVertex(self, vertex, UseExisting=0): return self.QuadrangleParameters(QUAD_STANDARD,vertex,UseExisting) - -# Public class: Mesh_Hexahedron -# ------------------------------ + pass # end of StdMeshersDC_Quadrangle class ## Defines a hexahedron 3D algorithm -# It is created by calling Mesh.Hexahedron(geom=0) +# +# It is created by calling smesh.Mesh.Hexahedron(geom=0) # # @ingroup l3_algos_basic class StdMeshersDC_Hexahedron(Mesh_Algorithm): - ## Name of method of class Mesh creating an instance of this class + ## name of the dynamic method in smesh.Mesh class + # @internal meshMethod = "Hexahedron" - ## Name of algorithm type + ## type of algorithm used with helper function in smesh.Mesh class + # @internal algoType = Hexa + ## flag pointing either this algorithm should be used by default in dynamic method + # of smesh.Mesh class + # @internal isDefault = True + ## doc string of the method + # @internal + docHelper = "Creates hexahedron 3D algorithm for volumes" ## Private constructor. + # @param mesh parent mesh object algorithm is assigned to + # @param geom geometry (shape/sub-shape) algorithm is assigned to; + # if it is @c 0 (default), the algorithm is assigned to the main shape def __init__(self, mesh, geom=0): Mesh_Algorithm.__init__(self) self.Create(mesh, geom, Hexa) pass -# Public class: Mesh_Projection1D -# ------------------------------- + pass # end of StdMeshersDC_Hexahedron class ## Defines a projection 1D algorithm -# It is created by calling Mesh.Projection1D(geom=0) -# @ingroup l3_algos_proj +# +# It is created by calling smesh.Mesh.Projection1D(geom=0) # +# @ingroup l3_algos_proj class StdMeshersDC_Projection1D(Mesh_Algorithm): - ## Name of method of class Mesh creating an instance of this class + ## name of the dynamic method in smesh.Mesh class + # @internal meshMethod = "Projection1D" - ## Name of algorithm type + ## type of algorithm used with helper function in smesh.Mesh class + # @internal algoType = "Projection_1D" + ## flag pointing either this algorithm should be used by default in dynamic method + # of smesh.Mesh class + # @internal isDefault = True + ## doc string of the method + # @internal + docHelper = "Creates projection 1D algorithm for edges" ## Private constructor. + # @param mesh parent mesh object algorithm is assigned to + # @param geom geometry (shape/sub-shape) algorithm is assigned to; + # if it is @c 0 (default), the algorithm is assigned to the main shape def __init__(self, mesh, geom=0): Mesh_Algorithm.__init__(self) self.Create(mesh, geom, self.algoType) + pass ## Defines "Source Edge" hypothesis, specifying a meshed edge, from where # a mesh pattern is taken, and, optionally, the association of vertices @@ -582,26 +679,37 @@ class StdMeshersDC_Projection1D(Mesh_Algorithm): hyp.SetVertexAssociation( srcV, tgtV ) return hyp - -# Public class: Mesh_Projection2D -# ------------------------------ + pass # end of StdMeshersDC_Projection1D class ## Defines a projection 2D algorithm -# It is created by calling Mesh.Projection2D(geom=0) -# @ingroup l3_algos_proj +# +# It is created by calling smesh.Mesh.Projection2D(geom=0) # +# @ingroup l3_algos_proj class StdMeshersDC_Projection2D(Mesh_Algorithm): - ## Name of method of class Mesh creating an instance of this class + ## name of the dynamic method in smesh.Mesh class + # @internal meshMethod = "Projection2D" - ## Name of algorithm type + ## type of algorithm used with helper function in smesh.Mesh class + # @internal algoType = "Projection_2D" + ## flag pointing either this algorithm should be used by default in dynamic method + # of smesh.Mesh class + # @internal isDefault = True + ## doc string of the method + # @internal + docHelper = "Creates projection 2D algorithm for faces" ## Private constructor. + # @param mesh parent mesh object algorithm is assigned to + # @param geom geometry (shape/sub-shape) algorithm is assigned to; + # if it is @c 0 (default), the algorithm is assigned to the main shape def __init__(self, mesh, geom=0): Mesh_Algorithm.__init__(self) self.Create(mesh, geom, self.algoType) + pass ## Defines "Source Face" hypothesis, specifying a meshed face, from where # a mesh pattern is taken, and, optionally, the association of vertices @@ -634,44 +742,60 @@ class StdMeshersDC_Projection2D(Mesh_Algorithm): hyp.SetVertexAssociation( srcV1, srcV2, tgtV1, tgtV2 ) return hyp -# Public class: Mesh_Projection1D2D -# --------------------------------- + pass # end of StdMeshersDC_Projection2D class ## Defines a projection 1D-2D algorithm -# It is created by calling Mesh.Projection1D2D(geom=0) +# +# It is created by calling smesh.Mesh.Projection1D2D(geom=0) # # @ingroup l3_algos_proj - class StdMeshersDC_Projection1D2D(StdMeshersDC_Projection2D): - ## Name of method of class Mesh creating an instance of this class + ## name of the dynamic method in smesh.Mesh class + # @internal meshMethod = "Projection1D2D" - ## Name of algorithm type + ## type of algorithm used with helper function in smesh.Mesh class + # @internal algoType = "Projection_1D2D" + ## doc string of the method + # @internal + docHelper = "Creates projection 1D-2D algorithm for edges and faces" ## Private constructor. + # @param mesh parent mesh object algorithm is assigned to + # @param geom geometry (shape/sub-shape) algorithm is assigned to; + # if it is @c 0 (default), the algorithm is assigned to the main shape def __init__(self, mesh, geom=0): StdMeshersDC_Projection2D.__init__(self, mesh, geom) + pass -# Public class: Mesh_Projection3D -# ------------------------------ + pass # end of StdMeshersDC_Projection1D2D class ## Defines a projection 3D algorithm -# It is created by calling Mesh.Projection3D(COMPOSITE) +# +# It is created by calling smesh.Mesh.Projection3D(geom=0) # # @ingroup l3_algos_proj -# class StdMeshersDC_Projection3D(Mesh_Algorithm): - ## Name of method of class Mesh creating an instance of this class + ## name of the dynamic method in smesh.Mesh class + # @internal meshMethod = "Projection3D" - ## Name of algorithm type + ## type of algorithm used with helper function in smesh.Mesh class + # @internal algoType = "Projection_3D" + ## doc string of the method + # @internal + docHelper = "Creates projection 3D algorithm for volumes" ## Private constructor. + # @param mesh parent mesh object algorithm is assigned to + # @param geom geometry (shape/sub-shape) algorithm is assigned to; + # if it is @c 0 (default), the algorithm is assigned to the main shape def __init__(self, mesh, geom=0): Mesh_Algorithm.__init__(self) self.Create(mesh, geom, self.algoType) + pass ## Defines the "Source Shape 3D" hypothesis, specifying a meshed solid, from where # the mesh pattern is taken, and, optionally, the association of vertices @@ -707,23 +831,30 @@ class StdMeshersDC_Projection3D(Mesh_Algorithm): #elif srcV1 or srcV2 or tgtV1 or tgtV2: return hyp -# Public class: Mesh_Prism -# ------------------------ + pass # end of StdMeshersDC_Projection3D class ## Defines a Prism 3D algorithm, which is either "Extrusion 3D" or "Radial Prism" # depending on geometry -# It is created by calling Mesh.Prism(geom=0) +# +# It is created by calling smesh.Mesh.Prism(geom=0) # # @ingroup l3_algos_3dextr -# class StdMeshersDC_Prism3D(Mesh_Algorithm): - ## Name of method of class Mesh creating an instance of this class + ## name of the dynamic method in smesh.Mesh class + # @internal meshMethod = "Prism" - ## Name of algorithm type + ## type of algorithm used with helper function in smesh.Mesh class + # @internal algoType = "Prism_3D" + ## doc string of the method + # @internal + docHelper = "Creates prism 3D algorithm for volumes" ## Private constructor. + # @param mesh parent mesh object algorithm is assigned to + # @param geom geometry (shape/sub-shape) algorithm is assigned to; + # if it is @c 0 (default), the algorithm is assigned to the main shape def __init__(self, mesh, geom=0): Mesh_Algorithm.__init__(self) @@ -735,11 +866,14 @@ class StdMeshersDC_Prism3D(Mesh_Algorithm): nbShells = len( SubShapeAll( shape, ShapeType["SHELL"] )) if nbSolids == 0 or nbSolids == nbShells: self.Create(mesh, geom, "Prism_3D") + pass else: self.algoType = "RadialPrism_3D" self.Create(mesh, geom, "RadialPrism_3D") self.distribHyp = self.Hypothesis("LayerDistribution", UseExisting=0) self.nbLayers = None + pass + pass ## Return 3D hypothesis holding the 1D one def Get3DHypothesis(self): @@ -847,28 +981,36 @@ class StdMeshersDC_Prism3D(Mesh_Algorithm): hyp.SetFineness( fineness ) return hyp + pass # end of StdMeshersDC_Prism3D class -# Public class: Mesh_RadialQuadrangle1D2D -# ------------------------------- - -## Defines a Radial Quadrangle 1D2D algorithm -# It is created by calling Mesh.Quadrangle(RADIAL_QUAD,geom=0) +## Defines a Radial Quadrangle 1D-2D algorithm +# +# It is created by calling smesh.Mesh.Quadrangle(smesh.RADIAL_QUAD,geom=0) # # @ingroup l2_algos_radialq class StdMeshersDC_RadialQuadrangle1D2D(Mesh_Algorithm): - ## Name of method of class Mesh creating an instance of this class + ## name of the dynamic method in smesh.Mesh class + # @internal meshMethod = "Quadrangle" - ## Name of algorithm type + ## type of algorithm used with helper function in smesh.Mesh class + # @internal algoType = RADIAL_QUAD + ## doc string of the method + # @internal + docHelper = "Creates quadrangle 1D-2D algorithm for triangular faces" ## Private constructor. + # @param mesh parent mesh object algorithm is assigned to + # @param geom geometry (shape/sub-shape) algorithm is assigned to; + # if it is @c 0 (default), the algorithm is assigned to the main shape def __init__(self, mesh, geom=0): Mesh_Algorithm.__init__(self) self.Create(mesh, geom, self.algoType) self.distribHyp = None #self.Hypothesis("LayerDistribution2D", UseExisting=0) self.nbLayers = None + pass ## Return 2D hypothesis holding the 1D one def Get2DHypothesis(self): @@ -954,25 +1096,37 @@ class StdMeshersDC_RadialQuadrangle1D2D(Mesh_Algorithm): hyp.SetFineness( fineness ) return hyp + pass # end of StdMeshersDC_RadialQuadrangle1D2D class -# Public class: Mesh_UseExistingElements -# -------------------------------------- -## Defines a Radial Quadrangle 1D2D algorithm -# It is created by calling Mesh.UseExisting1DElements(geom=0) +## Defines a Use Existing Elements 1D algorithm +# +# It is created by calling smesh.Mesh.UseExisting1DElements(geom=0) # # @ingroup l3_algos_basic class StdMeshersDC_UseExistingElements_1D(Mesh_Algorithm): - ## Name of method of class Mesh creating an instance of this class + ## name of the dynamic method in smesh.Mesh class + # @internal meshMethod = "UseExisting1DElements" - ## Name of algorithm type + ## type of algorithm used with helper function in smesh.Mesh class + # @internal algoType = "Import_1D" + ## flag pointing either this algorithm should be used by default in dynamic method + # of smesh.Mesh class + # @internal isDefault = True + ## doc string of the method + # @internal + docHelper = "Creates 1D algorithm for edges with reusing of existing mesh elements" + ## Private constructor. + # @param mesh parent mesh object algorithm is assigned to + # @param geom geometry (shape/sub-shape) algorithm is assigned to; + # if it is @c 0 (default), the algorithm is assigned to the main shape def __init__(self, mesh, geom=0): Mesh_Algorithm.__init__(self) self.Create(mesh, geom, self.algoType) - return + pass ## Defines "Source edges" hypothesis, specifying groups of edges to import # @param groups list of groups of edges @@ -991,24 +1145,37 @@ class StdMeshersDC_UseExistingElements_1D(Mesh_Algorithm): hyp.SetCopySourceMesh(toCopyMesh, toCopyGroups) return hyp -# Public class: Mesh_UseExistingElements -# -------------------------------------- -## Defines a Radial Quadrangle 1D2D algorithm -# It is created by calling Mesh.UseExisting2DElements(geom=0) + pass # end of StdMeshersDC_UseExistingElements_1D class + +## Defines a Use Existing Elements 1D-2D algorithm +# +# It is created by calling smesh.Mesh.UseExisting2DElements(geom=0) # # @ingroup l3_algos_basic class StdMeshersDC_UseExistingElements_1D2D(Mesh_Algorithm): - ## Name of method of class Mesh creating an instance of this class + ## name of the dynamic method in smesh.Mesh class + # @internal meshMethod = "UseExisting2DElements" - ## Name of algorithm type + ## type of algorithm used with helper function in smesh.Mesh class + # @internal algoType = "Import_1D2D" + ## flag pointing either this algorithm should be used by default in dynamic method + # of smesh.Mesh class + # @internal isDefault = True + ## doc string of the method + # @internal + docHelper = "Creates 1D-2D algorithm for edges/faces with reusing of existing mesh elements" + ## Private constructor. + # @param mesh parent mesh object algorithm is assigned to + # @param geom geometry (shape/sub-shape) algorithm is assigned to; + # if it is @c 0 (default), the algorithm is assigned to the main shape def __init__(self, mesh, geom=0): Mesh_Algorithm.__init__(self) self.Create(mesh, geom, self.algoType) - return + pass ## Defines "Source faces" hypothesis, specifying groups of faces to import # @param groups list of groups of faces @@ -1027,25 +1194,37 @@ class StdMeshersDC_UseExistingElements_1D2D(Mesh_Algorithm): hyp.SetCopySourceMesh(toCopyMesh, toCopyGroups) return hyp + pass # end of StdMeshersDC_UseExistingElements_1D2D class -# Public class: Mesh_Cartesian_3D -# -------------------------------------- ## Defines a Body Fitting 3D algorithm -# It is created by calling Mesh.BodyFitted(geom=0) +# +# It is created by calling smesh.Mesh.BodyFitted(geom=0) # # @ingroup l3_algos_basic class StdMeshersDC_Cartesian_3D(Mesh_Algorithm): - ## Name of method of class Mesh creating an instance of this class + ## name of the dynamic method in smesh.Mesh class + # @internal meshMethod = "BodyFitted" - ## Name of algorithm type + ## type of algorithm used with helper function in smesh.Mesh class + # @internal algoType = "Cartesian_3D" + ## flag pointing either this algorithm should be used by default in dynamic method + # of smesh.Mesh class + # @internal isDefault = True + ## doc string of the method + # @internal + docHelper = "Creates body fitting 3D algorithm for volumes" + ## Private constructor. + # @param mesh parent mesh object algorithm is assigned to + # @param geom geometry (shape/sub-shape) algorithm is assigned to; + # if it is @c 0 (default), the algorithm is assigned to the main shape def __init__(self, mesh, geom=0): self.Create(mesh, geom, self.algoType) self.hyp = None - return + pass ## Defines "Body Fitting parameters" hypothesis # @param xGridDef is definition of the grid along the X asix. @@ -1088,39 +1267,60 @@ class StdMeshersDC_Cartesian_3D(Mesh_Algorithm): self.hyp.SetSizeThreshold( sizeThreshold ) return self.hyp -# Public class: Mesh_UseExisting_1D -# --------------------------------- + pass # end of StdMeshersDC_Cartesian_3D class + ## Defines a stub 1D algorithm, which enables "manual" creation of nodes and # segments usable by 2D algoritms -# It is created by calling Mesh.UseExistingSegments(geom=0) +# +# It is created by calling smesh.Mesh.UseExistingSegments(geom=0) # # @ingroup l3_algos_basic - class StdMeshersDC_UseExisting_1D(Mesh_Algorithm): - ## Name of method of class Mesh creating an instance of this class + ## name of the dynamic method in smesh.Mesh class + # @internal meshMethod = "UseExistingSegments" - ## Name of algorithm type + ## type of algorithm used with helper function in smesh.Mesh class + # @internal algoType = "UseExisting_1D" + ## doc string of the method + # @internal + docHelper = "Creates 1D algorithm for edges with reusing of existing mesh elements" + ## Private constructor. + # @param mesh parent mesh object algorithm is assigned to + # @param geom geometry (shape/sub-shape) algorithm is assigned to; + # if it is @c 0 (default), the algorithm is assigned to the main shape def __init__(self, mesh, geom=0): self.Create(mesh, geom, self.algoType) + pass + pass # end of StdMeshersDC_UseExisting_1D class -# Public class: Mesh_UseExisting -# ------------------------------- ## Defines a stub 2D algorithm, which enables "manual" creation of nodes and # faces usable by 3D algoritms -# It is created by calling Mesh.UseExistingFaces(geom=0) +# +# It is created by calling smesh.Mesh.UseExistingFaces(geom=0) # # @ingroup l3_algos_basic - class StdMeshersDC_UseExisting_2D(Mesh_Algorithm): - ## Name of method of class Mesh creating an instance of this class + ## name of the dynamic method in smesh.Mesh class + # @internal meshMethod = "UseExistingFaces" - ## Name of algorithm type + ## type of algorithm used with helper function in smesh.Mesh class + # @internal algoType = "UseExisting_2D" + ## doc string of the method + # @internal + docHelper = "Creates 2D algorithm for faces with reusing of existing mesh elements" + ## Private constructor. + # @param mesh parent mesh object algorithm is assigned to + # @param geom geometry (shape/sub-shape) algorithm is assigned to; + # if it is @c 0 (default), the algorithm is assigned to the main shape def __init__(self, mesh, geom=0): self.Create(mesh, geom, self.algoType) + pass + + pass # end of StdMeshersDC_UseExisting_2D class diff --git a/src/SMESH_SWIG/smesh.py b/src/SMESH_SWIG/smesh.py index c13a57e8e..64279aa68 100644 --- a/src/SMESH_SWIG/smesh.py +++ b/src/SMESH_SWIG/smesh.py @@ -36,34 +36,48 @@ import geompy import smeshDC from smeshDC import * -# get instance of class smeshDC -smesh = salome.lcc.FindOrLoadComponent("FactoryServer", "SMESH") -smesh.init_smesh(salome.myStudy,geompy.geom) +# retrieve SMESH engine in try/except block +# to avoid problems in some cases, e.g. when generating documentation +try: + # get instance of class smeshDC + smesh = salome.lcc.FindOrLoadComponent( "FactoryServer", "SMESH" ) + smesh.init_smesh( salome.myStudy, geompy.geom ) +except: + smesh = None + pass -# load plugins +# load plugins and add dynamically generated methods to Mesh class, +# the same for for global variables declared by plug-ins from smeshDC import Mesh, algoCreator -for pluginName in os.environ["SMESH_MeshersList"].split(":"): +for pluginName in os.environ[ "SMESH_MeshersList" ].split( ":" ): + # + pluginName += "DC" + try: + exec( "from %s import *" % pluginName ) + except Exception, e: + print "Exception while loading %s: %s" % ( pluginName, e ) + continue + exec( "import %s" % pluginName ) + plugin = eval( pluginName ) - pluginName += "DC" - try: - exec("from %s import *" % pluginName ) - except Exception, e: - print "Exception while loading %s: %s" % ( pluginName, e ) - continue - exec("import %s" % pluginName ) - plugin = eval(pluginName) + # add methods creating algorithms to Mesh + for k in dir( plugin ): + if k[0] == '_': continue + algo = getattr( plugin, k ) + if type( algo ).__name__ == 'classobj' and hasattr( algo, "meshMethod" ): + if not hasattr( Mesh, algo.meshMethod ): + setattr( Mesh, algo.meshMethod, algoCreator() ) + pass + getattr( Mesh, algo.meshMethod ).add( algo ) + pass + pass + pass +del pluginName - # add methods creating algorithms to Mesh - for k in dir(plugin): - if k[0] == '_':continue - algo = getattr(plugin,k) - if type( algo ).__name__ == 'classobj' and hasattr( algo, "meshMethod"): - if not hasattr( Mesh, algo.meshMethod ): - setattr( Mesh, algo.meshMethod, algoCreator()) - getattr( Mesh, algo.meshMethod ).add( algo ) - -# Export the methods of smeshDC -for k in dir(smesh): - if k[0] == '_':continue - globals()[k]=getattr(smesh,k) -del k +# export the methods of smeshDC +if smesh: + for k in dir( smesh ): + if k[0] == '_': continue + globals()[k] = getattr( smesh, k ) + del k + pass diff --git a/src/SMESH_SWIG/smeshDC.py b/src/SMESH_SWIG/smeshDC.py index 9780503a1..e224ade4c 100644 --- a/src/SMESH_SWIG/smeshDC.py +++ b/src/SMESH_SWIG/smeshDC.py @@ -20,10 +20,8 @@ # Author : Francis KLOSS, OCC # Module : SMESH -""" - \namespace smesh - \brief Module smesh -""" +## @package smesh +# Python API for SALOME %Mesh module ## @defgroup l1_auxiliary Auxiliary methods and structures ## @defgroup l1_creating Creating meshes @@ -89,6 +87,7 @@ import geompyDC import SMESH # This is necessary for back compatibility from SMESH import * +from smesh_algorithm import Mesh_Algorithm import SALOME import SALOMEDS @@ -506,6 +505,14 @@ class smeshDC(SMESH._objref_SMESH_Gen): aMeshes.append(aMesh) return aMeshes, aStatus + ## Creates a Mesh object importing data from the given GMF file + # @return [ an instance of Mesh class, SMESH::ComputeError ] + # @ingroup l2_impexp + def CreateMeshesFromGMF( self, theFileName ): + aSmeshMesh, error = SMESH._objref_SMESH_Gen.CreateMeshesFromGMF(self,theFileName) + if error.comment: print "*** CreateMeshesFromGMF() errors:\n", error.comment + return Mesh(self, self.geompyD, aSmeshMesh), error + ## Concatenate the given meshes into one mesh. # @return an instance of Mesh class # @param meshes the meshes to combine into one mesh @@ -976,7 +983,10 @@ class Mesh: if studyID != geompyD.myStudyId: geompyD.init_geom( smeshpyD.GetCurrentStudy()) pass - geo_name = "%s_%s_for_meshing"%(self.geom.GetShapeType(), id(self.geom)%100) + if name: + geo_name = name + else: + geo_name = "%s_%s_for_meshing"%(self.geom.GetShapeType(), id(self.geom)%100) geompyD.addToStudy( self.geom, geo_name ) self.mesh = self.smeshpyD.CreateMesh(self.geom) @@ -1169,15 +1179,18 @@ class Mesh: except: shapeText = " on subshape #%s" % (err.subShapeID) errText = "" - stdErrors = ["OK", #COMPERR_OK - "Invalid input mesh", #COMPERR_BAD_INPUT_MESH - "std::exception", #COMPERR_STD_EXCEPTION - "OCC exception", #COMPERR_OCC_EXCEPTION - "SALOME exception", #COMPERR_SLM_EXCEPTION - "Unknown exception", #COMPERR_EXCEPTION + stdErrors = ["OK", #COMPERR_OK + "Invalid input mesh", #COMPERR_BAD_INPUT_MESH + "std::exception", #COMPERR_STD_EXCEPTION + "OCC exception", #COMPERR_OCC_EXCEPTION + "SALOME exception", #COMPERR_SLM_EXCEPTION + "Unknown exception", #COMPERR_EXCEPTION "Memory allocation problem", #COMPERR_MEMORY_PB - "Algorithm failed", #COMPERR_ALGO_FAILED - "Unexpected geometry"]#COMPERR_BAD_SHAPE + "Algorithm failed", #COMPERR_ALGO_FAILED + "Unexpected geometry", #COMPERR_BAD_SHAPE + "Warning", #COMPERR_WARNING + "Computation cancelled",#COMPERR_CANCELED + "No mesh on sub-shape"] #COMPERR_NO_MESH_ON_SHAPE if err.code > 0: if err.code < len(stdErrors): errText = stdErrors[err.code] else: @@ -1452,6 +1465,19 @@ class Mesh: meshPart = self.mesh self.mesh.ExportCGNS(meshPart, f, overwrite) + ## Exports the mesh in a file in GMF format + # @param f is the file name + # @param meshPart a part of mesh (group, sub-mesh) to export instead of the mesh + # @ingroup l2_impexp + def ExportGMF(self, f, meshPart=None): + if isinstance( meshPart, list ): + meshPart = self.GetIDSource( meshPart, SMESH.ALL ) + if isinstance( meshPart, Mesh ): + meshPart = meshPart.mesh + elif not meshPart: + meshPart = self.mesh + self.mesh.ExportGMF(meshPart, f) + ## Deprecated, used only for compatibility! Please, use ExportToMEDX() method instead. # Exports the mesh in a file in MED format and chooses the \a version of MED format ## allowing to overwrite the file if it exists or add the exported data to its contents @@ -1759,14 +1785,14 @@ class Mesh: # @return an instance of SMESH_MeshEditor # @ingroup l1_modifying def GetMeshEditor(self): - return self.mesh.GetMeshEditor() + return self.editor ## Wrap a list of IDs of elements or nodes into SMESH_IDSource which # can be passed as argument to a method accepting mesh, group or sub-mesh # @return an instance of SMESH_IDSource # @ingroup l1_auxiliary def GetIDSource(self, ids, elemType): - return self.GetMeshEditor().MakeIDSource(ids, elemType) + return self.editor.MakeIDSource(ids, elemType) ## Gets MED Mesh # @return an instance of SALOME_MED::MESH @@ -3974,6 +4000,18 @@ class Mesh: def DoubleNodeElemGroupsInRegion(self, theElems, theNodesNot, theShape): return self.editor.DoubleNodeElemGroupsInRegion(theElems, theNodesNot, theShape) + ## Identify the elements that will be affected by node duplication (actual duplication is not performed. + # This method is the first step of DoubleNodeElemGroupsInRegion. + # @param theElems - list of groups of elements (edges or faces) to be replicated + # @param theNodesNot - list of groups of nodes not to replicated + # @param theShape - shape to detect affected elements (element which geometric center + # located on or inside shape). + # The replicated nodes should be associated to affected elements. + # @return groups of affected elements + # @ingroup l2_modif_edit + def AffectedElemGroupsInRegion(self, theElems, theNodesNot, theShape): + return self.editor.AffectedElemGroupsInRegion(theElems, theNodesNot, theShape) + ## Double nodes on shared faces between groups of volumes and create flat elements on demand. # The list of groups must describe a partition of the mesh volumes. # The nodes of the internal faces at the boundaries of the groups are doubled. @@ -3994,6 +4032,11 @@ class Mesh: # @return TRUE if operation has been completed successfully, FALSE otherwise def CreateFlatElementsOnFacesGroups(self, theGroupsOfFaces ): return self.editor.CreateFlatElementsOnFacesGroups( theGroupsOfFaces ) + + ## identify all the elements around a geom shape, get the faces delimiting the hole + # + def CreateHoleSkin(self, radius, theShape, groupName, theNodesCoords): + return self.editor.CreateHoleSkin( radius, theShape, groupName, theNodesCoords ) def _valueFromFunctor(self, funcType, elemId): fn = self.smeshpyD.GetFunctor(funcType) @@ -4075,283 +4118,10 @@ class Mesh: def GetSkew(self, elemId): return self._valueFromFunctor(SMESH.FT_Skew, elemId) -## The mother class to define algorithm, it is not recommended to use it directly. + pass # end of Mesh class + +## Helper class for wrapping of SMESH.SMESH_Pattern CORBA class # -# For each meshing algorithm, a python class inheriting from class Mesh_Algorithm -# should be defined. This descendant class sould have two attributes defining the way -# it is created by class Mesh (see e.g. class StdMeshersDC_Segment in StdMeshersDC.py). -# - meshMethod attribute defines name of method of class Mesh by calling which the -# python class of algorithm is created. E.g. if in class MyPlugin_Algorithm -# meshMethod = "MyAlgorithm", then an instance of MyPlugin_Algorithm is created -# by the following code: my_algo = mesh.MyAlgorithm() -# - algoType defines name of algorithm type and is used mostly to discriminate -# algorithms that are created by the same method of class Mesh. E.g. if -# MyPlugin_Algorithm.algoType = "MyPLUGIN" then it's creation code can be: -# my_algo = mesh.MyAlgorithm(algo="MyPLUGIN") -# @ingroup l2_algorithms -class Mesh_Algorithm: - # @class Mesh_Algorithm - # @brief Class Mesh_Algorithm - - #def __init__(self,smesh): - # self.smesh=smesh - def __init__(self): - self.mesh = None - self.geom = None - self.subm = None - self.algo = None - - ## Finds a hypothesis in the study by its type name and parameters. - # Finds only the hypotheses created in smeshpyD engine. - # @return SMESH.SMESH_Hypothesis - def FindHypothesis (self, hypname, args, CompareMethod, smeshpyD): - study = smeshpyD.GetCurrentStudy() - #to do: find component by smeshpyD object, not by its data type - scomp = study.FindComponent(smeshpyD.ComponentDataType()) - if scomp is not None: - res,hypRoot = scomp.FindSubObject(SMESH.Tag_HypothesisRoot) - # Check if the root label of the hypotheses exists - if res and hypRoot is not None: - iter = study.NewChildIterator(hypRoot) - # Check all published hypotheses - while iter.More(): - hypo_so_i = iter.Value() - attr = hypo_so_i.FindAttribute("AttributeIOR")[1] - if attr is not None: - anIOR = attr.Value() - hypo_o_i = salome.orb.string_to_object(anIOR) - if hypo_o_i is not None: - # Check if this is a hypothesis - hypo_i = hypo_o_i._narrow(SMESH.SMESH_Hypothesis) - if hypo_i is not None: - # Check if the hypothesis belongs to current engine - if smeshpyD.GetObjectId(hypo_i) > 0: - # Check if this is the required hypothesis - if hypo_i.GetName() == hypname: - # Check arguments - if CompareMethod(hypo_i, args): - # found!!! - return hypo_i - pass - pass - pass - pass - pass - iter.Next() - pass - pass - pass - return None - - ## Finds the algorithm in the study by its type name. - # Finds only the algorithms, which have been created in smeshpyD engine. - # @return SMESH.SMESH_Algo - def FindAlgorithm (self, algoname, smeshpyD): - study = smeshpyD.GetCurrentStudy() - if not study: return None - #to do: find component by smeshpyD object, not by its data type - scomp = study.FindComponent(smeshpyD.ComponentDataType()) - if scomp is not None: - res,hypRoot = scomp.FindSubObject(SMESH.Tag_AlgorithmsRoot) - # Check if the root label of the algorithms exists - if res and hypRoot is not None: - iter = study.NewChildIterator(hypRoot) - # Check all published algorithms - while iter.More(): - algo_so_i = iter.Value() - attr = algo_so_i.FindAttribute("AttributeIOR")[1] - if attr is not None: - anIOR = attr.Value() - algo_o_i = salome.orb.string_to_object(anIOR) - if algo_o_i is not None: - # Check if this is an algorithm - algo_i = algo_o_i._narrow(SMESH.SMESH_Algo) - if algo_i is not None: - # Checks if the algorithm belongs to the current engine - if smeshpyD.GetObjectId(algo_i) > 0: - # Check if this is the required algorithm - if algo_i.GetName() == algoname: - # found!!! - return algo_i - pass - pass - pass - pass - iter.Next() - pass - pass - pass - return None - - ## If the algorithm is global, returns 0; \n - # else returns the submesh associated to this algorithm. - def GetSubMesh(self): - return self.subm - - ## Returns the wrapped mesher. - def GetAlgorithm(self): - return self.algo - - ## Gets the list of hypothesis that can be used with this algorithm - def GetCompatibleHypothesis(self): - mylist = [] - if self.algo: - mylist = self.algo.GetCompatibleHypothesis() - return mylist - - ## Gets the name of the algorithm - def GetName(self): - GetName(self.algo) - - ## Sets the name to the algorithm - def SetName(self, name): - self.mesh.smeshpyD.SetName(self.algo, name) - - ## Gets the id of the algorithm - def GetId(self): - return self.algo.GetId() - - ## Private method. - def Create(self, mesh, geom, hypo, so="libStdMeshersEngine.so"): - if geom is None: - raise RuntimeError, "Attemp to create " + hypo + " algoritm on None shape" - algo = self.FindAlgorithm(hypo, mesh.smeshpyD) - if algo is None: - algo = mesh.smeshpyD.CreateHypothesis(hypo, so) - pass - self.Assign(algo, mesh, geom) - return self.algo - - ## Private method - def Assign(self, algo, mesh, geom): - if geom is None: - raise RuntimeError, "Attemp to create " + algo + " algoritm on None shape" - self.mesh = mesh - name = "" - if not geom: - self.geom = mesh.geom - else: - self.geom = geom - AssureGeomPublished( mesh, geom ) - try: - name = GetName(geom) - pass - except: - pass - self.subm = mesh.mesh.GetSubMesh(geom, algo.GetName()) - self.algo = algo - status = mesh.mesh.AddHypothesis(self.geom, self.algo) - TreatHypoStatus( status, algo.GetName(), name, True ) - return - - def CompareHyp (self, hyp, args): - print "CompareHyp is not implemented for ", self.__class__.__name__, ":", hyp.GetName() - return False - - def CompareEqualHyp (self, hyp, args): - return True - - ## Private method - def Hypothesis (self, hyp, args=[], so="libStdMeshersEngine.so", - UseExisting=0, CompareMethod=""): - hypo = None - if UseExisting: - if CompareMethod == "": CompareMethod = self.CompareHyp - hypo = self.FindHypothesis(hyp, args, CompareMethod, self.mesh.smeshpyD) - pass - if hypo is None: - hypo = self.mesh.smeshpyD.CreateHypothesis(hyp, so) - a = "" - s = "=" - for arg in args: - argStr = str(arg) - if isinstance( arg, geompyDC.GEOM._objref_GEOM_Object ): - argStr = arg.GetStudyEntry() - if not argStr: argStr = "GEOM_Obj_%s", arg.GetEntry() - if len( argStr ) > 10: - argStr = argStr[:7]+"..." - if argStr[0] == '[': argStr += ']' - a = a + s + argStr - s = "," - pass - if len(a) > 50: - a = a[:47]+"..." - self.mesh.smeshpyD.SetName(hypo, hyp + a) - pass - geomName="" - if self.geom: - geomName = GetName(self.geom) - status = self.mesh.mesh.AddHypothesis(self.geom, hypo) - TreatHypoStatus( status, GetName(hypo), geomName, 0 ) - return hypo - - ## Returns entry of the shape to mesh in the study - def MainShapeEntry(self): - if not self.mesh or not self.mesh.GetMesh(): return "" - if not self.mesh.GetMesh().HasShapeToMesh(): return "" - shape = self.mesh.GetShape() - return shape.GetStudyEntry() - - ## Defines "ViscousLayers" hypothesis to give parameters of layers of prisms to build - # near mesh boundary. This hypothesis can be used by several 3D algorithms: - # NETGEN 3D, GHS3D, Hexahedron(i,j,k) - # @param thickness total thickness of layers of prisms - # @param numberOfLayers number of layers of prisms - # @param stretchFactor factor (>1.0) of growth of layer thickness towards inside of mesh - # @param ignoreFaces list of geometrical faces (or their ids) not to generate layers on - # @ingroup l3_hypos_additi - def ViscousLayers(self, thickness, numberOfLayers, stretchFactor, ignoreFaces=[]): - if not isinstance(self.algo, SMESH._objref_SMESH_3D_Algo): - raise TypeError, "ViscousLayers are supported by 3D algorithms only" - if not "ViscousLayers" in self.GetCompatibleHypothesis(): - raise TypeError, "ViscousLayers are not supported by %s"%self.algo.GetName() - if ignoreFaces and isinstance( ignoreFaces[0], geompyDC.GEOM._objref_GEOM_Object ): - ignoreFaces = [ self.mesh.geompyD.GetSubShapeID(self.mesh.geom, f) for f in ignoreFaces ] - hyp = self.Hypothesis("ViscousLayers", - [thickness, numberOfLayers, stretchFactor, ignoreFaces]) - hyp.SetTotalThickness(thickness) - hyp.SetNumberLayers(numberOfLayers) - hyp.SetStretchFactor(stretchFactor) - hyp.SetIgnoreFaces(ignoreFaces) - return hyp - - ## Transform a list of ether edges or tuples (edge, 1st_vertex_of_edge) - # into a list acceptable to SetReversedEdges() of some 1D hypotheses - # @ingroup l3_hypos_1dhyps - def ReversedEdgeIndices(self, reverseList): - resList = [] - geompy = self.mesh.geompyD - for i in reverseList: - if isinstance( i, int ): - s = geompy.SubShapes(self.mesh.geom, [i])[0] - if s.GetShapeType() != geompyDC.GEOM.EDGE: - raise TypeError, "Not EDGE index given" - resList.append( i ) - elif isinstance( i, geompyDC.GEOM._objref_GEOM_Object ): - if i.GetShapeType() != geompyDC.GEOM.EDGE: - raise TypeError, "Not an EDGE given" - resList.append( geompy.GetSubShapeID(self.mesh.geom, i )) - elif len( i ) > 1: - e = i[0] - v = i[1] - if not isinstance( e, geompyDC.GEOM._objref_GEOM_Object ) or \ - not isinstance( v, geompyDC.GEOM._objref_GEOM_Object ): - raise TypeError, "A list item must be a tuple (edge, 1st_vertex_of_edge)" - if v.GetShapeType() == geompyDC.GEOM.EDGE and \ - e.GetShapeType() == geompyDC.GEOM.VERTEX: - v,e = e,v - if e.GetShapeType() != geompyDC.GEOM.EDGE or \ - v.GetShapeType() != geompyDC.GEOM.VERTEX: - raise TypeError, "A list item must be a tuple (edge, 1st_vertex_of_edge)" - vFirst = FirstVertexOnCurve( e ) - tol = geompy.Tolerance( vFirst )[-1] - if geompy.MinDistance( v, vFirst ) > 1.5*tol: - resList.append( geompy.GetSubShapeID(self.mesh.geom, e )) - else: - raise TypeError, "Item must be either an edge or tuple (edge, 1st_vertex_of_edge)" - return resList - - class Pattern(SMESH._objref_SMESH_Pattern): def ApplyToMeshFaces(self, theMesh, theFacesIDs, theNodeIndexOnKeyPoint1, theReverse): @@ -4366,13 +4136,9 @@ class Pattern(SMESH._objref_SMESH_Pattern): theMesh.SetParameters(Parameters) return SMESH._objref_SMESH_Pattern.ApplyToHexahedrons( self, theMesh, theVolumesIDs, theNode000Index, theNode001Index ) -#Registering the new proxy for Pattern +# Registering the new proxy for Pattern omniORB.registerObjref(SMESH._objref_SMESH_Pattern._NP_RepositoryId, Pattern) - - - - ## Private class used to bind methods creating algorithms to the class Mesh # class algoCreator: @@ -4416,6 +4182,7 @@ class algoCreator: return None # Private class used to substitute and store variable parameters of hypotheses. +# class hypMethodWrapper: def __init__(self, hyp, method): self.hyp = hyp diff --git a/src/SMESH_SWIG/smesh_algorithm.py b/src/SMESH_SWIG/smesh_algorithm.py new file mode 100644 index 000000000..dfeaba4fb --- /dev/null +++ b/src/SMESH_SWIG/smesh_algorithm.py @@ -0,0 +1,322 @@ +# Copyright (C) 2007-2012 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 +# + +## @package smesh_algorithm +# Python API for base Mesh_Algorithm class. +# This package is a part of SALOME %Mesh module Python API + +import salome +import geompyDC +import SMESH + +## The base class to define meshing algorithms +# +# @note This class should not be used directly, it is supposed to be sub-classed +# for implementing Python API for specific meshing algorithms +# +# For each meshing algorithm, a python class inheriting from class %Mesh_Algorithm +# should be defined. This descendant class should have two attributes defining the way +# it is created by class Mesh (see e.g. class @ref StdMeshersDC.StdMeshersDC_Segment "StdMeshersDC_Segment" +# in StdMeshersDC package): +# - @c meshMethod attribute defines name of method of class smesh.Mesh by calling which the +# python class of algorithm is created; this method is dynamically added to the smesh.Mesh class +# in runtime. For example, if in @c class MyPlugin_Algorithm this attribute is defined as +# @code +# meshMethod = "MyAlgorithm" +# @endcode +# then an instance of @c MyPlugin_Algorithm can be created by the direct invokation of the function +# of smesh.Mesh class: +# @code +# my_algo = mesh.MyAlgorithm() +# @endcode +# - @c algoType defines type of algorithm and is used mostly to discriminate +# algorithms that are created by the same method of class smesh.Mesh. For example, if this attribute +# is specified in @c MyPlugin_Algorithm class as +# @code +# algoType = "MyPLUGIN" +# @endcode +# then it's creation code can be: +# @code +# my_algo = mesh.MyAlgorithm(algo="MyPLUGIN") +# @endcode +# @ingroup l2_algorithms +class Mesh_Algorithm: + + ## Private constuctor + def __init__(self): + self.mesh = None + self.geom = None + self.subm = None + self.algo = None + pass + + ## Finds a hypothesis in the study by its type name and parameters. + # Finds only the hypotheses created in smeshpyD engine. + # @return SMESH.SMESH_Hypothesis + def FindHypothesis (self, hypname, args, CompareMethod, smeshpyD): + study = smeshpyD.GetCurrentStudy() + #to do: find component by smeshpyD object, not by its data type + scomp = study.FindComponent(smeshpyD.ComponentDataType()) + if scomp is not None: + res,hypRoot = scomp.FindSubObject(SMESH.Tag_HypothesisRoot) + # Check if the root label of the hypotheses exists + if res and hypRoot is not None: + iter = study.NewChildIterator(hypRoot) + # Check all published hypotheses + while iter.More(): + hypo_so_i = iter.Value() + attr = hypo_so_i.FindAttribute("AttributeIOR")[1] + if attr is not None: + anIOR = attr.Value() + hypo_o_i = salome.orb.string_to_object(anIOR) + if hypo_o_i is not None: + # Check if this is a hypothesis + hypo_i = hypo_o_i._narrow(SMESH.SMESH_Hypothesis) + if hypo_i is not None: + # Check if the hypothesis belongs to current engine + if smeshpyD.GetObjectId(hypo_i) > 0: + # Check if this is the required hypothesis + if hypo_i.GetName() == hypname: + # Check arguments + if CompareMethod(hypo_i, args): + # found!!! + return hypo_i + pass + pass + pass + pass + pass + iter.Next() + pass + pass + pass + return None + + ## Finds the algorithm in the study by its type name. + # Finds only the algorithms, which have been created in smeshpyD engine. + # @return SMESH.SMESH_Algo + def FindAlgorithm (self, algoname, smeshpyD): + study = smeshpyD.GetCurrentStudy() + if not study: return None + #to do: find component by smeshpyD object, not by its data type + scomp = study.FindComponent(smeshpyD.ComponentDataType()) + if scomp is not None: + res,hypRoot = scomp.FindSubObject(SMESH.Tag_AlgorithmsRoot) + # Check if the root label of the algorithms exists + if res and hypRoot is not None: + iter = study.NewChildIterator(hypRoot) + # Check all published algorithms + while iter.More(): + algo_so_i = iter.Value() + attr = algo_so_i.FindAttribute("AttributeIOR")[1] + if attr is not None: + anIOR = attr.Value() + algo_o_i = salome.orb.string_to_object(anIOR) + if algo_o_i is not None: + # Check if this is an algorithm + algo_i = algo_o_i._narrow(SMESH.SMESH_Algo) + if algo_i is not None: + # Checks if the algorithm belongs to the current engine + if smeshpyD.GetObjectId(algo_i) > 0: + # Check if this is the required algorithm + if algo_i.GetName() == algoname: + # found!!! + return algo_i + pass + pass + pass + pass + iter.Next() + pass + pass + pass + return None + + ## If the algorithm is global, returns 0; \n + # else returns the submesh associated to this algorithm. + def GetSubMesh(self): + return self.subm + + ## Returns the wrapped mesher. + def GetAlgorithm(self): + return self.algo + + ## Gets the list of hypothesis that can be used with this algorithm + def GetCompatibleHypothesis(self): + mylist = [] + if self.algo: + mylist = self.algo.GetCompatibleHypothesis() + return mylist + + ## Gets the name of the algorithm + def GetName(self): + from smesh import GetName + return GetName(self.algo) + + ## Sets the name to the algorithm + def SetName(self, name): + self.mesh.smeshpyD.SetName(self.algo, name) + + ## Gets the id of the algorithm + def GetId(self): + return self.algo.GetId() + + ## Private method. + def Create(self, mesh, geom, hypo, so="libStdMeshersEngine.so"): + if geom is None: + raise RuntimeError, "Attemp to create " + hypo + " algoritm on None shape" + algo = self.FindAlgorithm(hypo, mesh.smeshpyD) + if algo is None: + algo = mesh.smeshpyD.CreateHypothesis(hypo, so) + pass + self.Assign(algo, mesh, geom) + return self.algo + + ## Private method + def Assign(self, algo, mesh, geom): + from smesh import AssureGeomPublished, TreatHypoStatus, GetName + if geom is None: + raise RuntimeError, "Attemp to create " + algo + " algoritm on None shape" + self.mesh = mesh + name = "" + if not geom: + self.geom = mesh.geom + else: + self.geom = geom + AssureGeomPublished( mesh, geom ) + try: + name = GetName(geom) + pass + except: + pass + self.subm = mesh.mesh.GetSubMesh(geom, algo.GetName()) + self.algo = algo + status = mesh.mesh.AddHypothesis(self.geom, self.algo) + TreatHypoStatus( status, algo.GetName(), name, True ) + return + + def CompareHyp (self, hyp, args): + print "CompareHyp is not implemented for ", self.__class__.__name__, ":", hyp.GetName() + return False + + def CompareEqualHyp (self, hyp, args): + return True + + ## Private method + def Hypothesis (self, hyp, args=[], so="libStdMeshersEngine.so", + UseExisting=0, CompareMethod=""): + from smesh import TreatHypoStatus, GetName + hypo = None + if UseExisting: + if CompareMethod == "": CompareMethod = self.CompareHyp + hypo = self.FindHypothesis(hyp, args, CompareMethod, self.mesh.smeshpyD) + pass + if hypo is None: + hypo = self.mesh.smeshpyD.CreateHypothesis(hyp, so) + a = "" + s = "=" + for arg in args: + argStr = str(arg) + if isinstance( arg, geompyDC.GEOM._objref_GEOM_Object ): + argStr = arg.GetStudyEntry() + if not argStr: argStr = "GEOM_Obj_%s", arg.GetEntry() + if len( argStr ) > 10: + argStr = argStr[:7]+"..." + if argStr[0] == '[': argStr += ']' + a = a + s + argStr + s = "," + pass + if len(a) > 50: + a = a[:47]+"..." + self.mesh.smeshpyD.SetName(hypo, hyp + a) + pass + geomName="" + if self.geom: + geomName = GetName(self.geom) + status = self.mesh.mesh.AddHypothesis(self.geom, hypo) + TreatHypoStatus( status, GetName(hypo), geomName, 0 ) + return hypo + + ## Returns entry of the shape to mesh in the study + def MainShapeEntry(self): + if not self.mesh or not self.mesh.GetMesh(): return "" + if not self.mesh.GetMesh().HasShapeToMesh(): return "" + shape = self.mesh.GetShape() + return shape.GetStudyEntry() + + ## Defines "ViscousLayers" hypothesis to give parameters of layers of prisms to build + # near mesh boundary. This hypothesis can be used by several 3D algorithms: + # NETGEN 3D, GHS3D, Hexahedron(i,j,k) + # @param thickness total thickness of layers of prisms + # @param numberOfLayers number of layers of prisms + # @param stretchFactor factor (>1.0) of growth of layer thickness towards inside of mesh + # @param ignoreFaces list of geometrical faces (or their ids) not to generate layers on + # @ingroup l3_hypos_additi + def ViscousLayers(self, thickness, numberOfLayers, stretchFactor, ignoreFaces=[]): + if not isinstance(self.algo, SMESH._objref_SMESH_3D_Algo): + raise TypeError, "ViscousLayers are supported by 3D algorithms only" + if not "ViscousLayers" in self.GetCompatibleHypothesis(): + raise TypeError, "ViscousLayers are not supported by %s"%self.algo.GetName() + if ignoreFaces and isinstance( ignoreFaces[0], geompyDC.GEOM._objref_GEOM_Object ): + ignoreFaces = [ self.mesh.geompyD.GetSubShapeID(self.mesh.geom, f) for f in ignoreFaces ] + hyp = self.Hypothesis("ViscousLayers", + [thickness, numberOfLayers, stretchFactor, ignoreFaces]) + hyp.SetTotalThickness(thickness) + hyp.SetNumberLayers(numberOfLayers) + hyp.SetStretchFactor(stretchFactor) + hyp.SetIgnoreFaces(ignoreFaces) + return hyp + + ## Transform a list of ether edges or tuples (edge, 1st_vertex_of_edge) + # into a list acceptable to SetReversedEdges() of some 1D hypotheses + # @ingroup l3_hypos_1dhyps + def ReversedEdgeIndices(self, reverseList): + from smesh import FirstVertexOnCurve + resList = [] + geompy = self.mesh.geompyD + for i in reverseList: + if isinstance( i, int ): + s = geompy.SubShapes(self.mesh.geom, [i])[0] + if s.GetShapeType() != geompyDC.GEOM.EDGE: + raise TypeError, "Not EDGE index given" + resList.append( i ) + elif isinstance( i, geompyDC.GEOM._objref_GEOM_Object ): + if i.GetShapeType() != geompyDC.GEOM.EDGE: + raise TypeError, "Not an EDGE given" + resList.append( geompy.GetSubShapeID(self.mesh.geom, i )) + elif len( i ) > 1: + e = i[0] + v = i[1] + if not isinstance( e, geompyDC.GEOM._objref_GEOM_Object ) or \ + not isinstance( v, geompyDC.GEOM._objref_GEOM_Object ): + raise TypeError, "A list item must be a tuple (edge, 1st_vertex_of_edge)" + if v.GetShapeType() == geompyDC.GEOM.EDGE and \ + e.GetShapeType() == geompyDC.GEOM.VERTEX: + v,e = e,v + if e.GetShapeType() != geompyDC.GEOM.EDGE or \ + v.GetShapeType() != geompyDC.GEOM.VERTEX: + raise TypeError, "A list item must be a tuple (edge, 1st_vertex_of_edge)" + vFirst = FirstVertexOnCurve( e ) + tol = geompy.Tolerance( vFirst )[-1] + if geompy.MinDistance( v, vFirst ) > 1.5*tol: + resList.append( geompy.GetSubShapeID(self.mesh.geom, e )) + else: + raise TypeError, "Item must be either an edge or tuple (edge, 1st_vertex_of_edge)" + return resList + diff --git a/src/SMESH_SWIG_WITHIHM/libSMESH_Swig.cxx b/src/SMESH_SWIG_WITHIHM/libSMESH_Swig.cxx index eca22e91e..679a8d853 100644 --- a/src/SMESH_SWIG_WITHIHM/libSMESH_Swig.cxx +++ b/src/SMESH_SWIG_WITHIHM/libSMESH_Swig.cxx @@ -37,6 +37,9 @@ // SALOME GUI includes #include +#include +#include +#include #include #include #include @@ -575,6 +578,44 @@ void SMESH_Swig::CreateAndDisplayActor( const char* Mesh_Entry ) ProcessVoidEvent(new TEvent(Mesh_Entry)); } +void SMESH_Swig::EraseActor( const char* Mesh_Entry, const bool allViewers ) +{ + class TEvent: public SALOME_Event + { + private: + const char* _entry; + bool _allViewers; + public: + TEvent(const char* Mesh_Entry, const bool allViewers ) { + _entry = Mesh_Entry; + _allViewers = allViewers; + } + virtual void Execute() { + SUIT_Session* aSession = SUIT_Session::session(); + SUIT_Application* anApplication = aSession->activeApplication(); + SalomeApp_Application* anApp = dynamic_cast(anApplication); + SMESHGUI_Displayer* aDisp = new SMESHGUI_Displayer(anApp); + ViewManagerList aManagers; + if ( !_allViewers ) { + aManagers << anApp->activeViewManager(); + } + else { + aManagers = anApp->viewManagers(); + } + foreach( SUIT_ViewManager* aMgr, aManagers ) { + if ( aMgr && aMgr->getType() == VTKViewer_Viewer::Type() ) { + SALOME_View* aSalomeView = dynamic_cast(aMgr->getViewModel()); + if (aSalomeView) { + aDisp->Erase(_entry,true, true, aSalomeView); + } + } + } + } + }; + + ProcessVoidEvent(new TEvent(Mesh_Entry, allViewers)); +} + void SMESH_Swig::SetName(const char* theEntry, const char* theName) { diff --git a/src/SMESH_SWIG_WITHIHM/libSMESH_Swig.h b/src/SMESH_SWIG_WITHIHM/libSMESH_Swig.h index 4a7b8e719..504eba845 100644 --- a/src/SMESH_SWIG_WITHIHM/libSMESH_Swig.h +++ b/src/SMESH_SWIG_WITHIHM/libSMESH_Swig.h @@ -65,6 +65,8 @@ public: void SetName( const char*, const char* ); + void EraseActor( const char*, const bool allViewers = false ); + /*! * \brief Set mesh icon according to compute status * \param Mesh_Entry - entry of a mesh diff --git a/src/SMESH_SWIG_WITHIHM/libSMESH_Swig.i b/src/SMESH_SWIG_WITHIHM/libSMESH_Swig.i index 52d2bb87f..db8ef31aa 100644 --- a/src/SMESH_SWIG_WITHIHM/libSMESH_Swig.i +++ b/src/SMESH_SWIG_WITHIHM/libSMESH_Swig.i @@ -75,4 +75,5 @@ class SMESH_Swig void SetMeshIcon(const char* Mesh_Entry, const bool isComputed, const bool isEmpty); void CreateAndDisplayActor( const char* Mesh_Entry ); + void EraseActor( const char* Mesh_Entry, const bool allViewers = false ); }; diff --git a/src/StdMeshers/StdMeshers_Cartesian_3D.cxx b/src/StdMeshers/StdMeshers_Cartesian_3D.cxx index c1e57198f..6b0c68b93 100644 --- a/src/StdMeshers/StdMeshers_Cartesian_3D.cxx +++ b/src/StdMeshers/StdMeshers_Cartesian_3D.cxx @@ -35,6 +35,7 @@ #include "utilities.h" #include "Utils_ExceptHandlers.hxx" +#include #include #include @@ -85,7 +86,10 @@ using namespace std; //#define _MY_DEBUG_ -#define ELLIPSOLID_WORKAROUND // remove it as soon as http://tracker.dev.opencascade.org/view.php?id=22809 is solved +#if OCC_VERSION_LARGE <= 0x06050300 +// workaround it required only for OCCT6.5.3 and older (see OCC22809) +#define ELLIPSOLID_WORKAROUND +#endif #ifdef ELLIPSOLID_WORKAROUND #include diff --git a/src/StdMeshers/StdMeshers_Cartesian_3D.hxx b/src/StdMeshers/StdMeshers_Cartesian_3D.hxx index 4aefa321f..df2228e3d 100644 --- a/src/StdMeshers/StdMeshers_Cartesian_3D.hxx +++ b/src/StdMeshers/StdMeshers_Cartesian_3D.hxx @@ -28,7 +28,7 @@ #include "SMESH_StdMeshers.hxx" -#include "SMESH_3D_Algo.hxx" +#include "SMESH_Algo.hxx" /*! * \brief A 3D algorithm generating 3D structured Cartesian mesh in the diff --git a/src/StdMeshers/StdMeshers_CompositeHexa_3D.hxx b/src/StdMeshers/StdMeshers_CompositeHexa_3D.hxx index d5b9f8b4e..a39791e96 100644 --- a/src/StdMeshers/StdMeshers_CompositeHexa_3D.hxx +++ b/src/StdMeshers/StdMeshers_CompositeHexa_3D.hxx @@ -25,7 +25,7 @@ #define _SMESH_CompositeSegment_1D_HXX_ #include "SMESH_StdMeshers.hxx" -#include "SMESH_3D_Algo.hxx" +#include "SMESH_Algo.hxx" class SMESH_Mesh; class StdMeshers_FaceSide; diff --git a/src/StdMeshers/StdMeshers_HexaFromSkin_3D.hxx b/src/StdMeshers/StdMeshers_HexaFromSkin_3D.hxx index 0912a4d03..16e70fc20 100644 --- a/src/StdMeshers/StdMeshers_HexaFromSkin_3D.hxx +++ b/src/StdMeshers/StdMeshers_HexaFromSkin_3D.hxx @@ -25,7 +25,7 @@ #define __StdMeshers_HexaFromSkin_3D_HXX__ #include "SMESH_StdMeshers.hxx" -#include "SMESH_3D_Algo.hxx" +#include "SMESH_Algo.hxx" /*! * \brief Alorithm generating hexahedral mesh from 2D skin of block diff --git a/src/StdMeshers/StdMeshers_Hexa_3D.hxx b/src/StdMeshers/StdMeshers_Hexa_3D.hxx index 48f1eebbe..50b476c7d 100644 --- a/src/StdMeshers/StdMeshers_Hexa_3D.hxx +++ b/src/StdMeshers/StdMeshers_Hexa_3D.hxx @@ -31,7 +31,7 @@ #include "SMESH_StdMeshers.hxx" -#include "SMESH_3D_Algo.hxx" +#include "SMESH_Algo.hxx" class StdMeshers_ViscousLayers; diff --git a/src/StdMeshers/StdMeshers_Import_1D.cxx b/src/StdMeshers/StdMeshers_Import_1D.cxx index b8a5076b8..a85647120 100644 --- a/src/StdMeshers/StdMeshers_Import_1D.cxx +++ b/src/StdMeshers/StdMeshers_Import_1D.cxx @@ -134,7 +134,7 @@ namespace // INTERNAL STUFF _ListenerData(const StdMeshers_ImportSource1D* h, _ListenerDataType type=SRC_HYP): SMESH_subMeshEventListenerData(/*isDeletable=*/true), _srcHyp(h) { - myType = type; + myType = type; } }; //================================================================================ @@ -613,7 +613,7 @@ namespace // INTERNAL STUFF //============================================================================= /*! - * Import elements from the other mesh + * Import elements from the other mesh */ //============================================================================= @@ -637,8 +637,8 @@ bool StdMeshers_Import_1D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape & th subShapeIDs.insert( shapeID ); // get nodes on vertices - list < SMESH_TNodeXYZ > vertexNodes; - list < SMESH_TNodeXYZ >::iterator vNIt; + list < SMESH_TNodeXYZ > vertexNodes; + list < SMESH_TNodeXYZ >::iterator vNIt; TopExp_Explorer vExp( theShape, TopAbs_VERTEX ); for ( ; vExp.More(); vExp.Next() ) { @@ -670,7 +670,7 @@ bool StdMeshers_Import_1D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape & th SMDS_ElemIteratorPtr srcElems = srcGroup->GetElements(); vector newNodes; SMDS_MeshNode *tmpNode = helper.AddNode(0,0,0); - double u; + double u = 0; while ( srcElems->more() ) // loop on group contents { const SMDS_MeshElement* edge = srcElems->next(); @@ -678,6 +678,10 @@ bool StdMeshers_Import_1D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape & th newNodes.resize( edge->NbNodes() ); newNodes.back() = 0; SMDS_MeshElement::iterator node = edge->begin_nodes(); + SMESH_TNodeXYZ a(edge->GetNode(0)); + // --- define a tolerance relative to the length of an edge + double mytol = a.Distance(edge->GetNode(edge->NbNodes()-1))/25; + //MESSAGE("mytol = " << mytol); for ( unsigned i = 0; i < newNodes.size(); ++i, ++node ) { TNodeNodeMap::iterator n2nIt = n2n->insert( make_pair( *node, (SMDS_MeshNode*)0 )).first; @@ -701,7 +705,7 @@ bool StdMeshers_Import_1D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape & th { // find out if node lies on theShape tmpNode->setXYZ( (*node)->X(), (*node)->Y(), (*node)->Z()); - if ( helper.CheckNodeU( geomEdge, tmpNode, u, 10 * edgeTol, /*force=*/true )) + if ( helper.CheckNodeU( geomEdge, tmpNode, u, mytol, /*force=*/true )) { SMDS_MeshNode* newNode = tgtMesh->AddNode( (*node)->X(), (*node)->Y(), (*node)->Z()); n2nIt->second = newNode; @@ -906,7 +910,7 @@ void StdMeshers_Import_1D::importMesh(const SMESH_Mesh* srcMesh, */ //============================================================================= -void StdMeshers_Import_1D::setEventListener(SMESH_subMesh* subMesh, +void StdMeshers_Import_1D::setEventListener(SMESH_subMesh* subMesh, StdMeshers_ImportSource1D* sourceHyp) { if ( sourceHyp ) diff --git a/src/StdMeshers/StdMeshers_Import_1D.hxx b/src/StdMeshers/StdMeshers_Import_1D.hxx index b71b90564..03b8cbcf0 100644 --- a/src/StdMeshers/StdMeshers_Import_1D.hxx +++ b/src/StdMeshers/StdMeshers_Import_1D.hxx @@ -28,7 +28,7 @@ #include "SMESH_StdMeshers.hxx" -#include "SMESH_1D_Algo.hxx" +#include "SMESH_Algo.hxx" #include "SMDS_MeshElement.hxx" class StdMeshers_ImportSource1D; diff --git a/src/StdMeshers/StdMeshers_Import_1D2D.hxx b/src/StdMeshers/StdMeshers_Import_1D2D.hxx index fc3a89d85..22dbed743 100644 --- a/src/StdMeshers/StdMeshers_Import_1D2D.hxx +++ b/src/StdMeshers/StdMeshers_Import_1D2D.hxx @@ -28,7 +28,7 @@ #include "SMESH_StdMeshers.hxx" -#include "SMESH_2D_Algo.hxx" +#include "SMESH_Algo.hxx" #include "SMDS_MeshElement.hxx" class StdMeshers_ImportSource1D; diff --git a/src/StdMeshers/StdMeshers_MEFISTO_2D.cxx b/src/StdMeshers/StdMeshers_MEFISTO_2D.cxx index fe637c65a..f7a91a6b1 100644 --- a/src/StdMeshers/StdMeshers_MEFISTO_2D.cxx +++ b/src/StdMeshers/StdMeshers_MEFISTO_2D.cxx @@ -51,8 +51,8 @@ #include #include -#include #include +#include #include #include #include @@ -64,6 +64,7 @@ #include #include #include +#include #include #include diff --git a/src/StdMeshers/StdMeshers_MEFISTO_2D.hxx b/src/StdMeshers/StdMeshers_MEFISTO_2D.hxx index 0dce86135..219df4089 100644 --- a/src/StdMeshers/StdMeshers_MEFISTO_2D.hxx +++ b/src/StdMeshers/StdMeshers_MEFISTO_2D.hxx @@ -25,14 +25,13 @@ // Moved here from SMESH_MEFISTO_2D.hxx // Author : Paul RASCLE, EDF // Module : SMESH -// $Header$ // #ifndef _StdMeshers_MEFISTO_2D_HXX_ #define _StdMeshers_MEFISTO_2D_HXX_ #include "SMESH_StdMeshers.hxx" -#include "SMESH_2D_Algo.hxx" +#include "SMESH_Algo.hxx" class TopoDS_Face; class StdMeshers_MaxElementArea; diff --git a/src/StdMeshers/StdMeshers_Penta_3D.hxx b/src/StdMeshers/StdMeshers_Penta_3D.hxx index 5d23368cc..680389051 100644 --- a/src/StdMeshers/StdMeshers_Penta_3D.hxx +++ b/src/StdMeshers/StdMeshers_Penta_3D.hxx @@ -36,17 +36,17 @@ // class StdMeshers_SMESHBlock // //////////////////////////////////////////////////////////////////////// +#include +#include +#include +#include #include #include -#include -#include -#include -#include +#include "SMESH_Algo.hxx" #include "SMESH_Block.hxx" #include "SMESH_ComputeError.hxx" #include "SMESH_MesherHelper.hxx" -#include "SMESH_3D_Algo.hxx" typedef std::map< double, std::vector > StdMeshers_IJNodeMap; diff --git a/src/StdMeshers/StdMeshers_Prism_3D.hxx b/src/StdMeshers/StdMeshers_Prism_3D.hxx index 8c1e6fa78..42d56fe16 100644 --- a/src/StdMeshers/StdMeshers_Prism_3D.hxx +++ b/src/StdMeshers/StdMeshers_Prism_3D.hxx @@ -29,25 +29,25 @@ #include "SMESH_StdMeshers.hxx" -#include "SMESH_3D_Algo.hxx" -#include "SMDS_TypeOfPosition.hxx" #include "SMDS_MeshNode.hxx" +#include "SMDS_TypeOfPosition.hxx" +#include "SMESHDS_Mesh.hxx" +#include "SMESH_Algo.hxx" #include "SMESH_Block.hxx" +#include "SMESH_Comment.hxx" #include "SMESH_Mesh.hxx" -#include "SMESHDS_Mesh.hxx" -#include "SMESH_subMesh.hxx" #include "SMESH_MesherHelper.hxx" -#include "SMESH_Comment.hxx" +#include "SMESH_subMesh.hxx" #include +#include #include #include -#include #include #include -#include #include +#include class SMESHDS_SubMesh; @@ -55,7 +55,6 @@ class TopoDS_Edge; class TopoDS_Faces; struct TNode; -//typedef std::map TNodeNodeMap; typedef std::vector TNodeColumn; // map of bottom nodes to the column of nodes above them diff --git a/src/StdMeshers/StdMeshers_ProjectionUtils.cxx b/src/StdMeshers/StdMeshers_ProjectionUtils.cxx index 3053be90d..d0f29a54b 100644 --- a/src/StdMeshers/StdMeshers_ProjectionUtils.cxx +++ b/src/StdMeshers/StdMeshers_ProjectionUtils.cxx @@ -2004,8 +2004,9 @@ bool StdMeshers_ProjectionUtils::MakeComputed(SMESH_subMesh * sm, const int iter if ( !srcMesh ) srcMesh = mesh; - if ( MakeComputed( srcMesh->GetSubMesh( srcShape ), iterationNb + 1 )) - return gen->Compute( *mesh, sm->GetSubShape() ); + if ( MakeComputed( srcMesh->GetSubMesh( srcShape ), iterationNb + 1 ) && + gen->Compute( *mesh, sm->GetSubShape() )) + return sm->IsMeshComputed(); return false; } diff --git a/src/StdMeshers/StdMeshers_Projection_1D.hxx b/src/StdMeshers/StdMeshers_Projection_1D.hxx index 5ef640170..acef6c83b 100644 --- a/src/StdMeshers/StdMeshers_Projection_1D.hxx +++ b/src/StdMeshers/StdMeshers_Projection_1D.hxx @@ -30,7 +30,7 @@ #include "SMESH_StdMeshers.hxx" -#include "SMESH_1D_Algo.hxx" +#include "SMESH_Algo.hxx" class StdMeshers_ProjectionSource1D; diff --git a/src/StdMeshers/StdMeshers_Projection_1D2D.cxx b/src/StdMeshers/StdMeshers_Projection_1D2D.cxx index efe6bf034..7e5cfe821 100644 --- a/src/StdMeshers/StdMeshers_Projection_1D2D.cxx +++ b/src/StdMeshers/StdMeshers_Projection_1D2D.cxx @@ -27,6 +27,7 @@ #include "SMESH_Gen.hxx" #include "SMESH_MesherHelper.hxx" +#include "SMESH_subMesh.hxx" #include "SMESH_subMeshEventListener.hxx" #include "StdMeshers_FaceSide.hxx" #include "StdMeshers_ProjectionSource2D.hxx" diff --git a/src/StdMeshers/StdMeshers_Projection_2D.cxx b/src/StdMeshers/StdMeshers_Projection_2D.cxx index b4734fa0c..60917a9fc 100644 --- a/src/StdMeshers/StdMeshers_Projection_2D.cxx +++ b/src/StdMeshers/StdMeshers_Projection_2D.cxx @@ -72,8 +72,6 @@ StdMeshers_Projection_2D::StdMeshers_Projection_2D(int hypId, int studyId, SMESH :SMESH_2D_Algo(hypId, studyId, gen) { _name = "Projection_2D"; - _shapeType = (1 << TopAbs_FACE); // 1 bit per shape type - _compatibleHypothesis.push_back("ProjectionSource2D"); _sourceHypo = 0; } @@ -808,7 +806,7 @@ bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& SMESH_subMesh* tgtSubMesh = tgtMesh->GetSubMesh( tgtFace ); if ( tgtMesh == srcMesh ) { - if ( !TAssocTool::MakeComputed( srcSubMesh )) + if ( !TAssocTool::MakeComputed( srcSubMesh ) || !srcSubMesh->IsMeshComputed() ) return error(COMPERR_BAD_INPUT_MESH,"Source mesh not computed"); } else { diff --git a/src/StdMeshers/StdMeshers_Projection_2D.hxx b/src/StdMeshers/StdMeshers_Projection_2D.hxx index 3d1bd1808..38bcb113a 100644 --- a/src/StdMeshers/StdMeshers_Projection_2D.hxx +++ b/src/StdMeshers/StdMeshers_Projection_2D.hxx @@ -29,7 +29,7 @@ #include "SMESH_StdMeshers.hxx" -#include "SMESH_2D_Algo.hxx" +#include "SMESH_Algo.hxx" class StdMeshers_ProjectionSource2D; diff --git a/src/StdMeshers/StdMeshers_Projection_3D.cxx b/src/StdMeshers/StdMeshers_Projection_3D.cxx index 76c29c822..ed22742f7 100644 --- a/src/StdMeshers/StdMeshers_Projection_3D.cxx +++ b/src/StdMeshers/StdMeshers_Projection_3D.cxx @@ -296,12 +296,12 @@ bool StdMeshers_Projection_3D::Compute(SMESH_Mesh& aMesh, const TopoDS_Shape& aS SMESH_Block::GetFaceEdgesIDs( fId, edgeIdVec ); for ( int i = 0; i < edgeIdVec.size(); ++i ) { int eID = edgeIdVec[ i ]; - shape2ShapeMap.Bind( tgtShapes( eID ), scrShapes( eID )); + shape2ShapeMap.Bind( scrShapes( eID ), tgtShapes( eID )); if ( i < 2 ) { vector< int > vertexIdVec; SMESH_Block::GetEdgeVertexIDs( eID, vertexIdVec ); - shape2ShapeMap.Bind( tgtShapes( vertexIdVec[0] ), scrShapes( vertexIdVec[0] )); - shape2ShapeMap.Bind( tgtShapes( vertexIdVec[1] ), scrShapes( vertexIdVec[1] )); + shape2ShapeMap.Bind( scrShapes( vertexIdVec[0]), tgtShapes( vertexIdVec[0]) ); + shape2ShapeMap.Bind( scrShapes( vertexIdVec[1]), tgtShapes( vertexIdVec[1]) ); } } } diff --git a/src/StdMeshers/StdMeshers_Projection_3D.hxx b/src/StdMeshers/StdMeshers_Projection_3D.hxx index 03e8c4838..fdfe5b817 100644 --- a/src/StdMeshers/StdMeshers_Projection_3D.hxx +++ b/src/StdMeshers/StdMeshers_Projection_3D.hxx @@ -29,7 +29,7 @@ #include "SMESH_StdMeshers.hxx" -#include "SMESH_3D_Algo.hxx" +#include "SMESH_Algo.hxx" class StdMeshers_ProjectionSource3D; diff --git a/src/StdMeshers/StdMeshers_QuadToTriaAdaptor.cxx b/src/StdMeshers/StdMeshers_QuadToTriaAdaptor.cxx index 5764cc6ea..4c96220ea 100644 --- a/src/StdMeshers/StdMeshers_QuadToTriaAdaptor.cxx +++ b/src/StdMeshers/StdMeshers_QuadToTriaAdaptor.cxx @@ -28,6 +28,8 @@ #include "SMESH_Algo.hxx" #include "SMESH_MesherHelper.hxx" +#include "SMESH_Group.hxx" +#include "SMESHDS_GroupBase.hxx" #include #include @@ -38,7 +40,9 @@ #include #include #include +#include "utilities.h" +#include #include #include @@ -224,7 +228,7 @@ namespace } } - // Within pyramids, replace nodes to remove by nodes to keep + // Within pyramids, replace nodes to remove by nodes to keep for ( unsigned i = 0; i < pyrams.size(); ++i ) { @@ -281,7 +285,7 @@ void StdMeshers_QuadToTriaAdaptor::MergePiramids( const SMDS_MeshElement* Pr // find and remove coincided faces of merged pyramids vector< const SMDS_MeshElement* > inverseElems - // copy inverse elements to avoid iteration on changing container + // copy inverse elements to avoid iteration on changing container ( TStdElemIterator( CommonNode->GetInverseElementIterator(SMDSAbs_Face)), itEnd); for ( unsigned i = 0; i < inverseElems.size(); ++i ) { @@ -550,13 +554,13 @@ bool StdMeshers_QuadToTriaAdaptor::CheckIntersection (const gp_Pnt& P, gp_Ax1 line( P, gp_Vec(P,PC)); vector< const SMDS_MeshElement* > suspectElems; searcher->GetElementsNearLine( line, SMDSAbs_Face, suspectElems); - + for ( int i = 0; i < suspectElems.size(); ++i ) { const SMDS_MeshElement* face = suspectElems[i]; if ( face == NotCheckedFace ) continue; Handle(TColgp_HSequenceOfPnt) aContour = new TColgp_HSequenceOfPnt; - for ( int i = 0; i < face->NbCornerNodes(); ++i ) + for ( int i = 0; i < face->NbCornerNodes(); ++i ) aContour->Append( SMESH_TNodeXYZ( face->GetNode(i) )); if( HasIntersection(P, PC, Pres, aContour) ) { res = true; @@ -702,7 +706,7 @@ int StdMeshers_QuadToTriaAdaptor::Preparation(const SMDS_MeshElement* face //======================================================================= //function : Compute -//purpose : +//purpose : //======================================================================= bool StdMeshers_QuadToTriaAdaptor::Compute(SMESH_Mesh& aMesh, @@ -898,6 +902,36 @@ bool StdMeshers_QuadToTriaAdaptor::Compute(SMESH_Mesh& aMesh) if ( aMesh.NbQuadrangles() < 1 ) return false; + // find if there is a group of faces identified as skin faces, with normal going outside the volume + std::string groupName = "skinFaces"; + SMESHDS_GroupBase* groupDS = 0; + SMESH_Mesh::GroupIteratorPtr groupIt = aMesh.GetGroups(); + while ( groupIt->more() ) + { + groupDS = 0; + SMESH_Group * group = groupIt->next(); + if ( !group ) continue; + groupDS = group->GetGroupDS(); + if ( !groupDS || groupDS->IsEmpty() ) + { + groupDS = 0; + continue; + } + if (groupDS->GetType() != SMDSAbs_Face) + { + groupDS = 0; + continue; + } + std::string grpName = group->GetName(); + if (grpName == groupName) + { + MESSAGE("group skinFaces provided"); + break; + } + else + groupDS = 0; + } + vector myPyramids; SMESH_MesherHelper helper(aMesh); helper.IsQuadraticSubMesh(aMesh.GetShapeToMesh()); @@ -911,7 +945,7 @@ bool StdMeshers_QuadToTriaAdaptor::Compute(SMESH_Mesh& aMesh) SMESH_ProxyMesh::SubMesh* prxSubMesh = getProxySubMesh(); SMDS_FaceIteratorPtr fIt = meshDS->facesIterator(/*idInceasingOrder=*/true); - while( fIt->more()) + while( fIt->more()) { const SMDS_MeshElement* face = fIt->next(); if ( !face ) continue; @@ -1003,7 +1037,7 @@ bool StdMeshers_QuadToTriaAdaptor::Compute(SMESH_Mesh& aMesh) continue; } - // Case of non-degenerated quadrangle + // Case of non-degenerated quadrangle // Find pyramid peak @@ -1062,6 +1096,10 @@ bool StdMeshers_QuadToTriaAdaptor::Compute(SMESH_Mesh& aMesh) } } + // if the face belong to the group of skinFaces, do not build a pyramid outside + if (groupDS && groupDS->Contains(face)) + intersected[0] = false; + // Create one or two pyramids for ( int isRev = 0; isRev < 2; ++isRev ) @@ -1176,7 +1214,7 @@ bool StdMeshers_QuadToTriaAdaptor::Compute2ndPart(SMESH_Mesh& for(k=0; k<4 && !hasInt; k++) { gp_Vec Vtmp(PsI[k],PsI[4]); gp_Pnt Pshift = PsI[k].XYZ() + Vtmp.XYZ() * 0.01; // base node moved a bit to apex - hasInt = + hasInt = ( HasIntersection3( Pshift, PsI[4], Pint, PsJ[0], PsJ[1], PsJ[4]) || HasIntersection3( Pshift, PsI[4], Pint, PsJ[1], PsJ[2], PsJ[4]) || HasIntersection3( Pshift, PsI[4], Pint, PsJ[2], PsJ[3], PsJ[4]) || @@ -1185,7 +1223,7 @@ bool StdMeshers_QuadToTriaAdaptor::Compute2ndPart(SMESH_Mesh& for(k=0; k<4 && !hasInt; k++) { gp_Vec Vtmp(PsJ[k],PsJ[4]); gp_Pnt Pshift = PsJ[k].XYZ() + Vtmp.XYZ() * 0.01; - hasInt = + hasInt = ( HasIntersection3( Pshift, PsJ[4], Pint, PsI[0], PsI[1], PsI[4]) || HasIntersection3( Pshift, PsJ[4], Pint, PsI[1], PsI[2], PsI[4]) || HasIntersection3( Pshift, PsJ[4], Pint, PsI[2], PsI[3], PsI[4]) || @@ -1215,7 +1253,7 @@ bool StdMeshers_QuadToTriaAdaptor::Compute2ndPart(SMESH_Mesh& PCi += PsI[k].XYZ(); PCj += PsJ[k].XYZ(); } - PCi /= 4; PCj /= 4; + PCi /= 4; PCj /= 4; gp_Vec VN1(PCi,PsI[4]); gp_Vec VN2(PCj,PsJ[4]); gp_Vec VI1(PCi,Pint); diff --git a/src/StdMeshers/StdMeshers_Quadrangle_2D.hxx b/src/StdMeshers/StdMeshers_Quadrangle_2D.hxx index 3f9202e86..e200bc5af 100644 --- a/src/StdMeshers/StdMeshers_Quadrangle_2D.hxx +++ b/src/StdMeshers/StdMeshers_Quadrangle_2D.hxx @@ -31,7 +31,7 @@ #include "StdMeshers_QuadrangleParams.hxx" -#include "SMESH_2D_Algo.hxx" +#include "SMESH_Algo.hxx" #include "Utils_SALOME_Exception.hxx" #include diff --git a/src/StdMeshers/StdMeshers_RadialPrism_3D.hxx b/src/StdMeshers/StdMeshers_RadialPrism_3D.hxx index 11959d46f..7a6eaf9bd 100644 --- a/src/StdMeshers/StdMeshers_RadialPrism_3D.hxx +++ b/src/StdMeshers/StdMeshers_RadialPrism_3D.hxx @@ -29,7 +29,7 @@ #include "SMESH_StdMeshers.hxx" -#include "SMESH_3D_Algo.hxx" +#include "SMESH_Algo.hxx" #include "SMDS_MeshNode.hxx" #include diff --git a/src/StdMeshers/StdMeshers_RadialQuadrangle_1D2D.cxx b/src/StdMeshers/StdMeshers_RadialQuadrangle_1D2D.cxx index d93c64eb6..3aeee6062 100644 --- a/src/StdMeshers/StdMeshers_RadialQuadrangle_1D2D.cxx +++ b/src/StdMeshers/StdMeshers_RadialQuadrangle_1D2D.cxx @@ -20,8 +20,6 @@ // SMESH SMESH : implementaion of SMESH idl descriptions // File : StdMeshers_RadialQuadrangle_1D2D.cxx // Module : SMESH -// Created : Fri Oct 20 11:37:07 2006 -// Author : Edward AGAPOV (eap) #include "StdMeshers_RadialQuadrangle_1D2D.hxx" @@ -878,6 +876,7 @@ bool StdMeshers_RadialQuadrangle_1D2D::Compute(SMESH_Mesh& aMesh, // orientation bool IsForward = ( CircEdge.Orientation()==TopAbs_FORWARD ); + const double angleSign = ( F.Orientation() == TopAbs_REVERSED ? -1.0 : 1.0 ); // create nodes and mesh elements on face // find axis of rotation @@ -896,7 +895,7 @@ bool StdMeshers_RadialQuadrangle_1D2D::Compute(SMESH_Mesh& aMesh, gp_Ax1 theAxis(P0,gp_Dir(Axis)); aTrsf.SetRotation( theAxis, Angles.Value(i) ); gp_Trsf2d aTrsf2d; - aTrsf2d.SetRotation( PC, Angles.Value(i) ); + aTrsf2d.SetRotation( PC, Angles.Value(i) * angleSign ); // create nodes int j = 1; for(; j<=Points.Length(); j++) { diff --git a/src/StdMeshers/StdMeshers_RadialQuadrangle_1D2D.hxx b/src/StdMeshers/StdMeshers_RadialQuadrangle_1D2D.hxx index b68ebe930..6a4def9e5 100644 --- a/src/StdMeshers/StdMeshers_RadialQuadrangle_1D2D.hxx +++ b/src/StdMeshers/StdMeshers_RadialQuadrangle_1D2D.hxx @@ -26,7 +26,7 @@ #include "SMESH_StdMeshers.hxx" -#include "SMESH_2D_Algo.hxx" +#include "SMESH_Algo.hxx" #include diff --git a/src/StdMeshers/StdMeshers_Regular_1D.cxx b/src/StdMeshers/StdMeshers_Regular_1D.cxx index 8d900955d..6ea520001 100644 --- a/src/StdMeshers/StdMeshers_Regular_1D.cxx +++ b/src/StdMeshers/StdMeshers_Regular_1D.cxx @@ -354,7 +354,7 @@ static void compensateError(double a1, double an, bool adjustNeighbors2an = false) { int i, nPar = theParams.size(); - if ( a1 + an < length && nPar > 1 ) + if ( a1 + an <= length && nPar > 1 ) { bool reverse = ( U1 > Un ); GCPnts_AbscissaPoint Discret(C3d, reverse ? an : -an, Un); @@ -375,10 +375,9 @@ static void compensateError(double a1, double an, dUn = Utgt - theParams.back(); } - double q = dUn / ( nPar - 1 ); if ( !adjustNeighbors2an ) { - q = dUn / ( Utgt - Un ); // (signed) factor of segment length change + double q = dUn / ( Utgt - Un ); // (signed) factor of segment length change for ( itU = theParams.rbegin(), i = 1; i < nPar; i++ ) { double prevU = *itU; (*itU) += dUn; @@ -386,7 +385,13 @@ static void compensateError(double a1, double an, dUn = q * (*itU - prevU) * (prevU-U1)/(Un-U1); } } - else { + else if ( nPar == 1 ) + { + theParams.back() += dUn; + } + else + { + double q = dUn / ( nPar - 1 ); theParams.back() += dUn; double sign = reverse ? -1 : 1; double prevU = theParams.back(); @@ -608,12 +613,14 @@ bool StdMeshers_Regular_1D::computeInternalParameters(SMESH_Mesh & theMesh, case NB_SEGMENTS: { double eltSize = 1; + int nbSegments; if ( _hypType == MAX_LENGTH ) { double nbseg = ceil(theLength / _value[ BEG_LENGTH_IND ]); // integer sup if (nbseg <= 0) nbseg = 1; // degenerated edge eltSize = theLength / nbseg; + nbSegments = (int) nbseg; } else if ( _hypType == LOCAL_LENGTH ) { @@ -654,13 +661,14 @@ bool StdMeshers_Regular_1D::computeInternalParameters(SMESH_Mesh & theMesh, if (nbseg <= 0) nbseg = 1; // degenerated edge eltSize = theLength / nbseg; + nbSegments = (int) nbseg; } else { // Number Of Segments hypothesis - int NbSegm = _ivalue[ NB_SEGMENTS_IND ]; - if ( NbSegm < 1 ) return false; - if ( NbSegm == 1 ) return true; + nbSegments = _ivalue[ NB_SEGMENTS_IND ]; + if ( nbSegments < 1 ) return false; + if ( nbSegments == 1 ) return true; switch (_ivalue[ DISTR_TYPE_IND ]) { @@ -670,8 +678,8 @@ bool StdMeshers_Regular_1D::computeInternalParameters(SMESH_Mesh & theMesh, if (fabs(scale - 1.0) < Precision::Confusion()) { // special case to avoid division by zero - for (int i = 1; i < NbSegm; i++) { - double param = f + (l - f) * i / NbSegm; + for (int i = 1; i < nbSegments; i++) { + double param = f + (l - f) * i / nbSegments; theParams.push_back( param ); } } else { @@ -679,10 +687,10 @@ bool StdMeshers_Regular_1D::computeInternalParameters(SMESH_Mesh & theMesh, if ( theReverse ) scale = 1.0 / scale; - double alpha = pow(scale, 1.0 / (NbSegm - 1)); - double factor = (l - f) / (1.0 - pow(alpha, NbSegm)); + double alpha = pow(scale, 1.0 / (nbSegments - 1)); + double factor = (l - f) / (1.0 - pow(alpha, nbSegments)); - for (int i = 1; i < NbSegm; i++) { + for (int i = 1; i < nbSegments; i++) { double param = f + factor * (1.0 - pow(alpha, i)); theParams.push_back( param ); } @@ -715,7 +723,7 @@ bool StdMeshers_Regular_1D::computeInternalParameters(SMESH_Mesh & theMesh, } break; case StdMeshers_NumberOfSegments::DT_Regular: - eltSize = theLength / _ivalue[ NB_SEGMENTS_IND ]; + eltSize = theLength / nbSegments; break; default: return false; @@ -725,13 +733,13 @@ bool StdMeshers_Regular_1D::computeInternalParameters(SMESH_Mesh & theMesh, if ( !Discret.IsDone() ) return error( "GCPnts_UniformAbscissa failed"); - int NbPoints = Discret.NbPoints(); - for ( int i = 2; i < NbPoints; i++ ) + int NbPoints = Min( Discret.NbPoints(), nbSegments + 1 ); + for ( int i = 2; i < NbPoints; i++ ) // skip 1st and last points { double param = Discret.Parameter(i); theParams.push_back( param ); } - compensateError( eltSize, eltSize, f, l, theLength, theC3d, theParams ); // for PAL9899 + compensateError( eltSize, eltSize, f, l, theLength, theC3d, theParams, true ); // for PAL9899 return true; } diff --git a/src/StdMeshers/StdMeshers_Regular_1D.hxx b/src/StdMeshers/StdMeshers_Regular_1D.hxx index aed1064ab..8dceddb55 100644 --- a/src/StdMeshers/StdMeshers_Regular_1D.hxx +++ b/src/StdMeshers/StdMeshers_Regular_1D.hxx @@ -31,7 +31,7 @@ #include "SMESH_StdMeshers.hxx" -#include "SMESH_1D_Algo.hxx" +#include "SMESH_Algo.hxx" #include "StdMeshers_FixedPoints1D.hxx" diff --git a/src/StdMeshers/StdMeshers_SegmentAroundVertex_0D.hxx b/src/StdMeshers/StdMeshers_SegmentAroundVertex_0D.hxx index abb8ce2c6..97d83042e 100644 --- a/src/StdMeshers/StdMeshers_SegmentAroundVertex_0D.hxx +++ b/src/StdMeshers/StdMeshers_SegmentAroundVertex_0D.hxx @@ -29,7 +29,7 @@ #include "SMESH_StdMeshers.hxx" -#include "SMESH_0D_Algo.hxx" +#include "SMESH_Algo.hxx" /*! * \brief Algorithm existing in order just to enable assignation of diff --git a/src/StdMeshers/StdMeshers_UseExisting_1D2D.hxx b/src/StdMeshers/StdMeshers_UseExisting_1D2D.hxx index 23c64b5b9..561036a44 100644 --- a/src/StdMeshers/StdMeshers_UseExisting_1D2D.hxx +++ b/src/StdMeshers/StdMeshers_UseExisting_1D2D.hxx @@ -26,8 +26,7 @@ #include "SMESH_StdMeshers.hxx" -#include "SMESH_1D_Algo.hxx" -#include "SMESH_2D_Algo.hxx" +#include "SMESH_Algo.hxx" /*! * \brief 1D and 2D algorithms doing nothing to allow mesh generation diff --git a/src/StdMeshers/StdMeshers_ViscousLayers.cxx b/src/StdMeshers/StdMeshers_ViscousLayers.cxx index ddae235f7..c875ca104 100644 --- a/src/StdMeshers/StdMeshers_ViscousLayers.cxx +++ b/src/StdMeshers/StdMeshers_ViscousLayers.cxx @@ -976,6 +976,9 @@ SMESH_ComputeErrorPtr _ViscousBuilder::Compute(SMESH_Mesh& theMesh, { if ( ! makeLayer(_sdVec[i]) ) return _error; + + if ( _sdVec[i]._edges.size() == 0 ) + continue; if ( ! inflate(_sdVec[i]) ) return _error; @@ -2504,22 +2507,21 @@ bool _ViscousBuilder::smoothAnalyticEdge( _SolidData& data, else // 2D { const gp_XY center( center3D.X(), center3D.Y() ); - + gp_XY uv0 = helper.GetNodeUV( F, data._edges[iFrom]->_2neibors->_nodes[0]); gp_XY uvM = helper.GetNodeUV( F, data._edges[iFrom]->_nodes.back()); gp_XY uv1 = helper.GetNodeUV( F, data._edges[iTo-1]->_2neibors->_nodes[1]); gp_Vec2d vec0( center, uv0 ); - gp_Vec2d vecM( center, uvM); + gp_Vec2d vecM( center, uvM ); gp_Vec2d vec1( center, uv1 ); double uLast = vec0.Angle( vec1 ); // -PI - +PI double uMidl = vec0.Angle( vecM ); - if ( uLast < 0 ) uLast += 2.*M_PI; // 0.0 - 2*PI - if ( uMidl < 0 ) uMidl += 2.*M_PI; - const bool sense = ( uMidl < uLast ); + if ( uLast * uMidl < 0. ) + uLast += ( uMidl > 0 ? +2. : -2. ) * M_PI; const double radius = 0.5 * ( vec0.Magnitude() + vec1.Magnitude() ); - gp_Ax2d axis( center, vec0 ); - gp_Circ2d circ ( axis, radius, sense ); + gp_Ax2d axis( center, vec0 ); + gp_Circ2d circ( axis, radius ); for ( int i = iFrom; i < iTo; ++i ) { double newU = uLast * len[i-iFrom] / len.back(); @@ -3375,6 +3377,15 @@ bool _ViscousBuilder::refine(_SolidData& data) } } + if ( !getMeshDS()->IsEmbeddedMode() ) + // Log node movement + for ( unsigned i = 0; i < data._edges.size(); ++i ) + { + _LayerEdge& edge = *data._edges[i]; + SMESH_TNodeXYZ p ( edge._nodes.back() ); + getMeshDS()->MoveNode( p._node, p.X(), p.Y(), p.Z() ); + } + // TODO: make quadratic prisms and polyhedrons(?) helper.SetElementsOnShape(true); @@ -3463,7 +3474,7 @@ bool _ViscousBuilder::shrink() helper.ToFixNodeParameters( true ); // EDGE's to shrink - map< int, _Shrinker1D > e2shrMap; + map< TGeomID, _Shrinker1D > e2shrMap; // loop on FACES to srink mesh on map< TGeomID, _SolidData* >::iterator f2sd = f2sdMap.begin(); @@ -3633,7 +3644,8 @@ bool _ViscousBuilder::shrink() for ( unsigned i = 0; i < nodesToSmooth.size(); ++i ) { moved |= nodesToSmooth[i].Smooth( badNb,surface,helper,refSign, - /*isCentroidal=*/isConcaveFace,/*set3D=*/false ); + /*isCentroidal=*/isConcaveFace, + /*set3D=*/isConcaveFace); } if ( badNb < oldBadNb ) nbNoImpSteps = 0; @@ -3650,12 +3662,10 @@ bool _ViscousBuilder::shrink() bool highQuality; { const bool hasTria = _mesh->NbTriangles(), hasQuad = _mesh->NbQuadrangles(); - if ( hasTria != hasQuad ) - { + if ( hasTria != hasQuad ) { highQuality = hasQuad; } - else - { + else { set nbNodesSet; SMDS_ElemIteratorPtr fIt = smDS->GetElements(); while ( fIt->more() && nbNodesSet.size() < 2 ) @@ -3676,6 +3686,14 @@ bool _ViscousBuilder::shrink() // Set an event listener to clear FACE sub-mesh together with SOLID sub-mesh _SrinkShapeListener::ToClearSubMeshWithSolid( sm, data._solid ); + if ( !getMeshDS()->IsEmbeddedMode() ) + // Log node movement + for ( unsigned i = 0; i < nodesToSmooth.size(); ++i ) + { + SMESH_TNodeXYZ p ( nodesToSmooth[i]._node ); + getMeshDS()->MoveNode( nodesToSmooth[i]._node, p.X(), p.Y(), p.Z() ); + } + } // loop on FACES to srink mesh on @@ -4227,7 +4245,7 @@ void _Shrinker1D::AddEdge( const _LayerEdge* e, SMESH_MesherHelper& helper ) GeomAdaptor_Curve aCurve(C, f,l); const double totLen = GCPnts_AbscissaPoint::Length(aCurve, f, l); - int nbExpectNodes = eSubMesh->NbNodes() - e->_nodes.size(); + int nbExpectNodes = eSubMesh->NbNodes(); _initU .reserve( nbExpectNodes ); _normPar.reserve( nbExpectNodes ); _nodes .reserve( nbExpectNodes ); @@ -4439,6 +4457,8 @@ bool _ViscousBuilder::addBoundaryElements() F = e2f->second.Oriented( TopAbs_FORWARD ); reverse = ( helper.GetSubShapeOri( F, E ) == TopAbs_REVERSED ); if ( helper.GetSubShapeOri( data._solid, F ) == TopAbs_REVERSED ) + reverse = !reverse, F.Reverse(); + if ( SMESH_Algo::IsReversedSubMesh( TopoDS::Face(F), getMeshDS() )) reverse = !reverse; } else @@ -4470,12 +4490,28 @@ bool _ViscousBuilder::addBoundaryElements() vector< const SMDS_MeshNode*>& nn1 = ledges[j-dj1]->_nodes; vector< const SMDS_MeshNode*>& nn2 = ledges[j-dj2]->_nodes; if ( isOnFace ) - for ( unsigned z = 1; z < nn1.size(); ++z ) + for ( size_t z = 1; z < nn1.size(); ++z ) sm->AddElement( getMeshDS()->AddFace( nn1[z-1], nn2[z-1], nn2[z], nn1[z] )); else - for ( unsigned z = 1; z < nn1.size(); ++z ) + for ( size_t z = 1; z < nn1.size(); ++z ) sm->AddElement( new SMDS_FaceOfNodes( nn1[z-1], nn2[z-1], nn2[z], nn1[z])); } + + // Make edges + for ( int isFirst = 0; isFirst < 2; ++isFirst ) + { + _LayerEdge* edge = isFirst ? ledges.front() : ledges.back(); + if ( !edge->_sWOL.IsNull() && edge->_sWOL.ShapeType() == TopAbs_EDGE ) + { + vector< const SMDS_MeshNode*>& nn = edge->_nodes; + if ( nn[1]->GetInverseElementIterator( SMDSAbs_Edge )->more() ) + continue; + helper.SetSubShape( edge->_sWOL ); + helper.SetElementsOnShape( true ); + for ( size_t z = 1; z < nn.size(); ++z ) + helper.AddEdge( nn[z-1], nn[z] ); + } + } } } diff --git a/src/StdMeshersGUI/StdMeshersGUI_CartesianParamCreator.cxx b/src/StdMeshersGUI/StdMeshersGUI_CartesianParamCreator.cxx index 48eec0eb4..52960e78c 100644 --- a/src/StdMeshersGUI/StdMeshersGUI_CartesianParamCreator.cxx +++ b/src/StdMeshersGUI/StdMeshersGUI_CartesianParamCreator.cxx @@ -606,7 +606,7 @@ QFrame* StdMeshersGUI_CartesianParamCreator::buildFrame() argGroupLayout->addWidget( new QLabel( tr( "THRESHOLD" ), GroupC1 ), row, 0 ); myThreshold = new SMESHGUI_SpinBox( GroupC1 ); myThreshold->setAcceptNames( false ); // No Notebook variables allowed - myThreshold->RangeStepAndValidator( 1.1, 1e+10, 1., "length_precision" ); + myThreshold->RangeStepAndValidator( 1.00001, 1e+10, 1., "length_precision" ); argGroupLayout->addWidget( myThreshold, row, 1 ); row++; diff --git a/src/StdMeshersGUI/StdMeshersGUI_StdHypothesisCreator.cxx b/src/StdMeshersGUI/StdMeshersGUI_StdHypothesisCreator.cxx index 6e902a7f1..87727c20d 100644 --- a/src/StdMeshersGUI/StdMeshersGUI_StdHypothesisCreator.cxx +++ b/src/StdMeshersGUI/StdMeshersGUI_StdHypothesisCreator.cxx @@ -747,7 +747,7 @@ bool StdMeshersGUI_StdHypothesisCreator::stdParams( ListOfStdParams& p ) const } SMESH::SMESH_Hypothesis_var hyp = initParamsHypothesis(); - SMESH::ListOfParameters_var aParameters = hyp->GetLastParameters(); + //SMESH::ListOfParameters_var aParameters = hyp->GetLastParameters(); if( hypType()=="LocalLength" ) { diff --git a/src/StdMeshersGUI/StdMeshersGUI_SubShapeSelectorWdg.cxx b/src/StdMeshersGUI/StdMeshersGUI_SubShapeSelectorWdg.cxx index 8c2240803..637163f66 100644 --- a/src/StdMeshersGUI/StdMeshersGUI_SubShapeSelectorWdg.cxx +++ b/src/StdMeshersGUI/StdMeshersGUI_SubShapeSelectorWdg.cxx @@ -249,7 +249,7 @@ void StdMeshersGUI_SubShapeSelectorWdg::SelectionIntoArgument() for ( ; anIt.More(); anIt.Next()) { // Loop on selected objects Handle(SALOME_InteractiveObject) IO = anIt.Value(); - GEOM::GEOM_Object_var aGeomObj = GetGeomObjectByEntry( IO->getEntry() ); + GEOM::GEOM_Object_var aGeomObj = GetGeomObjectByEntry( IO->getEntry() ); if ( !CORBA::is_nil( aGeomObj ) ) { // Selected Object From Study GEOM::GEOM_Object_ptr aGeomFatherObj = aGeomObj->GetMainShape(); QString aFatherEntry = ""; @@ -303,7 +303,9 @@ void StdMeshersGUI_SubShapeSelectorWdg::SelectionIntoArgument() } } // update add button - myAddButton->setEnabled( ( myListWidget->count() < myMaxSize || myMaxSize == -1 ) && mySelectedIDs.size() > 0 && ( mySelectedIDs.size() <= myMaxSize || myMaxSize == -1 ) ); + myAddButton->setEnabled( ( myListWidget->count() < myMaxSize || myMaxSize == -1 ) && + mySelectedIDs.size() > 0 && + ( mySelectedIDs.size() <= myMaxSize || myMaxSize == -1 ) ); //Connect Selected Ids in viewer and dialog's Ids list bool signalsBlocked = myListWidget->blockSignals( true ); -- 2.30.2