From a51df48e9905b1ff60c6693fca90cd7eb303a39d Mon Sep 17 00:00:00 2001 From: vsr Date: Thu, 9 Aug 2012 11:46:18 +0000 Subject: [PATCH] Merge from V6_main_20120808 08Aug12 --- GHS3DPLUGIN_version.h.in | 28 +- Makefile.am | 33 +- adm_local/Makefile.am | 27 +- adm_local/unix/Makefile.am | 27 +- adm_local/unix/config_files/Makefile.am | 27 +- adm_local/unix/config_files/check_GHS3D.m4 | 27 +- .../unix/config_files/check_GHS3DPLUGIN.m4 | 27 +- adm_local/unix/make_common_starter.am | 35 +- bin/Makefile.am | 27 +- bin/VERSION.in | 4 +- build_cmake | 27 + build_cmake.bat | 20 + build_configure | 97 +- clean_configure | 39 +- configure.ac | 175 +- doc/Makefile.am | 24 + doc/salome/Makefile.am | 28 + doc/salome/gui/GHS3DPLUGIN/Makefile.am | 62 + doc/salome/gui/GHS3DPLUGIN/doxyfile.in | 81 + doc/salome/gui/GHS3DPLUGIN/doxyfile_py.in | 159 + .../images/ghs3d_enforced_meshes.png | Bin 0 -> 32993 bytes .../images/ghs3d_enforced_vertices.png | Bin 0 -> 33075 bytes .../images/ghs3d_parameters_advanced.png | Bin 0 -> 36277 bytes .../images/ghs3d_parameters_basic.png | Bin 0 -> 25962 bytes .../GHS3DPLUGIN/images/ghs3d_screenshot.png | Bin 0 -> 69709 bytes .../images/ghs3d_screenshot_enf1.png | Bin 0 -> 89248 bytes .../images/ghs3d_screenshot_enf2.png | Bin 0 -> 91984 bytes .../images/ghs3d_screenshot_enf3.png | Bin 0 -> 61639 bytes .../images/ghs3d_screenshot_enf4.png | Bin 0 -> 64362 bytes .../images/ghs3d_screenshot_enf5.png | Bin 0 -> 57590 bytes .../images/ghs3d_screenshot_enf6.png | Bin 0 -> 62982 bytes doc/salome/gui/GHS3DPLUGIN/images/head.png | Bin 0 -> 78545 bytes doc/salome/gui/GHS3DPLUGIN/images/image2.gif | Bin 0 -> 4694 bytes .../gui/GHS3DPLUGIN/input/additional_hypo.doc | 18 + .../gui/GHS3DPLUGIN/input/ghs3d_hypo.doc | 180 + .../input/ghs3dplugin_python_interface.doc | 240 + doc/salome/gui/GHS3DPLUGIN/input/index.doc | 25 + doc/salome/gui/GHS3DPLUGIN/static/doxygen.css | 836 ++++ doc/salome/gui/GHS3DPLUGIN/static/footer.html | 12 + .../gui/GHS3DPLUGIN/static/header.html.in | 20 + .../gui/GHS3DPLUGIN/static/header_py.html.in | 21 + doc/salome/gui/Makefile.am | 26 + idl/GHS3DPlugin_Algorithm.idl | 97 +- idl/Makefile.am | 50 +- resources/GHS3DPlugin.xml | 13 +- resources/Makefile.am | 27 +- resources/SalomeApp.xml | 5 +- src/GHS3DPlugin/GHS3DPluginDC.py | 186 + src/GHS3DPlugin/GHS3DPlugin_Defs.hxx | 37 + src/GHS3DPlugin/GHS3DPlugin_GHS3D.cxx | 4314 +++++++++++++++++ src/{ => GHS3DPlugin}/GHS3DPlugin_GHS3D.hxx | 65 +- src/GHS3DPlugin/GHS3DPlugin_GHS3D_i.cxx | 116 + src/{ => GHS3DPlugin}/GHS3DPlugin_GHS3D_i.hxx | 29 +- src/GHS3DPlugin/GHS3DPlugin_Hypothesis.cxx | 1356 ++++++ src/GHS3DPlugin/GHS3DPlugin_Hypothesis.hxx | 341 ++ src/GHS3DPlugin/GHS3DPlugin_Hypothesis_i.cxx | 1163 +++++ src/GHS3DPlugin/GHS3DPlugin_Hypothesis_i.hxx | 163 + src/{ => GHS3DPlugin}/GHS3DPlugin_i.cxx | 31 +- src/GHS3DPlugin/Makefile.am | 68 + src/GHS3DPlugin/libmesh5.c | 1192 +++++ src/GHS3DPlugin/libmesh5.h | 152 + src/GHS3DPlugin_Defs.hxx | 36 - src/GHS3DPlugin_GHS3D.cxx | 1698 ------- src/GHS3DPlugin_GHS3D_i.cxx | 80 - src/GHS3DPlugin_Hypothesis.cxx | 628 --- src/GHS3DPlugin_Hypothesis.hxx | 152 - src/GHS3DPlugin_Hypothesis_i.cxx | 318 -- src/GHS3DPlugin_Hypothesis_i.hxx | 118 - src/GUI/GHS3DPluginGUI.cxx | 42 + src/GUI/GHS3DPluginGUI_Enums.h | 84 + src/GUI/GHS3DPluginGUI_HypothesisCreator.cxx | 1831 ++++++- src/GUI/GHS3DPluginGUI_HypothesisCreator.h | 293 +- src/GUI/GHS3DPlugin_images.ts | 23 +- src/GUI/GHS3DPlugin_msg_en.ts | 313 +- src/GUI/GHS3DPlugin_msg_fr.ts | 207 + src/GUI/Makefile.am | 83 +- src/Makefile.am | 68 +- 77 files changed, 13932 insertions(+), 3799 deletions(-) create mode 100755 build_cmake create mode 100644 build_cmake.bat create mode 100644 doc/Makefile.am create mode 100644 doc/salome/Makefile.am create mode 100755 doc/salome/gui/GHS3DPLUGIN/Makefile.am create mode 100755 doc/salome/gui/GHS3DPLUGIN/doxyfile.in create mode 100755 doc/salome/gui/GHS3DPLUGIN/doxyfile_py.in create mode 100644 doc/salome/gui/GHS3DPLUGIN/images/ghs3d_enforced_meshes.png create mode 100644 doc/salome/gui/GHS3DPLUGIN/images/ghs3d_enforced_vertices.png create mode 100644 doc/salome/gui/GHS3DPLUGIN/images/ghs3d_parameters_advanced.png create mode 100644 doc/salome/gui/GHS3DPLUGIN/images/ghs3d_parameters_basic.png create mode 100644 doc/salome/gui/GHS3DPLUGIN/images/ghs3d_screenshot.png create mode 100644 doc/salome/gui/GHS3DPLUGIN/images/ghs3d_screenshot_enf1.png create mode 100644 doc/salome/gui/GHS3DPLUGIN/images/ghs3d_screenshot_enf2.png create mode 100644 doc/salome/gui/GHS3DPLUGIN/images/ghs3d_screenshot_enf3.png create mode 100644 doc/salome/gui/GHS3DPLUGIN/images/ghs3d_screenshot_enf4.png create mode 100644 doc/salome/gui/GHS3DPLUGIN/images/ghs3d_screenshot_enf5.png create mode 100644 doc/salome/gui/GHS3DPLUGIN/images/ghs3d_screenshot_enf6.png create mode 100755 doc/salome/gui/GHS3DPLUGIN/images/head.png create mode 100755 doc/salome/gui/GHS3DPLUGIN/images/image2.gif create mode 100644 doc/salome/gui/GHS3DPLUGIN/input/additional_hypo.doc create mode 100644 doc/salome/gui/GHS3DPLUGIN/input/ghs3d_hypo.doc create mode 100644 doc/salome/gui/GHS3DPLUGIN/input/ghs3dplugin_python_interface.doc create mode 100644 doc/salome/gui/GHS3DPLUGIN/input/index.doc create mode 100755 doc/salome/gui/GHS3DPLUGIN/static/doxygen.css create mode 100755 doc/salome/gui/GHS3DPLUGIN/static/footer.html create mode 100755 doc/salome/gui/GHS3DPLUGIN/static/header.html.in create mode 100644 doc/salome/gui/GHS3DPLUGIN/static/header_py.html.in create mode 100644 doc/salome/gui/Makefile.am create mode 100644 src/GHS3DPlugin/GHS3DPluginDC.py create mode 100644 src/GHS3DPlugin/GHS3DPlugin_Defs.hxx create mode 100644 src/GHS3DPlugin/GHS3DPlugin_GHS3D.cxx rename src/{ => GHS3DPlugin}/GHS3DPlugin_GHS3D.hxx (53%) create mode 100644 src/GHS3DPlugin/GHS3DPlugin_GHS3D_i.cxx rename src/{ => GHS3DPlugin}/GHS3DPlugin_GHS3D_i.hxx (51%) create mode 100644 src/GHS3DPlugin/GHS3DPlugin_Hypothesis.cxx create mode 100644 src/GHS3DPlugin/GHS3DPlugin_Hypothesis.hxx create mode 100644 src/GHS3DPlugin/GHS3DPlugin_Hypothesis_i.cxx create mode 100644 src/GHS3DPlugin/GHS3DPlugin_Hypothesis_i.hxx rename src/{ => GHS3DPlugin}/GHS3DPlugin_i.cxx (56%) create mode 100644 src/GHS3DPlugin/Makefile.am create mode 100644 src/GHS3DPlugin/libmesh5.c create mode 100755 src/GHS3DPlugin/libmesh5.h delete mode 100644 src/GHS3DPlugin_Defs.hxx delete mode 100644 src/GHS3DPlugin_GHS3D.cxx delete mode 100644 src/GHS3DPlugin_GHS3D_i.cxx delete mode 100644 src/GHS3DPlugin_Hypothesis.cxx delete mode 100644 src/GHS3DPlugin_Hypothesis.hxx delete mode 100644 src/GHS3DPlugin_Hypothesis_i.cxx delete mode 100644 src/GHS3DPlugin_Hypothesis_i.hxx create mode 100644 src/GUI/GHS3DPluginGUI.cxx create mode 100644 src/GUI/GHS3DPluginGUI_Enums.h create mode 100755 src/GUI/GHS3DPlugin_msg_fr.ts diff --git a/GHS3DPLUGIN_version.h.in b/GHS3DPLUGIN_version.h.in index a04a008..7d4806c 100644 --- a/GHS3DPLUGIN_version.h.in +++ b/GHS3DPLUGIN_version.h.in @@ -1,21 +1,22 @@ -// Copyright (C) 2004-2008 CEA/DEN, EDF R&D +// Copyright (C) 2004-2012 CEA/DEN, EDF R&D // -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License. +// 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. +// 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 +// 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 +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // + // File : GHS3DPLUGIN_version.h // Author : Vadim SANDLER // Module : SALOME @@ -29,5 +30,6 @@ #define GHS3DPLUGIN_VERSION_STR "@VERSION@" #define GHS3DPLUGIN_VERSION @XVERSION@ +#define GHS3DPLUGIN_DEVELOPMENT @VERSION_DEV@ #endif // __GHS3DPLUGIN_VERSION_H__ diff --git a/Makefile.am b/Makefile.am index 38e3966..afc6dd9 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,21 +1,22 @@ -# Copyright (C) 2004-2008 CEA/DEN, EDF R&D +# Copyright (C) 2004-2012 CEA/DEN, EDF R&D # -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License. +# 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. +# 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 +# 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 +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com # + # -* Makefile *- # Author : Patrick GOLDBRONN (CEA) # Date : 28/06/2001 @@ -39,11 +40,11 @@ else !GHS3DPLUGIN_ENABLE_GUI -I ${SMESH_ROOT_DIR}/adm_local/unix/config_files endif -SUBDIRS = idl adm_local resources src bin +SUBDIRS = idl adm_local resources src bin doc -DIST_SUBDIRS = idl adm_local resources src bin +DIST_SUBDIRS = idl adm_local resources src bin doc -DISTCLEANFILES = a.out aclocal.m4 configure +DISTCLEANFILES = a.out aclocal.m4 configure local-install.sh hack_libtool salomeinclude_DATA = GHS3DPLUGIN_version.h diff --git a/adm_local/Makefile.am b/adm_local/Makefile.am index 0c722d0..249f903 100644 --- a/adm_local/Makefile.am +++ b/adm_local/Makefile.am @@ -1,21 +1,22 @@ -# Copyright (C) 2004-2008 CEA/DEN, EDF R&D +# Copyright (C) 2004-2012 CEA/DEN, EDF R&D # -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License. +# 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. +# 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 +# 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 +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com # + include $(top_srcdir)/adm_local/unix/make_common_starter.am SUBDIRS = unix diff --git a/adm_local/unix/Makefile.am b/adm_local/unix/Makefile.am index d109e0d..cd2cfe6 100644 --- a/adm_local/unix/Makefile.am +++ b/adm_local/unix/Makefile.am @@ -1,21 +1,22 @@ -# Copyright (C) 2004-2008 CEA/DEN, EDF R&D +# Copyright (C) 2004-2012 CEA/DEN, EDF R&D # -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License. +# 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. +# 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 +# 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 +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com # + include $(top_srcdir)/adm_local/unix/make_common_starter.am SUBDIRS = config_files diff --git a/adm_local/unix/config_files/Makefile.am b/adm_local/unix/config_files/Makefile.am index ee5c4d8..6d25f43 100644 --- a/adm_local/unix/config_files/Makefile.am +++ b/adm_local/unix/config_files/Makefile.am @@ -1,21 +1,22 @@ -# Copyright (C) 2004-2008 CEA/DEN, EDF R&D +# Copyright (C) 2004-2012 CEA/DEN, EDF R&D # -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License. +# 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. +# 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 +# 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 +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com # + include $(top_srcdir)/adm_local/unix/make_common_starter.am dist_admlocalm4_DATA = \ diff --git a/adm_local/unix/config_files/check_GHS3D.m4 b/adm_local/unix/config_files/check_GHS3D.m4 index 954a828..cec27b7 100644 --- a/adm_local/unix/config_files/check_GHS3D.m4 +++ b/adm_local/unix/config_files/check_GHS3D.m4 @@ -1,21 +1,22 @@ -dnl Copyright (C) 2004-2008 CEA/DEN, EDF R&D +dnl Copyright (C) 2004-2012 CEA/DEN, EDF R&D dnl -dnl This library is free software; you can redistribute it and/or -dnl modify it under the terms of the GNU Lesser General Public -dnl License as published by the Free Software Foundation; either -dnl version 2.1 of the License. +dnl This library is free software; you can redistribute it and/or +dnl modify it under the terms of the GNU Lesser General Public +dnl License as published by the Free Software Foundation; either +dnl version 2.1 of the License. dnl -dnl This library is distributed in the hope that it will be useful, -dnl but WITHOUT ANY WARRANTY; without even the implied warranty of -dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -dnl Lesser General Public License for more details. +dnl This library is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +dnl Lesser General Public License for more details. dnl -dnl You should have received a copy of the GNU Lesser General Public -dnl License along with this library; if not, write to the Free Software -dnl Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +dnl You should have received a copy of the GNU Lesser General Public +dnl License along with this library; if not, write to the Free Software +dnl Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA dnl -dnl See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +dnl See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com dnl + AC_DEFUN([CHECK_GHS3D],[ GHS3D_ok=no diff --git a/adm_local/unix/config_files/check_GHS3DPLUGIN.m4 b/adm_local/unix/config_files/check_GHS3DPLUGIN.m4 index 5ed3b2d..25f56bd 100755 --- a/adm_local/unix/config_files/check_GHS3DPLUGIN.m4 +++ b/adm_local/unix/config_files/check_GHS3DPLUGIN.m4 @@ -1,21 +1,22 @@ -dnl Copyright (C) 2004-2008 CEA/DEN, EDF R&D +dnl Copyright (C) 2004-2012 CEA/DEN, EDF R&D dnl -dnl This library is free software; you can redistribute it and/or -dnl modify it under the terms of the GNU Lesser General Public -dnl License as published by the Free Software Foundation; either -dnl version 2.1 of the License. +dnl This library is free software; you can redistribute it and/or +dnl modify it under the terms of the GNU Lesser General Public +dnl License as published by the Free Software Foundation; either +dnl version 2.1 of the License. dnl -dnl This library is distributed in the hope that it will be useful, -dnl but WITHOUT ANY WARRANTY; without even the implied warranty of -dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -dnl Lesser General Public License for more details. +dnl This library is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +dnl Lesser General Public License for more details. dnl -dnl You should have received a copy of the GNU Lesser General Public -dnl License along with this library; if not, write to the Free Software -dnl Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +dnl You should have received a copy of the GNU Lesser General Public +dnl License along with this library; if not, write to the Free Software +dnl Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA dnl -dnl See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +dnl See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com dnl + # Check availability of GHS3DPLUGIN binary distribution # # Author : Marc Tajchman (CEA, 2002) diff --git a/adm_local/unix/make_common_starter.am b/adm_local/unix/make_common_starter.am index 27fcce1..694041f 100644 --- a/adm_local/unix/make_common_starter.am +++ b/adm_local/unix/make_common_starter.am @@ -1,21 +1,30 @@ -# Copyright (C) 2004-2008 CEA/DEN, EDF R&D +# Copyright (C) 2004-2012 CEA/DEN, EDF R&D # -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License. +# 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. +# 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 +# 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 +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com # + +# ============================================================ +# The following is to avoid PACKAGE_... env variable +# redefinition compilation warnings +# ============================================================ +# +AM_CXXFLAGS = @KERNEL_CXXFLAGS@ -include SALOMEconfig.h +AM_CPPFLAGS = @KERNEL_CXXFLAGS@ -include SALOMEconfig.h + # ============================================================ # This file defines the common definitions used in several # Makefile. This file must be included, if needed, by the file diff --git a/bin/Makefile.am b/bin/Makefile.am index df80d88..75e88d0 100644 --- a/bin/Makefile.am +++ b/bin/Makefile.am @@ -1,21 +1,22 @@ -# Copyright (C) 2004-2008 CEA/DEN, EDF R&D +# Copyright (C) 2004-2012 CEA/DEN, EDF R&D # -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License. +# 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. +# 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 +# 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 +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com # + # -* Makefile *- # Author : Guillaume Boulant (CSSI) # Module : GHS3DPLUGIN diff --git a/bin/VERSION.in b/bin/VERSION.in index 777656f..735f67e 100755 --- a/bin/VERSION.in +++ b/bin/VERSION.in @@ -1 +1,3 @@ -THIS IS SALOME - GHS3DPLUGIN VERSION: @VERSION@ +[SALOME GHS3DPLUGIN] : @VERSION@ +[DEVELOPMENT] : @VERSION_DEV@ +[DESCRIPTION] : DISTENE TetGen-GHS3d meshing plug-in for SALOME Mesh module diff --git a/build_cmake b/build_cmake new file mode 100755 index 0000000..47bd15c --- /dev/null +++ b/build_cmake @@ -0,0 +1,27 @@ +#!/bin/sh +# Copyright (C) 2004-2012 CEA/DEN, EDF R&D +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License. +# +# 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 +# + +CURRENT_DIR=`pwd` +CONF_DIR=`echo $0 | sed -e "s,[^/]*$,,;s,/$,,;s,^$,.,"` +cd ${CONF_DIR} +python $KERNEL_ROOT_DIR/salome_adm/cmake_files/am2cmake.py --ghs3dplugin +status=$? +cd ${CURRENT_DIR} +exit $status diff --git a/build_cmake.bat b/build_cmake.bat new file mode 100644 index 0000000..5008649 --- /dev/null +++ b/build_cmake.bat @@ -0,0 +1,20 @@ +@REM Copyright (C) 2004-2012 CEA/DEN, EDF R&D +@REM +@REM This library is free software; you can redistribute it and/or +@REM modify it under the terms of the GNU Lesser General Public +@REM License as published by the Free Software Foundation; either +@REM version 2.1 of the License. +@REM +@REM This library is distributed in the hope that it will be useful, +@REM but WITHOUT ANY WARRANTY; without even the implied warranty of +@REM MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +@REM Lesser General Public License for more details. +@REM +@REM You should have received a copy of the GNU Lesser General Public +@REM License along with this library; if not, write to the Free Software +@REM Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +@REM +@REM See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +@REM + +%PYTHONBIN% %KERNEL_ROOT_DIR%\salome_adm\cmake_files\am2cmake.py --ghs3dplugin diff --git a/build_configure b/build_configure index 4d2dd1d..33e1049 100755 --- a/build_configure +++ b/build_configure @@ -1,22 +1,23 @@ #!/bin/bash -# Copyright (C) 2004-2008 CEA/DEN, EDF R&D +# Copyright (C) 2004-2012 CEA/DEN, EDF R&D # -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License. +# 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. +# 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 +# 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 +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com # + # Tool for updating list of .in file for the SALOME project # and regenerating configure script # Author : Marc Tajchman - CEA @@ -25,19 +26,6 @@ # ORIG_DIR=`pwd` CONF_DIR=`echo $0 | sed -e "s,[^/]*$,,;s,/$,,;s,^$,.,"` -GHS3DPLUGIN_WITH_GUI="yes" - -for option -do - case $option in - -with-gui | --with-gui) - GHS3DPLUGIN_WITH_GUI="yes" - break;; - -without-gui | --without-gui | -with-gui=no | --with-gui=no) - GHS3DPLUGIN_WITH_GUI="no" - break;; - esac -done ######################################################################## # Test if the KERNEL_ROOT_DIR is set correctly @@ -54,16 +42,6 @@ fi # exit #fi -######################################################################## -# Test if the GUI_ROOT_DIR is set correctly - -if test ${GHS3DPLUGIN_WITH_GUI} = yes; then - if test ! -d "${GUI_ROOT_DIR}"; then - echo "failed : GUI_ROOT_DIR variable is not correct !" - exit - fi -fi - ######################################################################## # Test if the GEOM_ROOT_DIR is set correctly @@ -92,40 +70,17 @@ cd ${CONF_DIR} ABS_CONF_DIR=`pwd` ####################################################################### -# Update configure.ac script: to set GHS3DPLUGIN_WITH_GUI variable -sed -e s/GHS3DPLUGIN_WITH_GUI=[a-z]*/GHS3DPLUGIN_WITH_GUI=${GHS3DPLUGIN_WITH_GUI}/g configure.ac > configure.tmp -mv -f configure.tmp configure.ac - -mkdir -p salome_adm/unix/config_files -#cp -f ${KERNEL_ROOT_DIR}/salome_adm/unix/config_files/* salome_adm/unix/config_files -#cp -f ${KERNEL_ROOT_DIR}/salome_adm/unix/pythonbe.py salome_adm/unix - -cp -f ${KERNEL_ROOT_DIR}/salome_adm/unix/SALOMEconfig.h.in salome_adm/unix - -#cp -f ${GUI_ROOT_DIR}/adm_local/unix/config_files/* salome_adm/unix/config_files -#cp -f ${MED_ROOT_DIR}/adm_local/unix/config_files/* salome_adm/unix/config_files -#cp -f ${GEOM_ROOT_DIR}/adm_local/unix/config_files/* salome_adm/unix/config_files -#cp -f ${SMESH_ROOT_DIR}/adm_local/unix/config_files/* salome_adm/unix/config_files - -# remove KERNEL deprecated configure files -#for deprecated in ac_cc_warnings.m4 ac_cxx_partial_specialization.m4 \ -# check_mico.m4 config.guess ltmain.sh ac_cxx_bool.m4 ltconfig ac_cxx_typename.m4 \ -# check_pthreads.m4 config.sub libtool.m4 ac_cxx_mutable.m4 missing -# do -# rm -f salome_adm/unix/config_files/${deprecated} -# done - # ____________________________________________________________________ # aclocal creates the aclocal.m4 file from the standard macro and the -# custom macro embedded in the directory salome_adm/unix/config_files +# custom macro embedded in the directory adm_local/unix/config_files # and KERNEL config_files directory. # output: # aclocal.m4 # autom4te.cache (directory) -echo "====================================================== aclocal" +echo "======================================================= aclocal" -if test ${GHS3DPLUGIN_WITH_GUI} = yes; then +if test -d "${GUI_ROOT_DIR}"; then aclocal -I adm_local/unix/config_files \ -I ${KERNEL_ROOT_DIR}/salome_adm/unix/config_files \ -I ${GUI_ROOT_DIR}/adm_local/unix/config_files \ @@ -146,10 +101,10 @@ fi # version. The files are created in the directory specified with the # AC_CONFIG_AUX_DIR() tag (see configure.ac). # output: -# salome_adm/unix/config_files/config.guess -# salome_adm/unix/config_files/config.sub -# salome_adm/unix/config_files/ltmain.sh -#echo "====================================================== libtoolize" +# adm_local/unix/config_files/config.guess +# adm_local/unix/config_files/config.sub +# adm_local/unix/config_files/ltmain.sh +echo "==================================================== libtoolize" libtoolize --force --copy --automake || exit 1 @@ -169,11 +124,11 @@ autoconf # AC_CONFIG_AUX_DIR() tag (see configure.ac). This step also # creates the Makefile.in files from the Makefile.am files. # output: -# salome_adm/unix/config_files/compile -# salome_adm/unix/config_files/depcomp -# salome_adm/unix/config_files/install-sh -# salome_adm/unix/config_files/missing -# salome_adm/unix/config_files/py-compile +# adm_local/unix/config_files/compile +# adm_local/unix/config_files/depcomp +# adm_local/unix/config_files/install-sh +# adm_local/unix/config_files/missing +# adm_local/unix/config_files/py-compile # Makefile.in (from Makefile.am) echo "====================================================== automake" diff --git a/clean_configure b/clean_configure index 6728b2e..891edb9 100755 --- a/clean_configure +++ b/clean_configure @@ -1,32 +1,25 @@ #!/bin/sh -# Copyright (C) 2004-2008 CEA/DEN, EDF R&D +# Copyright (C) 2004-2012 CEA/DEN, EDF R&D # -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License. +# 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. +# 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 +# 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 +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com # + rm -rf autom4te.cache aclocal.m4 configure make_config find . -name "*~" -print -exec rm {} \; find . -name "*.pyc" -print -exec rm {} \; -#exit -# ==================== ON SORT AVANT - -find bin -name Makefile.in | xargs rm -f -find doc -name Makefile.in | xargs rm -f -find idl -name Makefile.in | xargs rm -f -find resources -name Makefile.in | xargs rm -f -find salome_adm -name Makefile.in | xargs rm -f -find src -name Makefile.in | xargs rm -f -rm -f Makefile.in +find . -name Makefile.in | xargs rm -f +( cd adm_local/unix/config_files && rm -f config.* depcomp install-sh l*.m4 ltmain.sh missing py-compile ) diff --git a/configure.ac b/configure.ac index f5c94f7..d39b98b 100644 --- a/configure.ac +++ b/configure.ac @@ -1,21 +1,22 @@ -# Copyright (C) 2004-2008 CEA/DEN, EDF R&D +# Copyright (C) 2004-2012 CEA/DEN, EDF R&D # -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License. +# 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. +# 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 +# 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 +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com # + # PLEASE DO NOT MODIFY configure.in FILE # ALL CHANGES WILL BE DISCARDED BY THE NEXT # build_configure COMMAND @@ -26,14 +27,16 @@ # Modified by : Marc Tajchman (CEA) # Created from configure.in.base # -AC_INIT([Salome2 Project GHS3DPLUGIN module],[5.1.0], [webmaster.salome@opencascade.com], [SalomeGHS3DPLUGIN]) -AC_CONFIG_AUX_DIR(salome_adm/unix/config_files) +AC_INIT([Salome2 Project GHS3DPLUGIN module],[6.5.0], [webmaster.salome@opencascade.com], [SalomeGHS3DPLUGIN]) +AC_CONFIG_AUX_DIR(adm_local/unix/config_files) AC_CANONICAL_HOST AC_CANONICAL_TARGET -AM_INIT_AUTOMAKE +AM_INIT_AUTOMAKE([-Wno-portability]) XVERSION=`echo $VERSION | awk -F. '{printf("0x%02x%02x%02x",$1,$2,$3)}'` AC_SUBST(XVERSION) +VERSION_DEV=1 +AC_SUBST(VERSION_DEV) # set up MODULE_NAME variable for dynamic construction of directories (resources, etc.) MODULE_NAME=ghs3dplugin @@ -78,6 +81,7 @@ echo AC_PROG_MAKE_SET AC_PROG_INSTALL +AC_LOCAL_INSTALL dnl dnl libtool macro check for CC, LD, NM, LN_S, RANLIB, STRIP + pour les librairies dynamiques ! @@ -99,7 +103,7 @@ dnl Fix up the INSTALL macro if it s a relative path. We want the dnl full-path to the binary instead. case "$INSTALL" in *install-sh*) - INSTALL="${KERNEL_ROOT_DIR}/salome_adm/unix/config_files/install-sh -c" + INSTALL="${KERNEL_ROOT_DIR}/adm_local/unix/config_files/install-sh -c" ;; esac @@ -141,7 +145,15 @@ dnl testing MPICH dnl --------------------------------------------- dnl -CHECK_MPICH +dnl CHECK_MPICH + +echo +echo --------------------------------------------- +echo testing MPI +echo --------------------------------------------- +echo + +CHECK_MPI echo echo --------------------------------------------- @@ -217,11 +229,34 @@ AC_SUBST_FILE(CORBA) corba=make_$ORB CORBA=adm_local/unix/$corba -GHS3DPLUGIN_WITH_GUI=yes +echo +echo --------------------------------------------- +echo Testing GUI +echo --------------------------------------------- +echo + +CHECK_GUI_MODULE + +gui_ok=no +if test "${SalomeGUI_need}" != "no" -a "${FullGUI_ok}" = "yes" ; then + gui_ok=yes +fi -AM_CONDITIONAL(GHS3DPLUGIN_ENABLE_GUI, [test "${GHS3DPLUGIN_WITH_GUI}" = "yes"]) +AM_CONDITIONAL(GHS3DPLUGIN_ENABLE_GUI, [test "${gui_ok}" = "yes"]) + +if test "${SalomeGUI_need}" == "yes"; then + if test "${FullGUI_ok}" != "yes"; then + AC_MSG_WARN(For configure GHS3DPLUGIN module necessary full GUI!) + fi +elif test "${SalomeGUI_need}" == "auto"; then + if test "${FullGUI_ok}" != "yes"; then + AC_MSG_WARN(Full GUI not found. Build will be done without GUI!) + fi +elif test "${SalomeGUI_need}" == "no"; then + echo Build without GUI option has been chosen +fi -if test "${GHS3DPLUGIN_WITH_GUI}" = "yes"; then +if test "${gui_ok}" = "yes"; then echo echo --------------------------------------------- @@ -238,35 +273,15 @@ if test "${GHS3DPLUGIN_WITH_GUI}" = "yes"; then echo CHECK_QT +fi - echo - echo --------------------------------------------- - echo testing VTK - echo --------------------------------------------- - echo - - CHECK_VTK - - echo - echo --------------------------------------------- - echo Testing GUI - echo --------------------------------------------- - echo - - CHECK_SALOME_GUI - - echo - echo --------------------------------------------- - echo Testing full GUI - echo --------------------------------------------- - echo +echo +echo --------------------------------------------- +echo testing VTK +echo --------------------------------------------- +echo - CHECK_CORBA_IN_GUI - if test "x${CORBA_IN_GUI}" != "xyes"; then - echo "failed : For configure GHS3DPLUGIN module necessary full GUI !" - exit - fi -fi +CHECK_VTK echo echo --------------------------------------------- @@ -339,6 +354,13 @@ echo --------------------------------------------- echo CHECK_GHS3D +if test "${GHS3D_ok}" = "yes"; then + if test "x$GHS3D_VERSION" = "x" + then + GHS3D_VERSION=`ghs3d -u |grep "TETMESH-GHS3D SOFTWARE"|awk '{print $3}'|awk -F- '{print $1}'|awk -F. '{print $1$2}'` + fi + AC_DEFINE_UNQUOTED(GHS3D_VERSION,${GHS3D_VERSION}) +fi echo echo --------------------------------------------- @@ -347,12 +369,14 @@ echo --------------------------------------------- echo echo Configure -if test "${GHS3DPLUGIN_WITH_GUI}" = "yes"; then -variables="cc_ok boost_ok threads_ok omniORB_ok occ_ok doxygen_ok Kernel_ok Geom_ok Med_ok SMesh_ok GHS3D_ok OpenGL_ok qt_ok vtk_ok" -fi -if test "${GHS3DPLUGIN_WITH_GUI}" = "no"; then -variables="cc_ok boost_ok threads_ok omniORB_ok occ_ok doxygen_ok Kernel_ok Geom_ok Med_ok SMesh_ok GHS3D_ok" +if test "${gui_ok}" = "yes"; then + variables="cc_ok boost_ok threads_ok omniORB_ok occ_ok doxygen_ok Kernel_ok gui_ok Geom_ok Med_ok SMesh_ok GHS3D_ok OpenGL_ok qt_ok vtk_ok" +elif test "${SalomeGUI_need}" != "no"; then + variables="cc_ok boost_ok threads_ok omniORB_ok occ_ok doxygen_ok Kernel_ok gui_ok Geom_ok Med_ok SMesh_ok GHS3D_ok vtk_ok" +else + variables="cc_ok boost_ok threads_ok omniORB_ok occ_ok doxygen_ok Kernel_ok Geom_ok Med_ok SMesh_ok GHS3D_ok vtk_ok" fi + for var in $variables do printf " %10s : " `echo \$var | sed -e "s,_ok,,"` @@ -370,6 +394,10 @@ if test "X$GMAKE" = "Xyes"; then else AC_SUBST(SETX) SETX="set -x" fi + +dnl Build with SMESH cancel compute feature +AC_DEFINE(WITH_SMESH_CANCEL_COMPUTE) + echo echo --------------------------------------------- echo generating Makefiles and configure files @@ -380,21 +408,40 @@ AC_OUTPUT_COMMANDS([ \ chmod +x ./bin/*; \ ]) +AC_HACK_LIBTOOL +AC_CONFIG_COMMANDS([hack_libtool],[ +sed -i "s%^CC=\"\(.*\)\"%hack_libtool (){ \n\ + $(pwd)/hack_libtool \1 \"\$[@]\" \n\ +}\n\ +CC=\"hack_libtool\"%g" libtool +sed -i "s%\(\s*\)for searchdir in \$newlib_search_path \$lib_search_path \$sys_lib_search_path \$shlib_search_path; do%\1searchdirs=\"\$newlib_search_path \$lib_search_path \$sys_lib_search_path \$shlib_search_path\"\n\1for searchdir in \$searchdirs; do%g" libtool +sed -i "s%\(\s*\)searchdirs=\"\$newlib_search_path \$lib_search_path \(.*\)\"%\1searchdirs=\"\$newlib_search_path \$lib_search_path\"\n\1sss_beg=\"\"\n\1sss_end=\"\2\"%g" libtool +sed -i "s%\(\s*\)\(for searchdir in \$searchdirs; do\)%\1for sss in \$searchdirs; do\n\1 if ! test -d \$sss; then continue; fi\n\1 ssss=\$(cd \$sss; pwd)\n\1 if test \"\$ssss\" != \"\" \&\& test -d \$ssss; then\n\1 case \$ssss in\n\1 /usr/lib | /usr/lib64 ) ;;\n\1 * ) sss_beg=\"\$sss_beg \$ssss\" ;;\n\1 esac\n\1 fi\n\1done\n\1searchdirs=\"\$sss_beg \$sss_end\"\n\1\2%g" libtool +],[]) + # This list is initiated using autoscan and must be updated manually # when adding a new file .in to manage. When you execute # autoscan, the Makefile list is generated in the output file configure.scan. # This could be helpfull to update de configuration. AC_OUTPUT([ \ - ./salome_adm/unix/SALOMEconfig.h \ - ./adm_local/Makefile \ - ./adm_local/unix/Makefile \ - ./adm_local/unix/config_files/Makefile \ - ./bin/VERSION \ - ./bin/Makefile \ - ./GHS3DPLUGIN_version.h \ - ./src/Makefile \ - ./src/GUI/Makefile \ - ./resources/Makefile \ - ./idl/Makefile \ + adm_local/Makefile \ + adm_local/unix/Makefile \ + adm_local/unix/config_files/Makefile \ + bin/VERSION \ + bin/Makefile \ + GHS3DPLUGIN_version.h \ + doc/Makefile \ + doc/salome/Makefile \ + doc/salome/gui/Makefile \ + doc/salome/gui/GHS3DPLUGIN/Makefile \ + doc/salome/gui/GHS3DPLUGIN/doxyfile \ + doc/salome/gui/GHS3DPLUGIN/doxyfile_py \ + doc/salome/gui/GHS3DPLUGIN/static/header.html \ + doc/salome/gui/GHS3DPLUGIN/static/header_py.html \ + src/Makefile \ + src/GUI/Makefile \ + src/GHS3DPlugin/Makefile \ + resources/Makefile \ + idl/Makefile \ Makefile \ ]) diff --git a/doc/Makefile.am b/doc/Makefile.am new file mode 100644 index 0000000..2599845 --- /dev/null +++ b/doc/Makefile.am @@ -0,0 +1,24 @@ +# 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 +# +SUBDIRS = salome + +usr_docs: + (cd salome && $(MAKE) $(AM_MAKEFLAGS) usr_docs) + +docs: usr_docs diff --git a/doc/salome/Makefile.am b/doc/salome/Makefile.am new file mode 100644 index 0000000..15038d3 --- /dev/null +++ b/doc/salome/Makefile.am @@ -0,0 +1,28 @@ +# 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 +# + +SUBDIRS = gui +SUBDIRSGUI = gui + +usr_docs: + @@SETX@; for d in $(SUBDIRSGUI); do \ + (cd $$d && $(MAKE) $@) || exit 1; \ + done; + +docs: usr_docs \ No newline at end of file diff --git a/doc/salome/gui/GHS3DPLUGIN/Makefile.am b/doc/salome/gui/GHS3DPLUGIN/Makefile.am new file mode 100755 index 0000000..dfe458e --- /dev/null +++ b/doc/salome/gui/GHS3DPLUGIN/Makefile.am @@ -0,0 +1,62 @@ +# 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 + +EXTRA_DIST += images input static/footer.html static/doxygen.css + +guidocdir = $(docdir)/gui/GHS3DPLUGIN +guidoc_DATA = images/head.png + + +usr_docs: doxyfile + echo "===========================================" ; \ + echo "Generating Python interface documentation"; \ + echo "===========================================" ; \ + $(DOXYGEN) doxyfile_py \ + echo "===========================================" ; \ + echo "Generating GUI documentation" ; \ + echo "===========================================" ; \ + $(DOXYGEN) doxyfile ; + +docs: usr_docs + +clean-local: + @for filen in `find . -maxdepth 1` ; do \ + case $${filen} in \ + ./Makefile | ./doxyfile | ./doxyfile_py ) ;; \ + . | .. | ./static ) ;; \ + *) echo "Removing $${filen}" ; rm -rf $${filen} ;; \ + esac ; \ + done ; + +install-data-local: usr_docs + $(INSTALL) -d $(DESTDIR)$(docdir)/gui/GHS3DPLUGIN + @for filen in `find . -maxdepth 1` ; do \ + case $${filen} in \ + ./Makefile | ./doxyfile | ./doxyfile_py ) ;; \ + ./doxyfile.bak | ./doxyfile_py.bak ) ;; \ + . | .. | ./static ) ;; \ + *) echo "Installing $${filen}" ; cp -rp $${filen} $(DESTDIR)$(docdir)/gui/GHS3DPLUGIN ;; \ + esac ; \ + done ; + cp -rp $(srcdir)/images/head.png $(DESTDIR)$(docdir)/gui/GHS3DPLUGIN/ghs3dpluginpy_doc/ ; + +uninstall-local: + rm -rf $(DESTDIR)$(docdir)/gui/GHS3DPLUGIN + diff --git a/doc/salome/gui/GHS3DPLUGIN/doxyfile.in b/doc/salome/gui/GHS3DPLUGIN/doxyfile.in new file mode 100755 index 0000000..7af64c9 --- /dev/null +++ b/doc/salome/gui/GHS3DPLUGIN/doxyfile.in @@ -0,0 +1,81 @@ +# 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 +# + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- +PROJECT_NAME = "SALOME GHS3DPLUGIN User's Guide" +OUTPUT_DIRECTORY = . +CREATE_SUBDIRS = NO +OUTPUT_LANGUAGE = English +TAB_SIZE = 5 + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- +QUIET = NO +WARNINGS = YES + +#--------------------------------------------------------------------------- +#Input related options +#--------------------------------------------------------------------------- +INPUT = @srcdir@/input +FILE_PATTERNS = *.doc +EXCLUDE = +IMAGE_PATH = @srcdir@/images +EXAMPLE_PATH = + +#--------------------------------------------------------------------------- +#HTML related options +#--------------------------------------------------------------------------- +GENERATE_HTML = YES +HTML_OUTPUT = . +HTML_HEADER = @builddir@/static/header.html +HTML_FOOTER = @srcdir@/static/footer.html +HTML_STYLESHEET = @srcdir@/static/doxygen.css +TOC_EXPAND = YES +DISABLE_INDEX = NO +GENERATE_TREEVIEW = YES +TREEVIEW_WIDTH = 300 + +#--------------------------------------------------------------------------- +#SORT related options +#--------------------------------------------------------------------------- +SORT_GROUP_NAMES = NO + + +#--------------------------------------------------------------------------- +#LaTeX related option +#--------------------------------------------------------------------------- +GENERATE_LATEX = NO +EXTRA_PACKAGES = amsmath + +#--------------------------------------------------------------------------- +#RTF related options +#--------------------------------------------------------------------------- +GENERATE_RTF = NO + +#--------------------------------------------------------------------------- +#External reference options +#--------------------------------------------------------------------------- + +#rnv: 07.04.2011 Workaround for the doxygen 1.7.3: +#because it wrongly defines location of the html files for search. +TAGFILES = ghs3dpluginpy_doc.tag=../GHS3DPLUGIN/ghs3dpluginpy_doc +SEARCHENGINE = YES \ No newline at end of file diff --git a/doc/salome/gui/GHS3DPLUGIN/doxyfile_py.in b/doc/salome/gui/GHS3DPLUGIN/doxyfile_py.in new file mode 100755 index 0000000..47082b5 --- /dev/null +++ b/doc/salome/gui/GHS3DPLUGIN/doxyfile_py.in @@ -0,0 +1,159 @@ +# 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 +# + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- +PROJECT_NAME = "SALOME GHS3DPLUGIN User's Guide" +OUTPUT_DIRECTORY = . +CREATE_SUBDIRS = NO +OUTPUT_LANGUAGE = English +USE_WINDOWS_ENCODING = NO +BRIEF_MEMBER_DESC = YES +REPEAT_BRIEF = YES +ALWAYS_DETAILED_SEC = YES +INLINE_INHERITED_MEMB = YES +FULL_PATH_NAMES = NO +SHORT_NAMES = NO +JAVADOC_AUTOBRIEF = YES +MULTILINE_CPP_IS_BRIEF = NO +DETAILS_AT_TOP = NO +INHERIT_DOCS = YES +SEPARATE_MEMBER_PAGES = NO +TAB_SIZE = 5 +OPTIMIZE_OUTPUT_FOR_C = YES +OPTIMIZE_OUTPUT_JAVA = YES +BUILTIN_STL_SUPPORT = NO +DISTRIBUTE_GROUP_DOC = NO +SUBGROUPING = YES + +#--------------------------------------------------------------------------- +# Build related options +#--------------------------------------------------------------------------- +EXTRACT_ALL = YES +EXTRACT_PRIVATE = YES +EXTRACT_STATIC = NO +EXTRACT_LOCAL_CLASSES = YES +EXTRACT_LOCAL_METHODS = NO +HIDE_UNDOC_MEMBERS = NO +HIDE_UNDOC_CLASSES = NO +HIDE_FRIEND_COMPOUNDS = NO +HIDE_IN_BODY_DOCS = NO +INTERNAL_DOCS = YES +CASE_SENSE_NAMES = YES +HIDE_SCOPE_NAMES = YES +SHOW_INCLUDE_FILES = YES +INLINE_INFO = YES +SORT_MEMBER_DOCS = NO +SORT_BRIEF_DOCS = NO +SORT_BY_SCOPE_NAME = NO +GENERATE_TODOLIST = YES +GENERATE_TESTLIST = YES +GENERATE_BUGLIST = YES +GENERATE_DEPRECATEDLIST= YES +MAX_INITIALIZER_LINES = 25 +SHOW_USED_FILES = NO +SHOW_DIRECTORIES = NO + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- +SOURCE_BROWSER = NO +INLINE_SOURCES = NO +STRIP_CODE_COMMENTS = YES +REFERENCED_BY_RELATION = NO +REFERENCES_RELATION = YES +USE_HTAGS = NO +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- +QUIET = NO +WARNINGS = YES +WARN_IF_UNDOCUMENTED = YES +WARN_IF_DOC_ERROR = YES +WARN_NO_PARAMDOC = NO +EXCLUDE_SYMLINKS = NO +EXAMPLE_RECURSIVE = NO + +#--------------------------------------------------------------------------- +#Input related options +#--------------------------------------------------------------------------- +INPUT = @top_srcdir@/src/GHS3DPlugin/GHS3DPluginDC.py +FILE_PATTERNS = +IMAGE_PATH = @srcdir@/images +RECURSIVE = NO +EXAMPLE_PATH = + +#--------------------------------------------------------------------------- +#HTML related options +#--------------------------------------------------------------------------- +GENERATE_HTML = YES +HTML_OUTPUT = ghs3dpluginpy_doc +HTML_HEADER = @builddir@/static/header_py.html +HTML_FOOTER = @srcdir@/static/footer.html +HTML_STYLESHEET = @srcdir@/static/doxygen.css +TOC_EXPAND = YES +DISABLE_INDEX = NO +GENERATE_TREEVIEW = NO + +#--------------------------------------------------------------------------- +#LaTeX related option +#--------------------------------------------------------------------------- +GENERATE_LATEX = NO + +#--------------------------------------------------------------------------- +#RTF related options +#--------------------------------------------------------------------------- +GENERATE_RTF = NO + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- +CLASS_DIAGRAMS = NO +HIDE_UNDOC_RELATIONS = NO +HAVE_DOT = NO +CLASS_GRAPH = NO +COLLABORATION_GRAPH = NO +GROUP_GRAPHS = NO +UML_LOOK = NO +TEMPLATE_RELATIONS = NO +INCLUDE_GRAPH = NO +INCLUDED_BY_GRAPH = NO +CALL_GRAPH = NO +GRAPHICAL_HIERARCHY = NO +DIRECTORY_GRAPH = NO +DOT_IMAGE_FORMAT = jpg +DOT_FONTNAME = Arial +DOT_PATH = +DOTFILE_DIRS = +MAX_DOT_GRAPH_WIDTH = 1024 +MAX_DOT_GRAPH_HEIGHT = 1200 +MAX_DOT_GRAPH_DEPTH = 0 +DOT_TRANSPARENT = NO +DOT_MULTI_TARGETS = NO +GENERATE_LEGEND = NO +DOT_CLEANUP = YES + +#--------------------------------------------------------------------------- +#External reference options +#--------------------------------------------------------------------------- +GENERATE_TAGFILE = ghs3dpluginpy_doc.tag +SEARCHENGINE = YES \ No newline at end of file diff --git a/doc/salome/gui/GHS3DPLUGIN/images/ghs3d_enforced_meshes.png b/doc/salome/gui/GHS3DPLUGIN/images/ghs3d_enforced_meshes.png new file mode 100644 index 0000000000000000000000000000000000000000..9ddc0127df92bf99b76244a00271ff76cabfa8c2 GIT binary patch literal 32993 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 Wq100DFUN3rl(M3lLg5XQ!2bghwoVrS literal 0 HcmV?d00001 diff --git a/doc/salome/gui/GHS3DPLUGIN/images/ghs3d_enforced_vertices.png b/doc/salome/gui/GHS3DPLUGIN/images/ghs3d_enforced_vertices.png new file mode 100644 index 0000000000000000000000000000000000000000..d3a4bbcfa49c2ddd8d28f288c594bb7a5d207735 GIT binary patch literal 33075 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 literal 0 HcmV?d00001 diff --git a/doc/salome/gui/GHS3DPLUGIN/images/ghs3d_parameters_basic.png b/doc/salome/gui/GHS3DPLUGIN/images/ghs3d_parameters_basic.png new file mode 100644 index 0000000000000000000000000000000000000000..9519c1461d3734447fd669b37a63f7fea55d83cf GIT binary patch literal 25962 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 UNr5qaLEo(?t143>^)m3k062y4DgXcg literal 0 HcmV?d00001 diff --git a/doc/salome/gui/GHS3DPLUGIN/images/ghs3d_screenshot.png b/doc/salome/gui/GHS3DPLUGIN/images/ghs3d_screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..a9e7b972bea1c7ff415490d07669a390525a9a8b GIT binary patch literal 69709 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%0AKf6fJe<4r> zAz9jDJVGke?)O0Q(aD^08%UqBJ3#Y$({zB*f@{tnotWMg1E}~~rn`swP>h~aJgg4c z)xQlqWq0%GlHN=ybF8g)^##wK|4^d-Li)x#XSIZW5^IO!=#yu7=HqgPtkRGdf8*d+Dc!&*<#J40}G^cej^ zr(<_c09^CFJOmT61 zan}acl@##$*~@HOSHX$aQCw~>2W#yF!x3`R%v^5k)7B2}I6)o+Mw5x`)Fcpsb*pn& zZMEFh8g0bm<8p^~TKxEw5C3!!izSH{ixZis|Cr-%za@`PlB9bq`5**s&-`JuHr($a zw+l*3g8_K$tk{iU>o-Q9EK*nymGOF z-Iax;n-dsvO>ykgRziUgiOC5hnv56?dUjOUNHQ5Q8ucW`8Bqi@^o`Q%oFpOy-OfqW zTSYXt29K&B!;;LwJUtiw-@nk+)fMX>nItVqPec%cb{gSkAP%h^_e`uWNRqfa3_rBm z?q91@1t3Vbm|2};Ws|*-#CQ{q;W4&Xm9nnX#>vKB4%C!#`bH-w8yr;TXQBY<=0uX? zjLfJimpTUU1wwfIA-YE9*zi8b`r&qaJ{6{E&i>;2G6W@Q0Z&X2-m)ESgm?lOhSJht zKwC4ME}th1;dTY5qF_l%U}Hrw+bWBBrnZu8m8HCOrG@&gAzZ!yO?}#exMO63;mPPB z)X_j?k*C=2F3ZK*dyz|L-=}|YFxEdJNm|mLxF7^A3^UOBYtL2pHdkZ+C-NJWo)}sf zCg3gK&N*wr!VPGmTN?B_g{Rlq`O<;i{ME0{5DZ6%2!Xh@hWD_o(}X~;H?X5Li=>-p zc<<;N+CE1~k`}bYJIl=N0$OkFZvmxqd_4#FuRwhC>;D7DjP*rJ%UT$CFXSh$^%FLX z1wdKgqopXIQ-}yb&&W7!gHEOcLBgu4tuyL%+U+4jFw>IEH@B`Px#g@3K}mWDOMD;U z{5}C3z&^AzZ@c4bqd*hzCA0v%4vfe8f~93I0(>0uvA1;?2b*wNoe!Lb&?yQ!-6Q@! zs%l3n9mtAs{Gb1Z-rhdc2lYgiBx%+X?<}*hX`m0S30nZTRYD-pg71H#h2oEp)1uPn z!vlCCz3g=-FpyA;KgqYiy%kh7LRC>deeM9$f#5^8PSYt0<@uTHObznEt3RZ-uV22` zCFvnOkyE30ngosmThUHrN(8FVrbJyp5s)A2itcA&v2-%j*KxYw^yz2p@3(~ zM{5C;`|1zr9~g-Bw=PLfq$hT2^iGq&?|@q1Z-9+xqs1Sg zRhYhvHaZN)`a-1@qYD)!c$R}5Gn_~+#ua~i)B9a+{qw^-d9?a;uRRB)?gT$Q{*Igq zm83_oEP@cU6U9To*8wxy#`|-CAJ~ajWjYe;i3f;_8*y=i`$fAzn)cD?R)HycTk{$NjZvCO@CfiuyY z2kjvHPmvq%rPxUa{t;Lo31e2nY@QsVGd>wdQmS?bMPViqrnaJl8@;3RC!&D-%vAQK z`Z@W^_i69wjPY1F|ov6kB_Na&Es5Z8Jf>*LIO_m=dW=%>fZ% z#N{T_oG@<)8gx1iR_0*~kMP@n{XU~kXRN<1Nm^ExT@c<$7RN}jln7L!ZRH7~jSlsI zZ6?4s`kVRdBnuux96CioFn3!vgI>>p@@%Fryur^tJVPKDiuJc8Nz2Z%4nj$ar2z0I z+APIhv;kil+K28d&Taxa9e-Q81y#ADbab{qpulP|v#r2_=lq*|bo!)R50s?GL=o@&d$V1j{f8yx!K$- zJH<%SV)({hc)zgzGHR~Cha8Xc@LzQuo6F>hU<1W`D{Ew0( zEtWi;NRmEhCg4TjYiQk&5&`z?;o`sm$Ky==dSH-=iHTTWrX;NxG6*Fp2J~nZrQZRb zMk}J31bz+t6WTFjk|cdT2Z@mC`n652)KsUKzz9>mr=492VBrQ>P;7@_K&?-tj zXnjj1N&0NbAe5vfECnb6R-vsU%EOl=>9Z$;P?DYi@`EZ#kB|I(Ns=T literal 0 HcmV?d00001 diff --git a/doc/salome/gui/GHS3DPLUGIN/images/ghs3d_screenshot_enf1.png b/doc/salome/gui/GHS3DPLUGIN/images/ghs3d_screenshot_enf1.png new file mode 100644 index 0000000000000000000000000000000000000000..8923f007ae391b938d8917df97678c299307124c GIT binary patch literal 89248 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 z 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 literal 0 HcmV?d00001 diff --git a/doc/salome/gui/GHS3DPLUGIN/images/ghs3d_screenshot_enf4.png b/doc/salome/gui/GHS3DPLUGIN/images/ghs3d_screenshot_enf4.png new file mode 100644 index 0000000000000000000000000000000000000000..46f12d83cc9b0371eadf943292cb4bffce142b66 GIT binary patch literal 64362 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℘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 R@dJNAQc=*5uY#KU{|_1QxY7Us literal 0 HcmV?d00001 diff --git a/doc/salome/gui/GHS3DPLUGIN/images/head.png b/doc/salome/gui/GHS3DPLUGIN/images/head.png new file mode 100755 index 0000000000000000000000000000000000000000..307d9ef9a4c07f8fba2c8721309a978433bcf63c GIT binary patch literal 78545 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 D4zrO! literal 0 HcmV?d00001 diff --git a/doc/salome/gui/GHS3DPLUGIN/images/image2.gif b/doc/salome/gui/GHS3DPLUGIN/images/image2.gif new file mode 100755 index 0000000000000000000000000000000000000000..198351307f7783f5771a22bb6ea363dea50a10e8 GIT binary patch literal 4694 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 BV)+07 literal 0 HcmV?d00001 diff --git a/doc/salome/gui/GHS3DPLUGIN/input/additional_hypo.doc b/doc/salome/gui/GHS3DPLUGIN/input/additional_hypo.doc new file mode 100644 index 0000000..90873f2 --- /dev/null +++ b/doc/salome/gui/GHS3DPLUGIN/input/additional_hypo.doc @@ -0,0 +1,18 @@ +/*! + +\page additional_hypo_page Additional Hypotheses + +\n Additional Hypotheses can be applied as a supplement to the +main hypotheses, introducing additional concepts to mesh creation. + +One additional hypotheses can be used together with GHS3D algoritm: +

+ +For more detailed description of the this additional hypothesis please refer SALOME Mesh User's Guide. +*/ diff --git a/doc/salome/gui/GHS3DPLUGIN/input/ghs3d_hypo.doc b/doc/salome/gui/GHS3DPLUGIN/input/ghs3d_hypo.doc new file mode 100644 index 0000000..4c4ce5f --- /dev/null +++ b/doc/salome/gui/GHS3DPLUGIN/input/ghs3d_hypo.doc @@ -0,0 +1,180 @@ +/*! + +\page ghs3d_hypo_page GHS3D Parameters hypothesis + +\anchor ghs3d_top +\n GHS3D Parameters hypothesis works only with Tetrahedron (GHS3D) +algorithm. This algorithm is a commercial software. +\n To get a licence, visit http://www.distene.com/corp/eval-distene.html + +-# \ref ghs3d_general_parameters +-# \ref ghs3d_advanced_parameters +-# \ref ghs3d_enforced_vertices +-# \ref ghs3d_enforced_meshes + +\section ghs3d_general_parameters General parameters + +\image html ghs3d_parameters_basic.png + +
    +
  • Name - allows to define the name of the hypothesis (GHS3D +Parameters by default).
  • + +
  • To mesh holes - if checked, the algorithm will +create mesh in the holes inside a solid shape, else only the outermost +shape will be meshed. Volumic elements created within holes are bound +to the solid.
  • + +
  • Optimization level - allows choosing the required +optimization level: +
      +
    • none,
    • +
    • light,
    • +
    • medium (standard),
    • +
    • standard+,
    • +
    • strong.
    • +
    +Higher level of +optimisation provides better mesh, but can be time-consuming. +
  • +
+ +\ref ghs3d_top "Back to top" + +\section ghs3d_advanced_parameters Advanced parameters + +\image html ghs3d_parameters_advanced.png + +
  • Maximum memory size - launches ghs3d software with +work space limited to the specified amount of RAM, in Mbytes. If this option is +checked off, the software will be launched with 7O% of the total RAM space.
  • + +
  • Initial memory size - starts ghs3d software with +the specified amount of work space, in Mbytes. If this option is checked off, the +software will be started with 100 Megabytes of working space.
  • + +
  • Working directory - allows defining the folder for input and output +files of ghs3d software, which are the files starting with "GHS3D_" prefix.
  • + +
  • Keep working files - allows checking input and output files +of ghs3d software, while usually these files are removed after the +launch of the mesher.
  • + +
  • Verbose level - to choose verbosity level in the range from +0 to 10. +
    • 0, no standard output, +
    • 2, prints the data, quality statistics of the skin and final +meshes and indicates when the final mesh is being saved. In addition +the software gives indication regarding the CPU time. +
    • 10, same as 2 plus the main steps in the computation, quality +statistics histogram of the skin mesh, quality statistics histogram +together with the characteristics of the final mesh. +
  • + +
  • To create new nodes - if this option is checked off, ghs3d +tries to create tetrahedrons using only the nodes of the 2D mesh.
  • + +
  • To remove the initial central point TetMesh-GHS3D adds an internal point +at the gravity centre of the bounding box to speed up and to simplify +the meshing process. However, it is possible to refrain from creating +this point by using the command line option -no initial central point. This can be +particularly useful to generate a volume mesh without internal points at all and in some rare cases +at the boundary regeneration phase when it is impossible to proceed +with the standard options +(for example, when one dimension of the domain is more than 20 times greater than the other two). +Use this option if the boundary regeneration has failed with the standard parameters and before using +the recovery version (command line option -C). +Note: when using this option, the speed of the meshing process may +decrease, and the quality may change. +Note: the boundary regeneration may fail with this option, in some rare cases.
  • + +
  • To use boundary recovery version - enables using a +boundary recovery module which tries to +create volume meshes starting from very poor quality surface meshes +(almost flat triangles on the surface, high density propagation, +extreme aspect ratios, etc.) which fails with the standard version. The +resulting volume mesh will however most likely have a very poor +quality (poor aspect ratio of elements, tetrahedra with a very small +positive volume).
  • + +
  • To use FEM correction - Applies finite-element correction by +replacing overconstrained elements where it is possible. At first the process +slices the overconstrained edges and at second the overconstrained +facets. This ensures that there are no edges with two boundary +vertices and that there are no facets with three boundary vertices. TetMesh-GHS3D gives the initial +and final overconstrained edges and facets. It also gives the facets +which have three edges on the boundary. +Note: when using this option, the speed of the meshing process may +decrease, quality may change, and the smallest volume may be smaller. +By default, the FEM correction is not used.
  • + +
  • Option as text - allows to input in the command line any text +for ghs3d, for example, advanced options.
  • + + + +\ref ghs3d_top "Back to top" + +\section ghs3d_enforced_vertices Enforced vertices + +\note This feature is currently available only on meshes with no +geometry attached. Such meshes can be obtained by +
      +
    • Copying an existing mesh
    • +
    • Importing a mesh from file
    • +
    • Applying a transformation to a mesh a get result in a new mesh
    • +
    + +\image html ghs3d_enforced_vertices.png + +GHS3D algorithm can locally make the mesh finer. It is possible to +define enforced vertices in the volume where the mesh will be detailed. +A node will be created at the enforced vertex coordinates. + +An enforced vertex is defined by: +
      +
    • A vertex
    • +
        +
      • from GEOM (Vertex, Compound)
      • +
      • or from (x,y,z) cartesian coordinates
      • +
      +
    • A constant physical size
    • +
    • If a group name is given, the created node will be added to the +group. If the group does not exist, it is created.
    • +
    +\ref ghs3d_top "Back to top" + +\section ghs3d_enforced_meshes Enforced Meshes + +\note This feature is currently only available on 2D meshes with no +geometry attached. Such meshes can be obtained by +
      +
    • Copying an existing 2D mesh
    • +
    • Importing a 2D mesh from file
    • +
    • Applying a transformation to a 2D mesh a get result in a new mesh
    • +
    + +\image html ghs3d_enforced_meshes.png + +GHS3D algorithm can be forced by other meshes, sub-meshes or +groups. The constraint elements should be contained +entirely into the solid mesh. +
      +
    • The constraint element types are: +
        +
      • NODE
      • +
      • EDGE
      • +
      • FACE
      • +
    • +
    • If a size is given, the mesh will be refined around the enforced +elements given the size (not available yet)
    • +
    • If a group name is given, the enforced elements will be added to +the group. If the group does not exist, it is created.
    • +
    + +
    See Also a sample TUI Script of the \ref tui_ghs3d "creation of a Ghs3D hypothesis", including enforced vertices and meshes. + +\ref ghs3d_top "Back to top" + + +*/ diff --git a/doc/salome/gui/GHS3DPLUGIN/input/ghs3dplugin_python_interface.doc b/doc/salome/gui/GHS3DPLUGIN/input/ghs3dplugin_python_interface.doc new file mode 100644 index 0000000..09825c1 --- /dev/null +++ b/doc/salome/gui/GHS3DPLUGIN/input/ghs3dplugin_python_interface.doc @@ -0,0 +1,240 @@ +/*! + +\page ghs3dplugin_python_interface_page Python Interface + +Python package \ref GHS3DPluginDC "GHS3DPlugin" defines several classes, destined for creation of the 3D meshes. + +Documentation for GHS3DPlugin package is available in linear form grouped by classes, declared in the GHS3DPluginDC.py file. + +Below you can see an example of usage of the GHS3DPlugin package for mesh generation: + +\anchor tui_ghs3d + +
      +
    1. \ref tui_ghs3d_basic "Construction of Mesh using Ghs3D algorithm"
    2. +
    3. \ref tui_ghs3d_enforced_vertices "Adding enforced vertices"
    4. +
    5. \ref tui_ghs3d_enforced_meshes "Adding enforced mesh"
    6. +
    + +\anchor tui_ghs3d_basic +

    Construction of Mesh using Ghs3D algorithm

    + +\code +import geompy +import smesh +import BLSURFPlugin +import GHS3DPlugin + +# create a box +box = geompy.MakeBoxDXDYDZ(200., 200., 200.) +geompy.addToStudy(box, "box") + +# create a mesh on the box +ghs3dMesh = smesh.Mesh(box,"box: Ghs3D and BLSurf mesh") + +# create a BLSurf algorithm for faces +BLSURF = ghs3dMesh.Triangle(algo=smesh.BLSURF) +GHS3D = ghs3dMesh.Tetrahedron(algo=smesh.GHS3D) + +# compute the mesh +ghs3dMesh.Compute() + +# End of script +\endcode + +\image html ghs3d_screenshot.png Ghs3d mesh withtout hypothesis + +\ref tui_ghs3d "Back to top" + +\anchor tui_ghs3d_enforced_vertices +

    Adding enforced vertices

    + +\code + +# An enforced vertex can be added via: +# - the coordinates x,y,z +# - a GEOM vertex or compound (No geometry, TUI only) +# +# The created enforced nodes can also be stored in +# a group. +# +# This feature is available only on meshes without geometry. + +# Ex1: Add one enforced vertex with coordinates (50,50,100) +# and physical size 2. + +import geompy +import smesh +import BLSURFPlugin +import GHS3DPlugin + +# create a box +box = geompy.MakeBoxDXDYDZ(200., 200., 200.) +geompy.addToStudy(box, "box") +# create a mesh on the box +ghs3dMesh = smesh.Mesh(box,"box: Ghs3D and BLSurf mesh") +# create a BLSurf algorithm for faces +ghs3dMesh.Triangle(algo=smesh.BLSURF) +# compute the mesh +ghs3dMesh.Compute() + +# Make a copy of the 2D mesh +ghs3dMesh_wo_geometry = smesh.CopyMesh( ghs3dMesh, 'Ghs3D wo geometry', 0, 0) + +# create a Ghs3D algorithm and hypothesis and assign them to the mesh +GHS3D = smesh.CreateHypothesis('GHS3D_3D', 'GHS3DEngine') +GHS3D_Parameters = smesh.CreateHypothesis('GHS3D_Parameters', 'GHS3DEngine') +ghs3dMesh.AddHypothesis( GHS3D ) +ghs3dMesh.AddHypothesis( GHS3D_Parameters ) +# Create the enforced vertex +GHS3D_Parameters.SetEnforcedVertex( 50, 50, 100, 2) # no group +# Compute the mesh +ghs3dMesh.Compute() + + +# Ex2: Add one vertex enforced by a GEOM vertex at (50,50,100) +# with physical size 5 and add it to a group called "My special nodes" + +# Create another GHS3D hypothesis and assign it to the mesh without geometry +GHS3D_Parameters_wo_geometry = smesh.CreateHypothesis('GHS3D_Parameters', 'GHS3DEngine') +ghs3dMesh_wo_geometry.AddHypothesis( GHS3D ) +ghs3dMesh_wo_geometry.AddHypothesis( GHS3D_Parameters_wo_geometry ) + +# Create the enforced vertex +p1 = geompy.MakeVertex(150, 150, 100) +geompy.addToStudy(p1, "p1") +GHS3D_Parameters_wo_geometry.SetEnforcedVertexGeomWithGroup( p1, 5 , "My special nodes") +#GHS3D_Parameters.SetEnforcedVertexGeom( p1, 5 ) # no group + +# compute the mesh +ghs3dMesh_wo_geometry.Compute() + +# Erase all enforced vertices +GHS3D_Parameters.ClearEnforcedVertices() + +# End of script + +\endcode + +\image html ghs3d_screenshot_enf1.png Ghs3d mesh with enforced vertex +\image html ghs3d_screenshot_enf2.png Ghs3d mesh with enforced vertex from GEOM vertex + +\ref tui_ghs3d "Back to top" + +\anchor tui_ghs3d_enforced_meshes +

    Adding enforced mesh

    + +\code + +# It is possible to constrain GHS3D with another mesh or group. +# The constraint can refer to the nodes, edges or faces. +# This feature is available only on 2D meshes without geometry. +# The constraining elements are called enforced elements for the mesh. +# They can be recovered using groups if necessary. + +# In the following examples, a box and a cylinder are meshed in 2D. +# The mesh of the cylinder will be used as a constraint for the +# 3D mesh of the box. + +import geompy +import smesh +import BLSURFPlugin +import GHS3DPlugin + +box = geompy.MakeBoxDXDYDZ(200, 200, 200) +geompy.addToStudy( box, "box" ) +cylindre = geompy.MakeCylinderRH(50, 50) +geompy.TranslateDXDYDZ(cylindre, 100, 100, 30) +face_cyl = geompy.ExtractShapes(cylindre, geompy.ShapeType["FACE"], True)[1] +geompy.addToStudy( cylindre, 'cylindre' ) +geompy.addToStudyInFather( cylindre, face_cyl, 'face_cyl' ) +p1 = geompy.MakeVertex(20, 20, 20) +p2 = geompy.MakeVertex(180, 180, 20) +c = geompy.MakeCompound([p1,p2]) +geompy.addToStudy( p1, "p1" ) +geompy.addToStudy( p2, "p2" ) +geompy.addToStudy( c, "c" ) + +# Create the 2D algorithm and hypothesis +BLSURF = smesh.CreateHypothesis('BLSURF', 'BLSURFEngine') +# For the box +BLSURF_Parameters = smesh.CreateHypothesis('BLSURF_Parameters', 'BLSURFEngine') +BLSURF_Parameters.SetPhysicalMesh( 1 ) +BLSURF_Parameters.SetPhySize( 200 ) +# For the cylinder +BLSURF_Parameters2 = smesh.CreateHypothesis('BLSURF_Parameters', 'BLSURFEngine') +BLSURF_Parameters2.SetGeometricMesh( 1 ) + +# Create the 3D algorithm and hypothesis +GHS3D = smesh.CreateHypothesis('GHS3D_3D', 'GHS3DEngine') +GHS3D_Parameters_node = smesh.CreateHypothesis('GHS3D_Parameters', 'GHS3DEngine') +#GHS3D_Parameters_node.SetToMeshHoles( 1 ) +GHS3D_Parameters_edge = smesh.CreateHypothesis('GHS3D_Parameters', 'GHS3DEngine') +#GHS3D_Parameters_edge.SetToMeshHoles( 1 ) +GHS3D_Parameters_face = smesh.CreateHypothesis('GHS3D_Parameters', 'GHS3DEngine') +GHS3D_Parameters_face.SetToMeshHoles( 1 ) # to mesh inside the cylinder +GHS3D_Parameters_mesh = smesh.CreateHypothesis('GHS3D_Parameters', 'GHS3DEngine') +GHS3D_Parameters_mesh.SetToMeshHoles( 1 ) # to mesh inside the cylinder + +# Create the mesh on the cylinder +Mesh_cylindre = smesh.Mesh(cylindre) +smesh.SetName(Mesh_cylindre,"Mesh_cylindre") +Mesh_cylindre.AddHypothesis( BLSURF ) +Mesh_cylindre.AddHypothesis( BLSURF_Parameters2 ) +# Create some groups +face_cyl_faces = Mesh_cylindre.GroupOnGeom(face_cyl,'group_face_cyl', smesh.FACE) +face_cyl_edges = Mesh_cylindre.GroupOnGeom(face_cyl,'group_edge_cyl', smesh.EDGE) +face_cyl_nodes = Mesh_cylindre.GroupOnGeom(face_cyl,'group_node_cyl', smesh.NODE) +Mesh_cylindre.Compute() + +# Create the mesh on the cylinder +Mesh_box_tri = smesh.Mesh(box) +smesh.SetName(Mesh_box_tri,"Mesh_box_tri") +Mesh_box_tri.AddHypothesis( BLSURF ) +Mesh_box_tri.AddHypothesis( BLSURF_Parameters ) +Mesh_box_tri.Compute() + +# Create 4 copies of the 2D mesh to test the 3 types of contraints (NODE, EDGE, FACE) +# from the whole mesh and from groups of elements. +# Then the 3D algo and hypothesis are assigned to them. + +mesh_mesh = smesh.CopyMesh( Mesh_box_tri, 'Enforced by faces of mesh', 0, 0) +mesh_mesh.AddHypothesis( GHS3D ) +mesh_mesh.AddHypothesis( GHS3D_Parameters_mesh) + +mesh_node = smesh.CopyMesh( Mesh_box_tri, 'Enforced by group of nodes', 0, 0) +mesh_node.AddHypothesis( GHS3D ) +mesh_node.AddHypothesis( GHS3D_Parameters_node) + +mesh_edge = smesh.CopyMesh( Mesh_box_tri, 'Enforced by group of edges', 0, 0) +mesh_edge.AddHypothesis( GHS3D ) +mesh_edge.AddHypothesis( GHS3D_Parameters_edge) + +mesh_face = smesh.CopyMesh( Mesh_box_tri, 'Enforced by group of faces', 0, 0) +mesh_face.AddHypothesis( GHS3D ) +mesh_face.AddHypothesis( GHS3D_Parameters_face) + +# Add the enforced elements +GHS3D_Parameters_mesh.SetEnforcedMeshWithGroup(Mesh_cylindre.GetMesh(),smesh.FACE,"faces from cylinder") +GHS3D_Parameters_node.SetEnforcedMeshWithGroup(face_cyl_nodes,smesh.NODE,"nodes from face_cyl_nodes") +GHS3D_Parameters_edge.SetEnforcedMeshWithGroup(face_cyl_edges,smesh.EDGE,"edges from face_cyl_edges") +GHS3D_Parameters_face.SetEnforcedMeshWithGroup(face_cyl_faces,smesh.FACE,"faces from face_cyl_faces") + +#Compute the meshes +mesh_node.Compute() +mesh_edge.Compute() +mesh_face.Compute() +mesh_mesh.Compute() + +# End of script + +\endcode + +\image html ghs3d_screenshot_enf3.png +\image html ghs3d_screenshot_enf4.png +\image html ghs3d_screenshot_enf5.png +\image html ghs3d_screenshot_enf6.png + +\ref tui_ghs3d "Back to top" + +*/ diff --git a/doc/salome/gui/GHS3DPLUGIN/input/index.doc b/doc/salome/gui/GHS3DPLUGIN/input/index.doc new file mode 100644 index 0000000..e39ba6d --- /dev/null +++ b/doc/salome/gui/GHS3DPLUGIN/input/index.doc @@ -0,0 +1,25 @@ +/*! + +\mainpage Introduction to GHS3DPLUGIN + +\note GHS3DPLUGIN plugin used GHS3D commercial mesher and require a +license to be used within the Mesh module. + +\n \b GHS3DPLUGIN plugin is destined for: + +
      +
    • Meshing 3D geometric entities.
    • + - Volumes are split into tetrahedral (pyramidal) elements. +
    • Generating 3D meshes from 2D meshes, working without geometrical objects.
    • +
    + +To manage parameters of the GHS3DPLUGIN use \subpage ghs3d_hypo_page and \subpage additional_hypo_page + +Also all GHS3DPLUGIN functionalities are accessible via +\subpage ghs3dplugin_python_interface_page "GHS3DPLUGIN Python interface". + + +\image html image2.gif "Example of a tetrahedral 3D mesh" + + +*/ diff --git a/doc/salome/gui/GHS3DPLUGIN/static/doxygen.css b/doc/salome/gui/GHS3DPLUGIN/static/doxygen.css new file mode 100755 index 0000000..7a2dcbd --- /dev/null +++ b/doc/salome/gui/GHS3DPLUGIN/static/doxygen.css @@ -0,0 +1,836 @@ +/* The standard CSS for doxygen */ + +body, table, div, p, dl { + font-family: Lucida Grande, Verdana, Geneva, Arial, sans-serif; + font-size: 12px; +} + +/* @group Heading Levels */ + +h1 { + font-size: 150%; +} + +h2 { + font-size: 120%; +} + +h3 { + font-size: 100%; +} + +dt { + font-weight: bold; +} + +div.multicol { + -moz-column-gap: 1em; + -webkit-column-gap: 1em; + -moz-column-count: 3; + -webkit-column-count: 3; +} + +p.startli, p.startdd, p.starttd { + margin-top: 2px; +} + +p.endli { + margin-bottom: 0px; +} + +p.enddd { + margin-bottom: 4px; +} + +p.endtd { + margin-bottom: 2px; +} + +/* @end */ + +caption { + font-weight: bold; +} + +span.legend { + font-size: 70%; + text-align: center; +} + +h3.version { + font-size: 90%; + text-align: center; +} + +div.qindex, div.navtab{ + background-color: #EBEFF6; + border: 1px solid #A3B4D7; + text-align: center; + margin: 2px; + padding: 2px; +} + +div.qindex, div.navpath { + width: 100%; + line-height: 140%; +} + +div.navtab { + margin-right: 15px; +} + +/* @group Link Styling */ + +a { + color: #3D578C; + font-weight: normal; + text-decoration: none; +} + +.contents a:visited { + color: #4665A2; +} + +a:hover { + text-decoration: underline; +} + +a.qindex { + font-weight: bold; +} + +a.qindexHL { + font-weight: bold; + background-color: #9CAFD4; + color: #ffffff; + border: 1px double #869DCA; +} + +.contents a.qindexHL:visited { + color: #ffffff; +} + +a.el { + font-weight: bold; +} + +a.elRef { +} + +a.code { + color: #4665A2; +} + +a.codeRef { + color: #4665A2; +} + +/* @end */ + +dl.el { + margin-left: -1cm; +} + +.fragment { + font-family: monospace, fixed; + font-size: 105%; +} + +pre.fragment { + border: 1px solid #C4CFE5; + background-color: #FBFCFD; + padding: 4px 6px; + margin: 4px 8px 4px 2px; + overflow: auto; + word-wrap: break-word; + font-size: 9pt; + line-height: 125%; +} + +div.ah { + background-color: black; + font-weight: bold; + color: #ffffff; + margin-bottom: 3px; + margin-top: 3px; + padding: 0.2em; + border: solid thin #333; + border-radius: 0.5em; + -webkit-border-radius: .5em; + -moz-border-radius: .5em; + box-shadow: 2px 2px 3px #999; + -webkit-box-shadow: 2px 2px 3px #999; + -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px; + background-image: -webkit-gradient(linear, left top, left bottom, from(#eee), to(#000),color-stop(0.3, #444)); + background-image: -moz-linear-gradient(center top, #eee 0%, #444 40%, #000); +} + +div.groupHeader { + margin-left: 16px; + margin-top: 12px; + font-weight: bold; +} + +div.version { + border:1px solid #0000FF; + color: #CCCCCC; + font-family: Arial, Helvetica, sans-serif; + font-size: 9pt; + text-align: center; + width:100px; + -moz-border-radius: 8px; + margin: 5px; +} + +div.footer1 { + background-color: #DFE5F1; + border: 1px solid #AAAAAA; + font-family: Arial, Helvetica, sans-serif; + font-size: 11px; + padding: 10px; + margin-top: 15px; +} + + +div.groupText { + margin-left: 16px; + font-style: italic; +} + +body { + background: white; + color: black; + margin: 0; +} + +div.contents { + margin-top: 10px; + margin-left: 10px; + margin-right: 10px; +} + +td.indexkey { + background-color: #EBEFF6; + font-weight: bold; + border: 1px solid #C4CFE5; + margin: 2px 0px 2px 0; + padding: 2px 10px; +} + +td.indexvalue { + background-color: #EBEFF6; + border: 1px solid #C4CFE5; + padding: 2px 10px; + margin: 2px 0px; +} + +tr.memlist { + background-color: #EEF1F7; +} + +p.formulaDsp { + text-align: center; +} + +img.formulaDsp { + +} + +img.formulaInl { + vertical-align: middle; +} + +div.center { + text-align: center; + margin-top: 0px; + margin-bottom: 0px; + padding: 0px; +} + +div.center img { + border: 0px; +} + +address.footer { + text-align: right; + padding-right: 12px; +} + +img.footer { + border: 0px; + vertical-align: middle; +} + +/* @group Code Colorization */ + +span.keyword { + color: #008000 +} + +span.keywordtype { + color: #604020 +} + +span.keywordflow { + color: #e08000 +} + +span.comment { + color: #800000 +} + +span.preprocessor { + color: #806020 +} + +span.stringliteral { + color: #002080 +} + +span.charliteral { + color: #008080 +} + +span.vhdldigit { + color: #ff00ff +} + +span.vhdlchar { + color: #000000 +} + +span.vhdlkeyword { + color: #700070 +} + +span.vhdllogic { + color: #ff0000 +} + +/* @end */ + +/* +.search { + color: #003399; + font-weight: bold; +} + +form.search { + margin-bottom: 0px; + margin-top: 0px; +} + +input.search { + font-size: 75%; + color: #000080; + font-weight: normal; + background-color: #e8eef2; +} +*/ + +td.tiny { + font-size: 75%; +} + +.dirtab { + padding: 4px; + border-collapse: collapse; + border: 1px solid #A3B4D7; +} + +th.dirtab { + background: #EBEFF6; + font-weight: bold; +} + +hr { + height: 0px; + border: none; + border-top: 1px solid #4A6AAA; +} + +hr.footer { + height: 1px; +} + +/* @group Member Descriptions */ + +table.memberdecls { + border-spacing: 0px; + padding: 0px; +} + +.mdescLeft, .mdescRight, +.memItemLeft, .memItemRight, +.memTemplItemLeft, .memTemplItemRight, .memTemplParams { + background-color: #F9FAFC; + border: none; + margin: 4px; + padding: 1px 0 0 8px; +} + +.mdescLeft, .mdescRight { + padding: 0px 8px 4px 8px; + color: #555; +} + +.memItemLeft, .memItemRight, .memTemplParams { + border-top: 1px solid #C4CFE5; +} + +.memItemLeft, .memTemplItemLeft { + white-space: nowrap; +} + +.memTemplParams { + color: #4665A2; + white-space: nowrap; +} + +/* @end */ + +/* @group Member Details */ + +/* Styles for detailed member documentation */ + +.memtemplate { + font-size: 80%; + color: #4665A2; + font-weight: normal; + margin-left: 9px; +} + +.memnav { + background-color: #EBEFF6; + border: 1px solid #A3B4D7; + text-align: center; + margin: 2px; + margin-right: 15px; + padding: 2px; +} + +.memitem { + padding: 0; + margin-bottom: 10px; +} + +.memname { + white-space: nowrap; + font-weight: bold; + margin-left: 6px; +} + +.memproto { + border-top: 1px solid #A8B8D9; + border-left: 1px solid #A8B8D9; + border-right: 1px solid #A8B8D9; + padding: 6px 0px 6px 0px; + color: #253555; + font-weight: bold; + text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9); + /* opera specific markup */ + box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); + border-top-right-radius: 8px; + border-top-left-radius: 8px; + /* firefox specific markup */ + -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; + -moz-border-radius-topright: 8px; + -moz-border-radius-topleft: 8px; + /* webkit specific markup */ + -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); + -webkit-border-top-right-radius: 8px; + -webkit-border-top-left-radius: 8px; + background-image:url('nav_f.png'); + background-repeat:repeat-x; + background-color: #E2E8F2; + +} + +.memdoc { + border-bottom: 1px solid #A8B8D9; + border-left: 1px solid #A8B8D9; + border-right: 1px solid #A8B8D9; + padding: 2px 5px; + background-color: #FBFCFD; + border-top-width: 0; + /* opera specific markup */ + border-bottom-left-radius: 8px; + border-bottom-right-radius: 8px; + box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); + /* firefox specific markup */ + -moz-border-radius-bottomleft: 8px; + -moz-border-radius-bottomright: 8px; + -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; + background-image: -moz-linear-gradient(center top, #FFFFFF 0%, #FFFFFF 60%, #F7F8FB 95%, #EEF1F7); + /* webkit specific markup */ + -webkit-border-bottom-left-radius: 8px; + -webkit-border-bottom-right-radius: 8px; + -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); + background-image: -webkit-gradient(linear,center top,center bottom,from(#FFFFFF), color-stop(0.6,#FFFFFF), color-stop(0.60,#FFFFFF), color-stop(0.95,#F7F8FB), to(#EEF1F7)); +} + +.paramkey { + text-align: right; +} + +.paramtype { + white-space: nowrap; +} + +.paramname { + color: #602020; + white-space: nowrap; +} +.paramname em { + font-style: normal; +} + +.params, .retval, .exception, .tparams { + border-spacing: 6px 2px; +} + +.params .paramname, .retval .paramname { + font-weight: bold; + vertical-align: top; +} + +.params .paramtype { + font-style: italic; + vertical-align: top; +} + +.params .paramdir { + font-family: "courier new",courier,monospace; + vertical-align: top; +} + + + + +/* @end */ + +/* @group Directory (tree) */ + +/* for the tree view */ + +.ftvtree { + font-family: sans-serif; + margin: 0px; +} + +/* these are for tree view when used as main index */ + +.directory { + font-size: 9pt; + font-weight: bold; + margin: 5px; +} + +.directory h3 { + margin: 0px; + margin-top: 1em; + font-size: 11pt; +} + +/* +The following two styles can be used to replace the root node title +with an image of your choice. Simply uncomment the next two styles, +specify the name of your image and be sure to set 'height' to the +proper pixel height of your image. +*/ + +/* +.directory h3.swap { + height: 61px; + background-repeat: no-repeat; + background-image: url("yourimage.gif"); +} +.directory h3.swap span { + display: none; +} +*/ + +.directory > h3 { + margin-top: 0; +} + +.directory p { + margin: 0px; + white-space: nowrap; +} + +.directory div { + display: none; + margin: 0px; +} + +.directory img { + vertical-align: -30%; +} + +/* these are for tree view when not used as main index */ + +.directory-alt { + font-size: 100%; + font-weight: bold; +} + +.directory-alt h3 { + margin: 0px; + margin-top: 1em; + font-size: 11pt; +} + +.directory-alt > h3 { + margin-top: 0; +} + +.directory-alt p { + margin: 0px; + white-space: nowrap; +} + +.directory-alt div { + display: none; + margin: 0px; +} + +.directory-alt img { + vertical-align: -30%; +} + +/* @end */ + +div.dynheader { + margin-top: 8px; +} + +address { + font-style: normal; + color: #2A3D61; +} + +table.doxtable { + border-collapse:collapse; +} + +table.doxtable td, table.doxtable th { + border: 1px solid #2D4068; + padding: 3px 7px 2px; +} + +table.doxtable th { + background-color: #374F7F; + color: #FFFFFF; + font-size: 110%; + padding-bottom: 4px; + padding-top: 5px; + text-align:left; +} + +.tabsearch { + top: 0px; + left: 10px; + height: 36px; + background-image: url('tab_b.png'); + z-index: 101; + overflow: hidden; + font-size: 13px; +} + +.navpath ul +{ + font-size: 11px; + background-image:url('tab_b.png'); + background-repeat:repeat-x; + height:30px; + line-height:30px; + color:#8AA0CC; + border:solid 1px #C2CDE4; + overflow:hidden; + margin:0px; + padding:0px; +} + +.navpath li +{ + list-style-type:none; + float:left; + padding-left:10px; + padding-right:15px; + background-image:url('bc_s.png'); + background-repeat:no-repeat; + background-position:right; + color:#364D7C; +} + +.navpath li.navelem a +{ + height:32px; + display:block; + text-decoration: none; + outline: none; +} + +.navpath li.navelem a:hover +{ + color:#6884BD; +} + +.navpath li.footer +{ + list-style-type:none; + float:right; + padding-left:10px; + padding-right:15px; + background-image:none; + background-repeat:no-repeat; + background-position:right; + color:#364D7C; + font-size: 8pt; +} + + +div.summary +{ + float: right; + font-size: 8pt; + padding-right: 5px; + width: 50%; + text-align: right; +} + +div.summary a +{ + white-space: nowrap; +} + +div.ingroups +{ + font-size: 8pt; + padding-left: 5px; + width: 50%; + text-align: left; +} + +div.ingroups a +{ + white-space: nowrap; +} + +div.header +{ + background-image:url('nav_h.png'); + background-repeat:repeat-x; + background-color: #F9FAFC; + margin: 0px; + border-bottom: 1px solid #C4CFE5; +} + +div.headertitle +{ + padding: 5px 5px 5px 10px; +} + +.title { + font-size: 150%; + font-weight: bold; + margin: 10px 2px; +} + +dl +{ + padding: 0 0 0 10px; +} + +dl.note, dl.warning, dl.attention, dl.pre, dl.post, dl.invariant, dl.deprecated, dl.todo, dl.test, dl.bug +{ + border-left:4px solid; + padding: 0 0 0 6px; +} + +dl.note +{ + border-color: #D0D000; +} + +dl.warning, dl.attention +{ + border-color: #FF0000; +} + +dl.pre, dl.post, dl.invariant +{ + border-color: #00D000; +} + +dl.deprecated +{ + border-color: #505050; +} + +dl.todo +{ + border-color: #00C0E0; +} + +dl.test +{ + border-color: #3030E0; +} + +dl.bug +{ + border-color: #C08050; +} + +#projectlogo +{ + text-align: center; + vertical-align: bottom; + border-collapse: separate; +} + +#projectlogo img +{ + border: 0px none; +} + +#projectname +{ + background-color: #175783; + border: 1px solid; + height: 80px; + background-repeat: no-repeat; +/* font: 300% arial,sans-serif;*/ + margin: 0px; + padding: 0px; +} + +#projectbrief +{ + font: 120% arial,sans-serif; + margin: 0px; + padding: 0px; +} + +#projectnumber +{ + font: 50% arial,sans-serif; + margin: 0px; + padding: 0px; +} + +#titlearea +{ + background: url("head.png"); + background-color: #175783; + border: 1px solid; + height: 80px; + background-repeat: no-repeat; + padding: 0px; + margin: 0px; + width: 100%; + border-bottom: 1px solid #5373B4; +} + diff --git a/doc/salome/gui/GHS3DPLUGIN/static/footer.html b/doc/salome/gui/GHS3DPLUGIN/static/footer.html new file mode 100755 index 0000000..4c89a2b --- /dev/null +++ b/doc/salome/gui/GHS3DPLUGIN/static/footer.html @@ -0,0 +1,12 @@ + + + +
    +
    + Copyright © 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE
    + Copyright © 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
    +
    +
    + + + \ No newline at end of file diff --git a/doc/salome/gui/GHS3DPLUGIN/static/header.html.in b/doc/salome/gui/GHS3DPLUGIN/static/header.html.in new file mode 100755 index 0000000..4571b43 --- /dev/null +++ b/doc/salome/gui/GHS3DPLUGIN/static/header.html.in @@ -0,0 +1,20 @@ + + + + + +$title + +$treeview +$search +$mathjax + + + + +
    +
    Version: @VERSION@
    + +
    diff --git a/doc/salome/gui/GHS3DPLUGIN/static/header_py.html.in b/doc/salome/gui/GHS3DPLUGIN/static/header_py.html.in new file mode 100644 index 0000000..61414bb --- /dev/null +++ b/doc/salome/gui/GHS3DPLUGIN/static/header_py.html.in @@ -0,0 +1,21 @@ + + + + + +$title + +$treeview +$search +$mathjax + + + + +
    diff --git a/doc/salome/gui/Makefile.am b/doc/salome/gui/Makefile.am new file mode 100644 index 0000000..ddbdb9e --- /dev/null +++ b/doc/salome/gui/Makefile.am @@ -0,0 +1,26 @@ +# 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 + +SUBDIRS = GHS3DPLUGIN + +usr_docs: + (cd GHS3DPLUGIN && $(MAKE) $(AM_MAKEFLAGS) usr_docs) + +docs: usr_docs diff --git a/idl/GHS3DPlugin_Algorithm.idl b/idl/GHS3DPlugin_Algorithm.idl index a402d78..8af4f1e 100644 --- a/idl/GHS3DPlugin_Algorithm.idl +++ b/idl/GHS3DPlugin_Algorithm.idl @@ -1,21 +1,22 @@ -// Copyright (C) 2004-2008 CEA/DEN, EDF R&D +// Copyright (C) 2004-2012 CEA/DEN, EDF R&D // -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License. +// 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. +// 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 +// 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 +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // + // File : GHS3D_Algorithm.idl // Author : Julia DOROVSKIKH // $Header$ @@ -25,17 +26,41 @@ #include "SALOME_Exception.idl" #include "SMESH_Hypothesis.idl" +#include "SMESH_Mesh.idl" /*! * GHS3DPlugin: interfaces to GHS3D related hypotheses and algorithms */ module GHS3DPlugin { + typedef sequence TCoords; + struct GHS3DEnforcedVertex { + string name; + string geomEntry; + boolean isCompound; + TCoords coords; + string groupName; + double size; + }; + + typedef sequence GHS3DEnforcedVertexList; + + struct GHS3DEnforcedMesh { + string name; + string entry; + SMESH::ElementType elementType; + string groupName; + double size; + }; + + typedef sequence GHS3DEnforcedMeshList; + /*! * GHS3DPlugin_GHS3D: interface of "Tetrahedron (GHS3D)" algorithm */ interface GHS3DPlugin_GHS3D : SMESH::SMESH_3D_Algo { + SMESH::SMESH_Mesh importGMFMesh(in string aGMFFileName); }; /*! @@ -99,11 +124,57 @@ module GHS3DPlugin */ void SetToUseBoundaryRecoveryVersion(in boolean toUse); boolean GetToUseBoundaryRecoveryVersion(); + /*! + * Applies finite-element correction by replacing overconstrained elements where + * it is possible. The process is cutting first the overconstrained edges and + * second the overconstrained facets. This insure that no edges have two boundary + * vertices and that no facets have three boundary vertices. + */ + void SetFEMCorrection(in boolean toUseFem); + boolean GetFEMCorrection(); + /*! + * To removes initial central point. + */ + void SetToRemoveCentralPoint(in boolean toRemove); + boolean GetToRemoveCentralPoint(); /*! * To set hiden/undocumented/advanced options */ void SetTextOption(in string option); string GetTextOption(); + /*! + * To set an enforced vertex + */ + boolean SetEnforcedVertex(in double x, in double y, in double z, in double size) raises (SALOME::SALOME_Exception); + boolean SetEnforcedVertexNamed(in double x, in double y, in double z, in double size, in string vertexName) raises (SALOME::SALOME_Exception); + boolean SetEnforcedVertexWithGroup(in double x, in double y, in double z, in double size, in string groupName) raises (SALOME::SALOME_Exception); + boolean SetEnforcedVertexNamedWithGroup(in double x, in double y, in double z, in double size, in string vertexName, in string groupName) raises (SALOME::SALOME_Exception); + boolean SetEnforcedVertexGeom(in GEOM::GEOM_Object theVertex, in double size) raises (SALOME::SALOME_Exception); + boolean SetEnforcedVertexGeomWithGroup(in GEOM::GEOM_Object theVertex, in double size, in string groupName) raises (SALOME::SALOME_Exception); + double GetEnforcedVertex(in double x, in double y, in double z) raises (SALOME::SALOME_Exception); + double GetEnforcedVertexGeom(in GEOM::GEOM_Object theVertex) raises (SALOME::SALOME_Exception); + boolean RemoveEnforcedVertex(in double x, in double y, in double z) raises (SALOME::SALOME_Exception); + boolean RemoveEnforcedVertexGeom(in GEOM::GEOM_Object theVertex) raises (SALOME::SALOME_Exception); + GHS3DEnforcedVertexList GetEnforcedVertices(); + void ClearEnforcedVertices(); + /*! + * Set/get/unset an enforced vertex (private method for GUI) + */ + boolean p_SetEnforcedVertex(in double size, in double x, in double y, in double z, + in string theVertexName, in string theVertexEntry, in string groupName, + in boolean isCompound) raises (SALOME::SALOME_Exception); + + boolean SetEnforcedMesh(in SMESH::SMESH_IDSource theSource, in SMESH::ElementType elementType) raises (SALOME::SALOME_Exception); + boolean SetEnforcedMeshWithGroup(in SMESH::SMESH_IDSource theSource, in SMESH::ElementType elementType, in string groupName) raises (SALOME::SALOME_Exception); + boolean SetEnforcedMeshSize(in SMESH::SMESH_IDSource theSource, in SMESH::ElementType elementType, in double size) raises (SALOME::SALOME_Exception); + boolean SetEnforcedMeshSizeWithGroup(in SMESH::SMESH_IDSource theSource, in SMESH::ElementType elementType, in double size, in string groupName) raises (SALOME::SALOME_Exception); + GHS3DEnforcedMeshList GetEnforcedMeshes(); + void ClearEnforcedMeshes(); + /*! + * Set/get/unset an enforced vertex (private method for GUI) + */ + boolean p_SetEnforcedMesh(in SMESH::SMESH_IDSource theSource, in SMESH::ElementType elementType, + in double size, in string groupName) raises (SALOME::SALOME_Exception); }; }; diff --git a/idl/Makefile.am b/idl/Makefile.am index 229ec1e..e675d27 100644 --- a/idl/Makefile.am +++ b/idl/Makefile.am @@ -1,21 +1,22 @@ -# Copyright (C) 2004-2008 CEA/DEN, EDF R&D +# Copyright (C) 2004-2012 CEA/DEN, EDF R&D # -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License. +# 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. +# 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 +# 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 +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com # + # This Makefile is responsible of generating the client and server # implementation of IDL interfaces for both C++ and python usage. # The building process of the C++ files is in charge of each source @@ -25,6 +26,8 @@ include $(top_srcdir)/adm_local/unix/make_common_starter.am BASEIDL_FILES = GHS3DPlugin_Algorithm.idl +BASEIDL_FILES_PY=$(BASEIDL_FILES:%.idl=%_idl.py) + # This variable defines the files to be installed dist_salomeidl_DATA = $(BASEIDL_FILES) @@ -41,18 +44,19 @@ GHS3DPlugin_AlgorithmDynSK.cc: GHS3DPlugin_AlgorithmSK.cc nodist_salomeinclude_HEADERS = $(BASEIDL_FILES:%.idl=%.hh) libSalomeIDLGHS3DPLUGIN_la_CPPFLAGS = \ - -I$(top_builddir)/salome_adm/unix \ -I$(top_builddir)/idl \ $(CORBA_CXXFLAGS) \ $(CORBA_INCLUDES) \ $(KERNEL_CXXFLAGS) \ $(GEOM_CXXFLAGS) \ + $(MED_CXXFLAGS) \ $(SMESH_CXXFLAGS) libSalomeIDLGHS3DPLUGIN_la_LDFLAGS = -no-undefined -version-info=0:0:0 libSalomeIDLGHS3DPLUGIN_la_LIBADD = \ $(KERNEL_LDFLAGS) -lSalomeIDLKernel \ $(GEOM_LDFLAGS) -lSalomeIDLGEOM \ + $(MED_LDFLAGS) -lSalomeIDLMED \ $(SMESH_LDFLAGS) -lSalomeIDLSMESH \ @CORBA_LIBS@ @@ -64,6 +68,7 @@ OMNIORB_IDLPYFLAGS = \ -I$(top_builddir)/idl/salome \ -I$(KERNEL_ROOT_DIR)/idl/salome \ -I$(GEOM_ROOT_DIR)/idl/salome \ + -I$(MED_ROOT_DIR)/idl/salome \ -I$(SMESH_ROOT_DIR)/idl/salome IDLCXXFLAGS = \ @@ -72,12 +77,13 @@ IDLCXXFLAGS = \ -I$(top_builddir)/idl/salome \ -I$(KERNEL_ROOT_DIR)/idl/salome \ -I$(GEOM_ROOT_DIR)/idl/salome \ - -I$(SMESH_ROOT_DIR)/idl/salome \ - -I$(top_builddir)/salome_adm/unix + -I$(MED_ROOT_DIR)/idl/salome \ + -I$(SMESH_ROOT_DIR)/idl/salome IDLPYFLAGS = \ @IDLPYFLAGS@ \ -I$(KERNEL_ROOT_DIR)/idl/salome \ -I$(GEOM_ROOT_DIR)/idl/salome \ + -I$(MED_ROOT_DIR)/idl/salome \ -I$(SMESH_ROOT_DIR)/idl/salome # potential problem on parallel make on the following - multiple outputs @@ -93,9 +99,15 @@ install-exec-local: $(BASEIDL_FILES:%=$(top_srcdir)/idl/%) $(OMNIORB_IDL) $(IDLPYFLAGS) -C$(DESTDIR)$(salomepythondir) $$file ; \ done -# uninstall-local removes too much, but it works in distcheck +# we want to remove only staff generated for IDL files and nothing more uninstall-local: - rm -rf $(DESTDIR)$(salomepythondir)/* + @for modulen in GHS3DPlugin ; do \ + test -d $(DESTDIR)$(salomepythondir)/$${modulen} && echo "Removing $(DESTDIR)$(salomepythondir)/$${modulen}" && rm -rf $(DESTDIR)$(salomepythondir)/$${modulen} ; \ + test -d $(DESTDIR)$(salomepythondir)/$${modulen}__POA && echo "Removing $(DESTDIR)$(salomepythondir)/$${modulen}__POA" && rm -rf $(DESTDIR)$(salomepythondir)/$${modulen}__POA ; \ + done ; \ + for filen in $(BASEIDL_FILES_PY) ; do \ + echo "Removing $(DESTDIR)$(salomepythondir)/$${filen}" && rm -f $(DESTDIR)$(salomepythondir)/$${filen}* ; \ + done mostlyclean-local: -rm -f *.hh *.cc .depidl @@ -109,7 +121,7 @@ mostlyclean-local: @for dep in $^ dummy; do \ if [ $$dep != "dummy" ]; then \ echo Building dependencies for $$dep; \ - $(CPP) $(C_DEPEND_FLAG) -x c -I$(srcdir) -I$(KERNEL_ROOT_DIR)/idl/salome -I$(GEOM_ROOT_DIR)/idl/salome -I$(SMESH_ROOT_DIR)/idl/salome -I$(top_builddir)/salome_adm/unix $$dep 2>/dev/null | \ + $(CPP) $(C_DEPEND_FLAG) -x c -I$(srcdir) -I$(KERNEL_ROOT_DIR)/idl/salome -I$(GEOM_ROOT_DIR)/idl/salome -I$(MED_ROOT_DIR)/idl/salome -I$(SMESH_ROOT_DIR)/idl/salome $$dep 2>/dev/null | \ sed 's/\.o/\SK.cc/' >>$@; \ fi; \ done ; diff --git a/resources/GHS3DPlugin.xml b/resources/GHS3DPlugin.xml index 404c5bc..2c1ece4 100644 --- a/resources/GHS3DPlugin.xml +++ b/resources/GHS3DPlugin.xml @@ -1,7 +1,7 @@ +
    + +
    diff --git a/src/GHS3DPlugin/GHS3DPluginDC.py b/src/GHS3DPlugin/GHS3DPluginDC.py new file mode 100644 index 0000000..adc2dd9 --- /dev/null +++ b/src/GHS3DPlugin/GHS3DPluginDC.py @@ -0,0 +1,186 @@ +# Copyright (C) 2007-2012 CEA/DEN, EDF R&D +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License. +# +# 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 +# + +from smesh import Mesh_Algorithm, AssureGeomPublished + +# import GHS3DPlugin module if possible +noGHS3DPlugin = 0 +try: + import GHS3DPlugin +except ImportError: + noGHS3DPlugin = 1 + pass + +# Optimization level of GHS3D +# V3.1 +None_Optimization, Light_Optimization, Medium_Optimization, Strong_Optimization = 0,1,2,3 +# V4.1 (partialy redefines V3.1). Issue 0020574 +None_Optimization, Light_Optimization, Standard_Optimization, StandardPlus_Optimization, Strong_Optimization = 0,1,2,3,4 + +GHS3D = "GHS3D_3D" + +## Tetrahedron GHS3D 3D algorithm +# It is created by calling Mesh.Tetrahedron( GHS3D, geom=0 ) +# +class GHS3D_Algorithm(Mesh_Algorithm): + + meshMethod = "Tetrahedron" + algoType = GHS3D + + ## Private constructor. + def __init__(self, mesh, geom=0): + Mesh_Algorithm.__init__(self) + if noGHS3DPlugin: print "Warning: GHS3DPlugin module unavailable" + self.Create(mesh, geom, self.algoType, "libGHS3DEngine.so") + self.params = None + + ## Defines hypothesis having several parameters + # + def Parameters(self): + if not self.params: + self.params = self.Hypothesis("GHS3D_Parameters", [], + "libGHS3DEngine.so", UseExisting=0) + return self.params + + ## To mesh "holes" in a solid or not. Default is to mesh. + # + def SetToMeshHoles(self, toMesh): + self.Parameters().SetToMeshHoles(toMesh) + + ## Set Optimization level: + # None_Optimization, Light_Optimization, Standard_Optimization, StandardPlus_Optimization, + # Strong_Optimization. + # Default is Standard_Optimization + def SetOptimizationLevel(self, level): + self.Parameters().SetOptimizationLevel(level) + + ## Maximal size of memory to be used by the algorithm (in Megabytes). + # + def SetMaximumMemory(self, MB): + self.Parameters().SetMaximumMemory(MB) + + ## Initial size of memory to be used by the algorithm (in Megabytes) in + # automatic memory adjustment mode. + def SetInitialMemory(self, MB): + self.Parameters().SetInitialMemory(MB) + + ## Path to working directory. + # + def SetWorkingDirectory(self, path): + self.Parameters().SetWorkingDirectory(path) + + ## To keep working files or remove them. Log file remains in case of errors anyway. + def SetKeepFiles(self, toKeep): + self.Parameters().SetKeepFiles(toKeep) + + ## To set verbose level [0-10].
      + #
    • 0 - no standard output, + #
    • 2 - prints the data, quality statistics of the skin and final meshes and + # indicates when the final mesh is being saved. In addition the software + # gives indication regarding the CPU time. + #
    • 10 - same as 2 plus the main steps in the computation, quality statistics + # histogram of the skin mesh, quality statistics histogram together with + # the characteristics of the final mesh.
    + def SetVerboseLevel(self, level): + self.Parameters().SetVerboseLevel(level) + + ## To create new nodes. + def SetToCreateNewNodes(self, toCreate): + self.Parameters().SetToCreateNewNodes(toCreate) + + ## To use boundary recovery version which tries to create mesh on a very poor + # quality surface mesh. + def SetToUseBoundaryRecoveryVersion(self, toUse): + self.Parameters().SetToUseBoundaryRecoveryVersion(toUse) + + ## Applies finite-element correction by replacing overconstrained elements where + # it is possible. The process is cutting first the overconstrained edges and + # second the overconstrained facets. This insure that no edges have two boundary + # vertices and that no facets have three boundary vertices. + def SetFEMCorrection(self, toUseFem): + self.Parameters().SetFEMCorrection(toUseFem) + + ## To removes initial central point. + def SetToRemoveCentralPoint(self, toRemove): + self.Parameters().SetToRemoveCentralPoint(toRemove) + + ## To set an enforced vertex. + # @param x : x coordinate + # @param y : y coordinate + # @param z : z coordinate + # @param size : size of 1D element around enforced vertex + # @param vertexName : name of the enforced vertex + # @param groupName : name of the group + def SetEnforcedVertex(self, x, y, z, size, vertexName = "", groupName = ""): + if vertexName == "": + if groupName == "": + return self.Parameters().SetEnforcedVertex(x, y, z, size) + else: + return self.Parameters().SetEnforcedVertexWithGroup(x, y, z, size, groupName) + else: + if groupName == "": + return self.Parameters().SetEnforcedVertexNamed(x, y, z, size, vertexName) + else: + return self.Parameters().SetEnforcedVertexNamedWithGroup(x, y, z, size, vertexName, groupName) + + ## To set an enforced vertex given a GEOM vertex, group or compound. + # @param theVertex : GEOM vertex (or group, compound) to be projected on theFace. + # @param size : size of 1D element around enforced vertex + # @param groupName : name of the group + def SetEnforcedVertexGeom(self, theVertex, size, groupName = ""): + AssureGeomPublished( self.mesh, theVertex ) + if groupName == "": + return self.Parameters().SetEnforcedVertexGeom(theVertex, size) + else: + return self.Parameters().SetEnforcedVertexGeomWithGroup(theVertex, size, groupName) + + ## To remove an enforced vertex. + # @param x : x coordinate + # @param y : y coordinate + # @param z : z coordinate + def RemoveEnforcedVertex(self, x, y, z): + return self.Parameters().RemoveEnforcedVertex(x, y, z) + + ## To remove an enforced vertex given a GEOM vertex, group or compound. + # @param theVertex : GEOM vertex (or group, compound) to be projected on theFace. + def RemoveEnforcedVertexGeom(self, theVertex): + AssureGeomPublished( self.mesh, theVertex ) + return self.Parameters().RemoveEnforcedVertexGeom(theVertex) + + ## To set an enforced mesh with given size and add the enforced elements in the group "groupName". + # @param theSource : source mesh which provides constraint elements/nodes + # @param elementType : SMESH.ElementType (NODE, EDGE or FACE) + # @param size : size of elements around enforced elements. Unused if -1. + # @param groupName : group in which enforced elements will be added. Unused if "". + def SetEnforcedMesh(self, theSource, elementType, size = -1, groupName = ""): + if size < 0: + if groupName == "": + return self.Parameters().SetEnforcedMesh(theSource, elementType) + else: + return self.Parameters().SetEnforcedMeshWithGroup(theSource, elementType, groupName) + else: + if groupName == "": + return self.Parameters().SetEnforcedMeshSize(theSource, elementType, size) + else: + return self.Parameters().SetEnforcedMeshSizeWithGroup(theSource, elementType, size, groupName) + + ## Sets command line option as text. + def SetTextOption(self, option): + self.Parameters().SetTextOption(option) + diff --git a/src/GHS3DPlugin/GHS3DPlugin_Defs.hxx b/src/GHS3DPlugin/GHS3DPlugin_Defs.hxx new file mode 100644 index 0000000..2ec37bb --- /dev/null +++ b/src/GHS3DPlugin/GHS3DPlugin_Defs.hxx @@ -0,0 +1,37 @@ +// Copyright (C) 2004-2012 CEA/DEN, EDF R&D +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// 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 : GHS3DPlugin_Defs.hxx +// Author : Alexander A. BORODIN +// +#ifndef _GHS3DPlugin_DEFS_HXX_ +#define _GHS3DPlugin_DEFS_HXX_ + +#ifdef WIN32 + #if defined GHS3DPLUGIN_EXPORTS || defined GHS3DEngine_EXPORTS + #define GHS3DPLUGIN_EXPORT __declspec( dllexport ) + #else + #define GHS3DPLUGIN_EXPORT __declspec( dllimport ) + #endif +#else + #define GHS3DPLUGIN_EXPORT +#endif + +#endif diff --git a/src/GHS3DPlugin/GHS3DPlugin_GHS3D.cxx b/src/GHS3DPlugin/GHS3DPlugin_GHS3D.cxx new file mode 100644 index 0000000..6da9eec --- /dev/null +++ b/src/GHS3DPlugin/GHS3DPlugin_GHS3D.cxx @@ -0,0 +1,4314 @@ +// Copyright (C) 2004-2012 CEA/DEN, EDF R&D +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// 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 : GHS3DPlugin_GHS3D.cxx +// Created : +// Author : Edward AGAPOV, modified by Lioka RAZAFINDRAZAKA (CEA) 09/02/2007 +// Project : SALOME +//============================================================================= +// +#include "GHS3DPlugin_GHS3D.hxx" +#include "GHS3DPlugin_Hypothesis.hxx" + +#include + +//#include "SMESH_Gen.hxx" +#include +#include "SMESH_Mesh.hxx" +#include "SMESH_Comment.hxx" +#include "SMESH_MesherHelper.hxx" +#include "SMESH_MeshEditor.hxx" +#include "SMESH_OctreeNode.hxx" +#include "SMESH_Group.hxx" + +#include "SMDS_MeshElement.hxx" +#include "SMDS_MeshNode.hxx" +#include "SMDS_FaceOfNodes.hxx" +#include "SMDS_VolumeOfNodes.hxx" + +#include "SMESHDS_Group.hxx" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "utilities.h" + +#ifdef WIN32 +#include +#else +#include +#endif +#include + +//#include + + +#define castToNode(n) static_cast( n ); + +#ifdef _DEBUG_ +#define DUMP(txt) \ +// std::cout << txt +#else +#define DUMP(txt) +#endif + +extern "C" +{ +#ifndef WNT +#include +#include +#endif +#include +#include +} + +#define HOLE_ID -1 + +#ifndef GHS3D_VERSION +#define GHS3D_VERSION 41 +#endif + +typedef const list TTriaList; + +static void removeFile( const TCollection_AsciiString& fileName ) +{ + try { + OSD_File( fileName ).Remove(); + } + catch ( Standard_ProgramError ) { + MESSAGE("Can't remove file: " << fileName.ToCString() << " ; file does not exist or permission denied"); + } +} + +//============================================================================= +/*! + * + */ +//============================================================================= + +GHS3DPlugin_GHS3D::GHS3DPlugin_GHS3D(int hypId, int studyId, SMESH_Gen* gen) + : SMESH_3D_Algo(hypId, studyId, gen) +{ + MESSAGE("GHS3DPlugin_GHS3D::GHS3DPlugin_GHS3D"); + _name = "GHS3D_3D"; + _shapeType = (1 << TopAbs_SHELL) | (1 << TopAbs_SOLID);// 1 bit /shape type + _onlyUnaryInput = false; // Compute() will be called on a compound of solids + _iShape=0; + _nbShape=0; + _compatibleHypothesis.push_back( GHS3DPlugin_Hypothesis::GetHypType()); + _compatibleHypothesis.push_back( StdMeshers_ViscousLayers::GetHypType() ); + _requireShape = false; // can work without shape_studyId + + smeshGen_i = SMESH_Gen_i::GetSMESHGen(); + CORBA::Object_var anObject = smeshGen_i->GetNS()->Resolve("/myStudyManager"); + SALOMEDS::StudyManager_var aStudyMgr = SALOMEDS::StudyManager::_narrow(anObject); + + MESSAGE("studyid = " << _studyId); + + myStudy = NULL; + myStudy = aStudyMgr->GetStudyByID(_studyId); + if (myStudy) + MESSAGE("myStudy->StudyId() = " << myStudy->StudyId()); + +#ifdef WITH_SMESH_CANCEL_COMPUTE + _compute_canceled = false; +#endif +} + +//============================================================================= +/*! + * + */ +//============================================================================= + +GHS3DPlugin_GHS3D::~GHS3DPlugin_GHS3D() +{ + MESSAGE("GHS3DPlugin_GHS3D::~GHS3DPlugin_GHS3D"); +} + +//============================================================================= +/*! + * + */ +//============================================================================= + +bool GHS3DPlugin_GHS3D::CheckHypothesis ( SMESH_Mesh& aMesh, + const TopoDS_Shape& aShape, + Hypothesis_Status& aStatus ) +{ + aStatus = SMESH_Hypothesis::HYP_OK; + + _hyp = 0; + _viscousLayersHyp = 0; + _keepFiles = false; + + const list & hyps = + GetUsedHypothesis(aMesh, aShape, /*ignoreAuxiliary=*/false); + list ::const_iterator h = hyps.begin(); + for ( ; h != hyps.end(); ++h ) + { + if ( !_hyp ) + _hyp = dynamic_cast< const GHS3DPlugin_Hypothesis*> ( *h ); + if ( !_viscousLayersHyp ) + _viscousLayersHyp = dynamic_cast< const StdMeshers_ViscousLayers*> ( *h ); + } + if ( _hyp ) + _keepFiles = _hyp->GetKeepFiles(); + + return true; +} + + +//======================================================================= +//function : entryToShape +//purpose : +//======================================================================= + +TopoDS_Shape GHS3DPlugin_GHS3D::entryToShape(std::string entry) +{ + MESSAGE("GHS3DPlugin_GHS3D::entryToShape "<FindObjectID( entry.c_str() ); + SALOMEDS::GenericAttribute_var anAttr; + + if (!aSObj->_is_nil() && aSObj->FindAttribute(anAttr, "AttributeIOR")) { + SALOMEDS::AttributeIOR_var anIOR = SALOMEDS::AttributeIOR::_narrow(anAttr); + CORBA::String_var aVal = anIOR->Value(); + CORBA::Object_var obj = myStudy->ConvertIORToObject(aVal); + aGeomObj = GEOM::GEOM_Object::_narrow(obj); + } + if ( !aGeomObj->_is_nil() ) + S = smeshGen_i->GeomObjectToShape( aGeomObj.in() ); + return S; +} + +//======================================================================= +//function : findShape +//purpose : +//======================================================================= + +static TopoDS_Shape findShape(const SMDS_MeshNode *aNode[], + TopoDS_Shape aShape, + const TopoDS_Shape shape[], + double** box, + const int nShape, + TopAbs_State * state = 0) +{ + gp_XYZ aPnt(0,0,0); + int j, iShape, nbNode = 4; + + for ( j=0; jX(), aNode[j]->Y(), aNode[j]->Z() ); + if ( aNode[j]->GetPosition()->GetTypeOfPosition() == SMDS_TOP_3DSPACE ) { + aPnt = p; + break; + } + aPnt += p / nbNode; + } + + BRepClass3d_SolidClassifier SC (aShape, aPnt, Precision::Confusion()); + if (state) *state = SC.State(); + if ( SC.State() != TopAbs_IN || aShape.IsNull() || aShape.ShapeType() != TopAbs_SOLID) { + for (iShape = 0; iShape < nShape; iShape++) { + aShape = shape[iShape]; + if ( !( aPnt.X() < box[iShape][0] || box[iShape][1] < aPnt.X() || + aPnt.Y() < box[iShape][2] || box[iShape][3] < aPnt.Y() || + aPnt.Z() < box[iShape][4] || box[iShape][5] < aPnt.Z()) ) { + BRepClass3d_SolidClassifier SC (aShape, aPnt, Precision::Confusion()); + if (state) *state = SC.State(); + if (SC.State() == TopAbs_IN) + break; + } + } + } + return aShape; +} + +//======================================================================= +//function : readMapIntLine +//purpose : +//======================================================================= + +static char* readMapIntLine(char* ptr, int tab[]) { + long int intVal; + std::cout << std::endl; + + for ( int i=0; i<17; i++ ) { + intVal = strtol(ptr, &ptr, 10); + if ( i < 3 ) + tab[i] = intVal; + } + return ptr; +} + +//================================================================================ +/*! + * \brief returns true if a triangle defined by the nodes is a temporary face on a + * side facet of pyramid and defines sub-domian inside the pyramid + */ +//================================================================================ + +static bool isTmpFace(const SMDS_MeshNode* node1, + const SMDS_MeshNode* node2, + const SMDS_MeshNode* node3) +{ + // find a pyramid sharing the 3 nodes + //const SMDS_MeshElement* pyram = 0; + SMDS_ElemIteratorPtr vIt1 = node1->GetInverseElementIterator(SMDSAbs_Volume); + while ( vIt1->more() ) + { + const SMDS_MeshElement* pyram = vIt1->next(); + if ( pyram->NbCornerNodes() != 5 ) continue; + int i2, i3; + if ( (i2 = pyram->GetNodeIndex( node2 )) >= 0 && + (i3 = pyram->GetNodeIndex( node3 )) >= 0 ) + { + // Triangle defines sub-domian inside the pyramid if it's + // normal points out of the pyram + + // make i2 and i3 hold indices of base nodes of the pyram while + // keeping the nodes order in the triangle + const int iApex = 4; + if ( i2 == iApex ) + i2 = i3, i3 = pyram->GetNodeIndex( node1 ); + else if ( i3 == iApex ) + i3 = i2, i2 = pyram->GetNodeIndex( node1 ); + + int i3base = (i2+1) % 4; // next index after i2 within the pyramid base + return ( i3base != i3 ); + } + } + return false; +} + +//======================================================================= +//function : findShapeID +//purpose : find the solid corresponding to GHS3D sub-domain following +// the technique proposed in GHS3D manual (available within +// ghs3d installation) in chapter "B.4 Subdomain (sub-region) assignment". +// In brief: normal of the triangle defined by the given nodes +// points out of the domain it is associated to +//======================================================================= + +static int findShapeID(SMESH_Mesh& mesh, + const SMDS_MeshNode* node1, + const SMDS_MeshNode* node2, + const SMDS_MeshNode* node3, + const bool toMeshHoles) +{ + const int invalidID = 0; + SMESHDS_Mesh* meshDS = mesh.GetMeshDS(); + + // face the nodes belong to + const SMDS_MeshElement * face = meshDS->FindFace(node1,node2,node3); + if ( !face ) + return isTmpFace(node1, node2, node3) ? HOLE_ID : invalidID; +#ifdef _DEBUG_ + std::cout << "bnd face " << face->GetID() << " - "; +#endif + // geom face the face assigned to + SMESH_MeshEditor editor(&mesh); + int geomFaceID = editor.FindShape( face ); + if ( !geomFaceID ) + return isTmpFace(node1, node2, node3) ? HOLE_ID : invalidID; + TopoDS_Shape shape = meshDS->IndexToShape( geomFaceID ); + if ( shape.IsNull() || shape.ShapeType() != TopAbs_FACE ) + return invalidID; + TopoDS_Face geomFace = TopoDS::Face( shape ); + + // solids bounded by geom face + TopTools_IndexedMapOfShape solids, shells; + TopTools_ListIteratorOfListOfShape ansIt = mesh.GetAncestors(geomFace); + for ( ; ansIt.More(); ansIt.Next() ) { + switch ( ansIt.Value().ShapeType() ) { + case TopAbs_SOLID: + solids.Add( ansIt.Value() ); break; + case TopAbs_SHELL: + shells.Add( ansIt.Value() ); break; + default:; + } + } + // analyse found solids + if ( solids.Extent() == 0 || shells.Extent() == 0) + return invalidID; + + const TopoDS_Solid& solid1 = TopoDS::Solid( solids(1) ); + if ( solids.Extent() == 1 ) + { + if ( toMeshHoles ) + return meshDS->ShapeToIndex( solid1 ); + + //////////// UNCOMMENT AS SOON AS + //////////// http://tracker.dev.opencascade.org/view.php?id=23129 + //////////// IS SOLVED + // - Are we at a hole boundary face? + // if ( shells(1).IsSame( BRepTools::OuterShell( solid1 )) ) + // { // - No, but maybe a hole is bound by two shapes? Does shells(1) touches another shell? + // bool touch = false; + // TopExp_Explorer eExp( shells(1), TopAbs_EDGE ); + // // check if any edge of shells(1) belongs to another shell + // for ( ; eExp.More() && !touch; eExp.Next() ) { + // ansIt = mesh.GetAncestors( eExp.Current() ); + // for ( ; ansIt.More() && !touch; ansIt.Next() ) { + // if ( ansIt.Value().ShapeType() == TopAbs_SHELL ) + // touch = ( !ansIt.Value().IsSame( shells(1) )); + // } + // } + // if (!touch) + // return meshDS->ShapeToIndex( solid1 ); + // } + } + // find orientation of geom face within the first solid + TopExp_Explorer fExp( solid1, TopAbs_FACE ); + for ( ; fExp.More(); fExp.Next() ) + if ( geomFace.IsSame( fExp.Current() )) { + geomFace = TopoDS::Face( fExp.Current() ); + break; + } + if ( !fExp.More() ) + return invalidID; // face not found + + // normale to triangle + gp_Pnt node1Pnt ( node1->X(), node1->Y(), node1->Z() ); + gp_Pnt node2Pnt ( node2->X(), node2->Y(), node2->Z() ); + gp_Pnt node3Pnt ( node3->X(), node3->Y(), node3->Z() ); + gp_Vec vec12( node1Pnt, node2Pnt ); + gp_Vec vec13( node1Pnt, node3Pnt ); + gp_Vec meshNormal = vec12 ^ vec13; + if ( meshNormal.SquareMagnitude() < DBL_MIN ) + return invalidID; + + // get normale to geomFace at any node + bool geomNormalOK = false; + gp_Vec geomNormal; + const SMDS_MeshNode* nodes[3] = { node1, node2, node3 }; + SMESH_MesherHelper helper( mesh ); helper.SetSubShape( geomFace ); + for ( int i = 0; !geomNormalOK && i < 3; ++i ) + { + // find UV of i-th node on geomFace + const SMDS_MeshNode* nNotOnSeamEdge = 0; + if ( helper.IsSeamShape( nodes[i]->getshapeId() )) { + if ( helper.IsSeamShape( nodes[(i+1)%3]->getshapeId() )) + nNotOnSeamEdge = nodes[(i+2)%3]; + else + nNotOnSeamEdge = nodes[(i+1)%3]; + } + bool uvOK; + gp_XY uv = helper.GetNodeUV( geomFace, nodes[i], nNotOnSeamEdge, &uvOK ); + // check that uv is correct + if (uvOK) { + double tol = 1e-6; + TopoDS_Shape nodeShape = helper.GetSubShapeByNode( nodes[i], meshDS ); + if ( !nodeShape.IsNull() ) + switch ( nodeShape.ShapeType() ) + { + case TopAbs_FACE: tol = BRep_Tool::Tolerance( TopoDS::Face( nodeShape )); break; + case TopAbs_EDGE: tol = BRep_Tool::Tolerance( TopoDS::Edge( nodeShape )); break; + case TopAbs_VERTEX: tol = BRep_Tool::Tolerance( TopoDS::Vertex( nodeShape )); break; + default:; + } + gp_Pnt nodePnt ( nodes[i]->X(), nodes[i]->Y(), nodes[i]->Z() ); + BRepAdaptor_Surface surface( geomFace ); + uvOK = ( nodePnt.Distance( surface.Value( uv.X(), uv.Y() )) < 2 * tol ); + if ( uvOK ) { + // normale to geomFace at UV + gp_Vec du, dv; + surface.D1( uv.X(), uv.Y(), nodePnt, du, dv ); + geomNormal = du ^ dv; + if ( geomFace.Orientation() == TopAbs_REVERSED ) + geomNormal.Reverse(); + geomNormalOK = ( geomNormal.SquareMagnitude() > DBL_MIN * 1e3 ); + } + } + } + if ( !geomNormalOK) + return invalidID; + + // compare normals + bool isReverse = ( meshNormal * geomNormal ) < 0; + if ( !isReverse ) + return meshDS->ShapeToIndex( solid1 ); + + if ( solids.Extent() == 1 ) + return HOLE_ID; // we are inside a hole + else + return meshDS->ShapeToIndex( solids(2) ); +} + +//======================================================================= +//function : countShape +//purpose : +//======================================================================= + +// template < class Mesh, class Shape > +// static int countShape( Mesh* mesh, Shape shape ) { +// TopExp_Explorer expShape ( mesh->ShapeToMesh(), shape ); +// TopTools_MapOfShape mapShape; +// int nbShape = 0; +// for ( ; expShape.More(); expShape.Next() ) { +// if (mapShape.Add(expShape.Current())) { +// nbShape++; +// } +// } +// return nbShape; +// } + +//======================================================================= +//function : getShape +//purpose : +//======================================================================= + +// template < class Mesh, class Shape, class Tab > +// void getShape(Mesh* mesh, Shape shape, Tab *t_Shape) { +// TopExp_Explorer expShape ( mesh->ShapeToMesh(), shape ); +// TopTools_MapOfShape mapShape; +// for ( int i=0; expShape.More(); expShape.Next() ) { +// if (mapShape.Add(expShape.Current())) { +// t_Shape[i] = expShape.Current(); +// i++; +// } +// } +// return; +// } + +// //======================================================================= +// //function : findEdgeID +// //purpose : +// //======================================================================= +// +// static int findEdgeID(const SMDS_MeshNode* aNode, +// const SMESHDS_Mesh* theMesh, +// const int nEdge, +// const TopoDS_Shape* t_Edge) { +// +// TopoDS_Shape aPntShape, foundEdge; +// TopoDS_Vertex aVertex; +// gp_Pnt aPnt( aNode->X(), aNode->Y(), aNode->Z() ); +// +// int foundInd, ind; +// double nearest = RealLast(), *t_Dist; +// double epsilon = Precision::Confusion(); +// +// t_Dist = new double[ nEdge ]; +// aPntShape = BRepBuilderAPI_MakeVertex( aPnt ).Shape(); +// aVertex = TopoDS::Vertex( aPntShape ); +// +// for ( ind=0; ind < nEdge; ind++ ) { +// BRepExtrema_DistShapeShape aDistance ( aVertex, t_Edge[ind] ); +// t_Dist[ind] = aDistance.Value(); +// if ( t_Dist[ind] < nearest ) { +// nearest = t_Dist[ind]; +// foundEdge = t_Edge[ind]; +// foundInd = ind; +// if ( nearest < epsilon ) +// ind = nEdge; +// } +// } +// +// delete [] t_Dist; +// return theMesh->ShapeToIndex( foundEdge ); +// } + + +//======================================================================= +//function : readGMFFile +//purpose : read GMF file with geometry associated to mesh +// TODO +//======================================================================= + +// static bool readGMFFile( +// const int fileOpen, +// const char* theFileName, +// SMESH_Mesh& theMesh, +// const int nbShape, +// const TopoDS_Shape* tabShape, +// double** tabBox, +// map & theGhs3dIdToNodeMap, +// bool toMeshHoles, +// int nbEnforcedVertices, +// int nbEnforcedNodes) +// { +// TopoDS_Shape aShape; +// TopoDS_Vertex aVertex; +// SMESHDS_Mesh* theMeshDS = theMesh.GetMeshDS(); +// int nbElem = 0, nbRef = 0, IdShapeRef = 1; +// int *tabID; +// int aGMFNodeID = 0; +// int compoundID = +// nbShape ? theMeshDS->ShapeToIndex( tabShape[0] ) : theMeshDS->ShapeToIndex( theMeshDS->ShapeToMesh() ); +// int tetraShapeID = compoundID; +// double epsilon = Precision::Confusion(); +// int *nodeAssigne, *GMFNodeAssigne; +// SMDS_MeshNode** GMFNode; +// TopoDS_Shape *tabCorner, *tabEdge; +// std::map tabRef; +// +// +// int ver, dim; +// MESSAGE("Read " << theFileName << " file"); +// int InpMsh = GmfOpenMesh(theFileName, GmfRead, &ver, &dim); +// if (!InpMsh) +// return false; +// +// // =========================== +// // Fill the tabID array: BEGIN +// // =========================== +// +// /* +// The output .mesh file does not contain yet the subdomain-info (Ghs3D 4.2) +// */ +// Kernel_Utils::Localizer loc; +// struct stat status; +// size_t length; +// +// char *ptr, *mapPtr; +// char *tetraPtr; +// int *tab = new int[3]; +// +// // Read the file state +// fstat(fileOpen, &status); +// length = status.st_size; +// +// // Mapping the result file into memory +// #ifdef WNT +// HANDLE fd = CreateFile(theFileName, GENERIC_READ, FILE_SHARE_READ, +// NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); +// HANDLE hMapObject = CreateFileMapping(fd, NULL, PAGE_READONLY, +// 0, (DWORD)length, NULL); +// ptr = ( char* ) MapViewOfFile(hMapObject, FILE_MAP_READ, 0, 0, 0 ); +// #else +// ptr = (char *) mmap(0,length,PROT_READ,MAP_PRIVATE,fileOpen,0); +// #endif +// mapPtr = ptr; +// +// ptr = readMapIntLine(ptr, tab); +// tetraPtr = ptr; +// +// nbElem = tab[0]; +// int nbNodes = tab[1]; +// +// for (int i=0; i < 4*nbElem; i++) +// strtol(ptr, &ptr, 10); +// +// for (int iNode=1; iNode <= nbNodes; iNode++) +// for (int iCoor=0; iCoor < 3; iCoor++) +// strtod(ptr, &ptr); +// +// +// // Reading the number of triangles which corresponds to the number of sub-domains +// int nbTriangle = strtol(ptr, &ptr, 10); +// +// +// // The keyword does not exist yet => to update when it is created +// // int nbTriangle = GmfStatKwd(InpMsh, GmfSubdomain); +// // int id_tri[3]; +// +// +// tabID = new int[nbTriangle]; +// for (int i=0; i < nbTriangle; i++) { +// tabID[i] = 0; +// int nodeId1, nodeId2, nodeId3; +// // find the solid corresponding to GHS3D sub-domain following +// // the technique proposed in GHS3D manual in chapter +// // "B.4 Subdomain (sub-region) assignment" +// +// nodeId1 = strtol(ptr, &ptr, 10); +// nodeId2 = strtol(ptr, &ptr, 10); +// nodeId3 = strtol(ptr, &ptr, 10); +// +// // // The keyword does not exist yet => to update when it is created +// // GmfGetLin(InpMsh, GmfSubdomain, &id_tri[0], &id_tri[1], &id_tri[2]); +// // nodeId1 = id_tri[0]; +// // nodeId2 = id_tri[1]; +// // nodeId3 = id_tri[2]; +// +// if ( nbTriangle > 1 ) { +// // get the nodes indices +// const SMDS_MeshNode* n1 = theGhs3dIdToNodeMap[ nodeId1 ]; +// const SMDS_MeshNode* n2 = theGhs3dIdToNodeMap[ nodeId2 ]; +// const SMDS_MeshNode* n3 = theGhs3dIdToNodeMap[ nodeId3 ]; +// try { +// OCC_CATCH_SIGNALS; +// tabID[i] = findShapeID( theMesh, n1, n2, n3, toMeshHoles ); +// // -- 0020330: Pb with ghs3d as a submesh +// // check that found shape is to be meshed +// if ( tabID[i] > 0 ) { +// const TopoDS_Shape& foundShape = theMeshDS->IndexToShape( tabID[i] ); +// bool isToBeMeshed = false; +// for ( int iS = 0; !isToBeMeshed && iS < nbShape; ++iS ) +// isToBeMeshed = foundShape.IsSame( tabShape[ iS ]); +// if ( !isToBeMeshed ) +// tabID[i] = HOLE_ID; +// } +// // END -- 0020330: Pb with ghs3d as a submesh +// #ifdef _DEBUG_ +// std::cout << i+1 << " subdomain: findShapeID() returns " << tabID[i] << std::endl; +// #endif +// } +// catch ( Standard_Failure & ex) +// { +// #ifdef _DEBUG_ +// std::cout << i+1 << " subdomain: Exception caugt: " << ex.GetMessageString() << std::endl; +// #endif +// } +// catch (...) { +// #ifdef _DEBUG_ +// std::cout << i+1 << " subdomain: unknown exception caught " << std::endl; +// #endif +// } +// } +// } +// +// // =========================== +// // Fill the tabID array: END +// // =========================== +// +// +// tabRef[GmfVertices] = 3; +// tabRef[GmfCorners] = 1; +// tabRef[GmfEdges] = 2; +// tabRef[GmfRidges] = 1; +// tabRef[GmfTriangles] = 3; +// // tabRef[GmfQuadrilaterals] = 4; +// tabRef[GmfTetrahedra] = 4; +// // tabRef[GmfHexahedra] = 8; +// +// SMDS_NodeIteratorPtr itOnGMFInputNode = theMeshDS->nodesIterator(); +// while ( itOnGMFInputNode->more() ) +// theMeshDS->RemoveNode( itOnGMFInputNode->next() ); +// +// +// int nbVertices = GmfStatKwd(InpMsh, GmfVertices); +// int nbCorners = max(countShape( theMeshDS, TopAbs_VERTEX ) , GmfStatKwd(InpMsh, GmfCorners)); +// int nbShapeEdge = countShape( theMeshDS, TopAbs_EDGE ); +// +// tabCorner = new TopoDS_Shape[ nbCorners ]; +// tabEdge = new TopoDS_Shape[ nbShapeEdge ]; +// nodeAssigne = new int[ nbVertices + 1 ]; +// GMFNodeAssigne = new int[ nbVertices + 1 ]; +// GMFNode = new SMDS_MeshNode*[ nbVertices + 1 ]; +// +// getShape(theMeshDS, TopAbs_VERTEX, tabCorner); +// getShape(theMeshDS, TopAbs_EDGE, tabEdge); +// +// std::map ::const_iterator it = tabRef.begin(); +// for ( ; it != tabRef.end() ; ++it) +// { +// // int dummy; +// GmfKwdCod token = it->first; +// nbRef = it->second; +// +// nbElem = GmfStatKwd(InpMsh, token); +// if (nbElem > 0) { +// GmfGotoKwd(InpMsh, token); +// std::cout << "Read " << nbElem; +// } +// else +// continue; +// +// int id[nbElem*tabRef[token]]; +// int ghs3dShapeID[nbElem]; +// +// if (token == GmfVertices) { +// std::cout << " vertices" << std::endl; +// int aGMFID; +// +// float VerTab_f[nbElem][3]; +// double VerTab_d[nbElem][3]; +// SMDS_MeshNode * aGMFNode; +// +// for ( int iElem = 0; iElem < nbElem; iElem++ ) { +// aGMFID = iElem + 1; +// if (ver == GmfFloat) { +// GmfGetLin(InpMsh, token, &VerTab_f[nbElem][0], &VerTab_f[nbElem][1], &VerTab_f[nbElem][2], &ghs3dShapeID[iElem]); +// aGMFNode = theMeshDS->AddNode(VerTab_f[nbElem][0], VerTab_f[nbElem][1], VerTab_f[nbElem][2]); +// } +// else { +// GmfGetLin(InpMsh, token, &VerTab_d[nbElem][0], &VerTab_d[nbElem][1], &VerTab_d[nbElem][2], &ghs3dShapeID[iElem]); +// aGMFNode = theMeshDS->AddNode(VerTab_d[nbElem][0], VerTab_d[nbElem][1], VerTab_d[nbElem][2]); +// } +// GMFNode[ aGMFID ] = aGMFNode; +// nodeAssigne[ aGMFID ] = 0; +// GMFNodeAssigne[ aGMFID ] = 0; +// } +// } +// else if (token == GmfCorners && nbElem > 0) { +// std::cout << " corners" << std::endl; +// for ( int iElem = 0; iElem < nbElem; iElem++ ) +// GmfGetLin(InpMsh, token, &id[iElem*tabRef[token]]); +// } +// else if (token == GmfRidges && nbElem > 0) { +// std::cout << " ridges" << std::endl; +// for ( int iElem = 0; iElem < nbElem; iElem++ ) +// GmfGetLin(InpMsh, token, &id[iElem*tabRef[token]]); +// } +// else if (token == GmfEdges && nbElem > 0) { +// std::cout << " edges" << std::endl; +// for ( int iElem = 0; iElem < nbElem; iElem++ ) +// GmfGetLin(InpMsh, token, &id[iElem*tabRef[token]], &id[iElem*tabRef[token]+1], &ghs3dShapeID[iElem]); +// } +// else if (token == GmfTriangles && nbElem > 0) { +// std::cout << " triangles" << std::endl; +// for ( int iElem = 0; iElem < nbElem; iElem++ ) +// GmfGetLin(InpMsh, token, &id[iElem*tabRef[token]], &id[iElem*tabRef[token]+1], &id[iElem*tabRef[token]+2], &ghs3dShapeID[iElem]); +// } +// // else if (token == GmfQuadrilaterals && nbElem > 0) { +// // std::cout << " Quadrilaterals" << std::endl; +// // for ( int iElem = 0; iElem < nbElem; iElem++ ) +// // GmfGetLin(InpMsh, token, &id[iElem*tabRef[token]], &id[iElem*tabRef[token]+1], &id[iElem*tabRef[token]+2], &id[iElem*tabRef[token]+3], &ghs3dShapeID[iElem]); +// // } +// else if (token == GmfTetrahedra && nbElem > 0) { +// std::cout << " Tetrahedra" << std::endl; +// for ( int iElem = 0; iElem < nbElem; iElem++ ) +// GmfGetLin(InpMsh, token, +// &id[iElem*tabRef[token]], +// &id[iElem*tabRef[token]+1], +// &id[iElem*tabRef[token]+2], +// &id[iElem*tabRef[token]+3], +// &ghs3dShapeID[iElem]); +// } +// // else if (token == GmfHexahedra && nbElem > 0) { +// // std::cout << " Hexahedra" << std::endl; +// // for ( int iElem = 0; iElem < nbElem; iElem++ ) +// // GmfGetLin(InpMsh, token, &id[iElem*tabRef[token]], &id[iElem*tabRef[token]+1], &id[iElem*tabRef[token]+2], &id[iElem*tabRef[token]+3], +// // &id[iElem*tabRef[token]+4], &id[iElem*tabRef[token]+5], &id[iElem*tabRef[token]+6], &id[iElem*tabRef[token]+7], &ghs3dShapeID[iElem]); +// // } +// +// switch (token) { +// case GmfCorners: +// case GmfRidges: +// case GmfEdges: +// case GmfTriangles: +// // case GmfQuadrilaterals: +// case GmfTetrahedra: +// // case GmfHexahedra: +// { +// int nodeDim, shapeID, *nodeID; +// SMDS_MeshNode** node; +// // std::vector< SMDS_MeshNode* > enfNode( nbRef ); +// SMDS_MeshElement * aGMFElement; +// +// node = new SMDS_MeshNode*[nbRef]; +// nodeID = new int[ nbRef ]; +// +// for ( int iElem = 0; iElem < nbElem; iElem++ ) +// { +// for ( int iRef = 0; iRef < nbRef; iRef++ ) +// { +// aGMFNodeID = id[iElem*tabRef[token]+iRef]; // read nbRef aGMFNodeID +// node [ iRef ] = GMFNode[ aGMFNodeID ]; +// nodeID[ iRef ] = aGMFNodeID; +// } +// +// switch (token) +// { +// case GmfCorners: { +// nodeDim = 1; +// gp_Pnt GMFPnt ( node[0]->X(), node[0]->Y(), node[0]->Z() ); +// for ( int i=0; iAddEdge( node[0], node[1] ); +// int iNode = 1; +// if ( GMFNodeAssigne[ nodeID[0] ] == 0 || GMFNodeAssigne[ nodeID[0] ] == 2 ) +// iNode = 0; +// shapeID = findEdgeID( node[iNode], theMeshDS, nbShapeEdge, tabEdge ); +// break; +// } +// case GmfRidges: +// break; +// case GmfTriangles: { +// nodeDim = 3; +// aGMFElement = theMeshDS->AddFace( node[0], node[1], node[2]); +// shapeID = -1; +// break; +// } +// // case GmfQuadrilaterals: { +// // nodeDim = 4; +// // aGMFElement = theMeshDS->AddFace( node[0], node[1], node[2], node[3] ); +// // shapeID = -1; +// // break; +// // } +// case GmfTetrahedra: { +// +// // IN WORK +// TopoDS_Shape aSolid; +// // We always run GHS3D with "to mesh holes"==TRUE but we must not create +// // tetras within holes depending on hypo option, +// // so we first check if aTet is inside a hole and then create it +// if ( nbTriangle > 1 ) { +// tetraShapeID = HOLE_ID; // negative tetraShapeID means not to create tetras if !toMeshHoles +// int aGhs3dShapeID = ghs3dShapeID[iElem] - IdShapeRef; +// if ( tabID[ aGhs3dShapeID ] == 0 ) { +// TopAbs_State state; +// aSolid = findShape(node, aSolid, tabShape, tabBox, nbShape, &state); +// if ( toMeshHoles || state == TopAbs_IN ) +// tetraShapeID = theMeshDS->ShapeToIndex( aSolid ); +// tabID[ aGhs3dShapeID ] = tetraShapeID; +// } +// else +// tetraShapeID = tabID[ aGhs3dShapeID ]; +// } +// else if ( nbShape > 1 ) { +// // Case where nbTriangle == 1 while nbShape == 2 encountered +// // with compound of 2 boxes and "To mesh holes"==False, +// // so there are no subdomains specified for each tetrahedron. +// // Try to guess a solid by a node already bound to shape +// tetraShapeID = 0; +// for ( int i=0; i<4 && tetraShapeID==0; i++ ) { +// if ( nodeAssigne[ nodeID[i] ] == 1 && +// node[i]->GetPosition()->GetTypeOfPosition() == SMDS_TOP_3DSPACE && +// node[i]->getshapeId() > 1 ) +// { +// tetraShapeID = node[i]->getshapeId(); +// } +// } +// if ( tetraShapeID==0 ) { +// aSolid = findShape(node, aSolid, tabShape, tabBox, nbShape); +// tetraShapeID = theMeshDS->ShapeToIndex( aSolid ); +// } +// } +// // set new nodes and tetrahedron onto the shape +// for ( int i=0; i<4; i++ ) { +// if ( nodeAssigne[ nodeID[i] ] == 0 ) { +// if ( tetraShapeID != HOLE_ID ) +// theMeshDS->SetNodeInVolume( node[i], tetraShapeID ); +// nodeAssigne[ nodeID[i] ] = tetraShapeID; +// } +// } +// if ( toMeshHoles || tetraShapeID != HOLE_ID ) { +// aGMFElement = theMeshDS->AddVolume( node[1], node[0], node[2], node[3] ); +// theMeshDS->SetMeshElementOnShape( aGMFElement, tetraShapeID ); +// } +// +// // IN WORK +// +// nodeDim = 5; +// break; +// } +// // case GmfHexahedra: { +// // nodeDim = 6; +// // aGMFElement = theMeshDS->AddVolume( node[0], node[3], node[2], node[1], +// // node[4], node[7], node[6], node[5] ); +// // break; +// // } +// default: continue; +// } +// if (token != GmfRidges) +// { +// for ( int i=0; iSetNodeOnVertex( node[0], aVertex ); +// else if ( token == GmfEdges ) theMeshDS->SetNodeOnEdge( node[i], shapeID ); +// else if ( token == GmfTriangles ) theMeshDS->SetNodeOnFace( node[i], shapeID ); +// GMFNodeAssigne[ nodeID[i] ] = nodeDim; +// } +// } +// if ( token != "Corners" ) +// theMeshDS->SetMeshElementOnShape( aGMFElement, shapeID ); +// } +// } // for +// +// if ( !toMeshHoles ) { +// map ::iterator itOnNode = theGhs3dIdToNodeMap.find( nbVertices-(nbEnforcedVertices+nbEnforcedNodes) ); +// for ( ; itOnNode != theGhs3dIdToNodeMap.end(); ++itOnNode) { +// if ( nodeAssigne[ itOnNode->first ] == HOLE_ID ) +// theMeshDS->RemoveFreeNode( itOnNode->second, 0 ); +// } +// } +// +// delete [] node; +// delete [] nodeID; +// break; +// } // case GmfTetrahedra +// } // switch(token) +// } // for +// cout << std::endl; +// +// #ifdef WNT +// UnmapViewOfFile(mapPtr); +// CloseHandle(hMapObject); +// CloseHandle(fd); +// #else +// munmap(mapPtr, length); +// #endif +// close(fileOpen); +// +// delete [] tabID; +// delete [] tabCorner; +// delete [] tabEdge; +// delete [] nodeAssigne; +// delete [] GMFNodeAssigne; +// delete [] GMFNode; +// +// return true; +// } + + +//======================================================================= +//function : addElemInMeshGroup +//purpose : Update or create groups in mesh +//======================================================================= + +static void addElemInMeshGroup(SMESH_Mesh* theMesh, + const SMDS_MeshElement* anElem, + std::string groupName, + std::set groupsToRemove) +{ + bool groupDone = false; + SMESH_Mesh::GroupIteratorPtr grIt = theMesh->GetGroups(); + while (grIt->more()) { + SMESH_Group * group = grIt->next(); + if ( !group ) continue; + SMESHDS_GroupBase* groupDS = group->GetGroupDS(); + if ( !groupDS ) continue; + if ( groupDS->GetType()==anElem->GetType() &&groupName.compare(group->GetName())==0) { + SMESHDS_Group* aGroupDS = static_cast( groupDS ); + aGroupDS->SMDSGroup().Add(anElem); + groupDone = true; +// MESSAGE("Successfully added enforced element to existing group " << groupName); + break; + } + } + + if (!groupDone) + { + int groupId; + SMESH_Group* aGroup = theMesh->AddGroup(anElem->GetType(), groupName.c_str(), groupId); + aGroup->SetName( groupName.c_str() ); + SMESHDS_Group* aGroupDS = static_cast( aGroup->GetGroupDS() ); + aGroupDS->SMDSGroup().Add(anElem); +// MESSAGE("Successfully created enforced vertex group " << groupName); + groupDone = true; + } + if (!groupDone) + throw SALOME_Exception(LOCALIZED("A enforced vertex node was not added to a group")); +} + + +//======================================================================= +//function : updateMeshGroups +//purpose : Update or create groups in mesh +//======================================================================= + +static void updateMeshGroups(SMESH_Mesh* theMesh, std::set groupsToRemove) +{ + SMESH_Mesh::GroupIteratorPtr grIt = theMesh->GetGroups(); + while (grIt->more()) { + SMESH_Group * group = grIt->next(); + if ( !group ) continue; + SMESHDS_GroupBase* groupDS = group->GetGroupDS(); + if ( !groupDS ) continue; + std::string currentGroupName = (string)group->GetName(); + if (groupDS->IsEmpty() && groupsToRemove.find(currentGroupName) != groupsToRemove.end()) { + // Previous group created by enforced elements + MESSAGE("Delete previous group created by removed enforced elements: " << group->GetName()) + theMesh->RemoveGroup(groupDS->GetID()); + } + } +} + +//======================================================================= +//function : readGMFFile +//purpose : read GMF file w/o geometry associated to mesh +//======================================================================= + +static bool readGMFFile(const char* theFile, +#ifdef WITH_SMESH_CANCEL_COMPUTE + GHS3DPlugin_GHS3D* theAlgo, +#endif + SMESH_MesherHelper* theHelper, + TopoDS_Shape theSolid, + vector & theNodeByGhs3dId, + map & theNodeToGhs3dIdMap, + std::vector & aNodeGroupByGhs3dId, + std::vector & anEdgeGroupByGhs3dId, + std::vector & aFaceGroupByGhs3dId, + std::set & groupsToRemove + ) +{ + std::string tmpStr; + SMESHDS_Mesh* theMeshDS = theHelper->GetMeshDS(); + + int nbInitialNodes = theNodeByGhs3dId.size(); + int nbMeshNodes = theMeshDS->NbNodes(); + + const bool isQuadMesh = + theHelper->GetMesh()->NbEdges( ORDER_QUADRATIC ) || + theHelper->GetMesh()->NbFaces( ORDER_QUADRATIC ) || + theHelper->GetMesh()->NbVolumes( ORDER_QUADRATIC ); + +#ifdef _DEBUG_ + std::cout << "theNodeByGhs3dId.size(): " << nbInitialNodes << std::endl; + std::cout << "theHelper->GetMesh()->NbNodes(): " << nbMeshNodes << std::endl; + std::cout << "isQuadMesh: " << isQuadMesh << std::endl; +#endif + + if (theHelper->GetSubShapeID() != 0) + theHelper->IsQuadraticSubMesh( theHelper->GetSubShape() ); + + // --------------------------------- + // Read generated elements and nodes + // --------------------------------- + + int nbElem = 0, nbRef = 0; + int aGMFNodeID = 0/*, shapeID*/; + //int *nodeAssigne; + const SMDS_MeshNode** GMFNode; +#ifdef _DEBUG_ + std::map > subdomainId2tetraId; +#endif + std::map tabRef; + + tabRef[GmfVertices] = 3; // for new nodes and enforced nodes + tabRef[GmfCorners] = 1; + tabRef[GmfEdges] = 2; // for enforced edges + tabRef[GmfRidges] = 1; + tabRef[GmfTriangles] = 3; // for enforced faces + tabRef[GmfQuadrilaterals] = 4; + tabRef[GmfTetrahedra] = 4; // for new tetras + tabRef[GmfHexahedra] = 8; + + int ver, dim; + MESSAGE("Read " << theFile << " file"); + int InpMsh = GmfOpenMesh(theFile, GmfRead, &ver, &dim); + if (!InpMsh) + return false; + MESSAGE("Done "); + + // Issue 0020682. Avoid creating nodes and tetras at place where + // volumic elements already exist + SMESH_ElementSearcher* elemSearcher = 0; + vector< const SMDS_MeshElement* > foundVolumes; + if ( theHelper->GetMesh()->NbVolumes() > 0 ) + elemSearcher = SMESH_MeshEditor( theHelper->GetMesh() ).GetElementSearcher(); + + int nbVertices = GmfStatKwd(InpMsh, GmfVertices) - nbInitialNodes; + GMFNode = new const SMDS_MeshNode*[ nbVertices + 1 ]; + //nodeAssigne = new int[ nbVertices + 1 ]; + + std::map ::const_iterator it = tabRef.begin(); + for ( ; it != tabRef.end() ; ++it) + { +#ifdef WITH_SMESH_CANCEL_COMPUTE + if(theAlgo->computeCanceled()) { + GmfCloseMesh(InpMsh); + delete [] GMFNode; + //delete [] nodeAssigne; + return false; + } +#endif + int dummy; + GmfKwdCod token = it->first; + nbRef = it->second; + + nbElem = GmfStatKwd(InpMsh, token); + if (nbElem > 0) { + GmfGotoKwd(InpMsh, token); + std::cout << "Read " << nbElem; + } + else + continue; + + std::vector id (nbElem*tabRef[token]); // node ids + + if (token == GmfVertices) { + (nbElem <= 1) ? tmpStr = " vertex" : tmpStr = " vertices"; +// std::cout << nbInitialNodes << " from input mesh " << std::endl; + + // Remove orphan nodes from previous enforced mesh which was cleared +// if ( nbElem < nbMeshNodes ) { +// const SMDS_MeshNode* node; +// SMDS_NodeIteratorPtr nodeIt = theMeshDS->nodesIterator(); +// while ( nodeIt->more() ) +// { +// node = nodeIt->next(); +// if (theNodeToGhs3dIdMap.find(node) != theNodeToGhs3dIdMap.end()) +// theMeshDS->RemoveNode(node); +// } +// } + + + int aGMFID; + + float VerTab_f[3]; + double x, y, z; + const SMDS_MeshNode * aGMFNode; + + //shapeID = theMeshDS->ShapeToIndex( theSolid ); + for ( int iElem = 0; iElem < nbElem; iElem++ ) { +#ifdef WITH_SMESH_CANCEL_COMPUTE + if(theAlgo->computeCanceled()) { + GmfCloseMesh(InpMsh); + delete [] GMFNode; + //delete [] nodeAssigne; + return false; + } +#endif + if (ver == GmfFloat) { + GmfGetLin(InpMsh, token, &VerTab_f[0], &VerTab_f[1], &VerTab_f[2], &dummy); + x = VerTab_f[0]; + y = VerTab_f[1]; + z = VerTab_f[2]; + } + else { + GmfGetLin(InpMsh, token, &x, &y, &z, &dummy); + } + if (iElem >= nbInitialNodes) { + if ( elemSearcher && + elemSearcher->FindElementsByPoint( gp_Pnt(x,y,z), SMDSAbs_Volume, foundVolumes)) + aGMFNode = 0; + else + aGMFNode = theHelper->AddNode(x, y, z); + + aGMFID = iElem -nbInitialNodes +1; + GMFNode[ aGMFID ] = aGMFNode; + //nodeAssigne[ aGMFID ] = 0; + if (aGMFID-1 < aNodeGroupByGhs3dId.size() && !aNodeGroupByGhs3dId.at(aGMFID-1).empty()) + addElemInMeshGroup(theHelper->GetMesh(), aGMFNode, aNodeGroupByGhs3dId.at(aGMFID-1), groupsToRemove); + } + } + } + else if (token == GmfCorners && nbElem > 0) { + (nbElem <= 1) ? tmpStr = " corner" : tmpStr = " corners"; + for ( int iElem = 0; iElem < nbElem; iElem++ ) + GmfGetLin(InpMsh, token, &id[iElem*tabRef[token]]); + } + else if (token == GmfRidges && nbElem > 0) { + (nbElem <= 1) ? tmpStr = " ridge" : tmpStr = " ridges"; + for ( int iElem = 0; iElem < nbElem; iElem++ ) + GmfGetLin(InpMsh, token, &id[iElem*tabRef[token]]); + } + else if (token == GmfEdges && nbElem > 0) { + (nbElem <= 1) ? tmpStr = " edge" : tmpStr = " edges"; + for ( int iElem = 0; iElem < nbElem; iElem++ ) + GmfGetLin(InpMsh, token, &id[iElem*tabRef[token]], &id[iElem*tabRef[token]+1], &dummy); + } + else if (token == GmfTriangles && nbElem > 0) { + (nbElem <= 1) ? tmpStr = " triangle" : tmpStr = " triangles"; + for ( int iElem = 0; iElem < nbElem; iElem++ ) + GmfGetLin(InpMsh, token, &id[iElem*tabRef[token]], &id[iElem*tabRef[token]+1], &id[iElem*tabRef[token]+2], &dummy); + } + else if (token == GmfQuadrilaterals && nbElem > 0) { + (nbElem <= 1) ? tmpStr = " Quadrilateral" : tmpStr = " Quadrilaterals"; + for ( int iElem = 0; iElem < nbElem; iElem++ ) + GmfGetLin(InpMsh, token, &id[iElem*tabRef[token]], &id[iElem*tabRef[token]+1], &id[iElem*tabRef[token]+2], &id[iElem*tabRef[token]+3], &dummy); + } + else if (token == GmfTetrahedra && nbElem > 0) { + (nbElem <= 1) ? tmpStr = " Tetrahedron" : tmpStr = " Tetrahedra"; + for ( int iElem = 0; iElem < nbElem; iElem++ ) { + GmfGetLin(InpMsh, token, &id[iElem*tabRef[token]], &id[iElem*tabRef[token]+1], &id[iElem*tabRef[token]+2], &id[iElem*tabRef[token]+3], &dummy); +#ifdef _DEBUG_ + subdomainId2tetraId[dummy].insert(iElem+1); +// MESSAGE("subdomainId2tetraId["< 0) { + (nbElem <= 1) ? tmpStr = " Hexahedron" : tmpStr = " Hexahedra"; + for ( int iElem = 0; iElem < nbElem; iElem++ ) + GmfGetLin(InpMsh, token, &id[iElem*tabRef[token]], &id[iElem*tabRef[token]+1], &id[iElem*tabRef[token]+2], &id[iElem*tabRef[token]+3], + &id[iElem*tabRef[token]+4], &id[iElem*tabRef[token]+5], &id[iElem*tabRef[token]+6], &id[iElem*tabRef[token]+7], &dummy); + } + std::cout << tmpStr << std::endl; + std::cout << std::endl; + + switch (token) { + case GmfCorners: + case GmfRidges: + case GmfEdges: + case GmfTriangles: + case GmfQuadrilaterals: + case GmfTetrahedra: + case GmfHexahedra: + { + std::vector< const SMDS_MeshNode* > node( nbRef ); + std::vector< int > nodeID( nbRef ); + std::vector< SMDS_MeshNode* > enfNode( nbRef ); + const SMDS_MeshElement* aCreatedElem; + + for ( int iElem = 0; iElem < nbElem; iElem++ ) + { +#ifdef WITH_SMESH_CANCEL_COMPUTE + if(theAlgo->computeCanceled()) { + GmfCloseMesh(InpMsh); + delete [] GMFNode; + //delete [] nodeAssigne; + return false; + } +#endif + // Check if elem is already in input mesh. If yes => skip + bool fullyCreatedElement = false; // if at least one of the nodes was created + for ( int iRef = 0; iRef < nbRef; iRef++ ) + { + aGMFNodeID = id[iElem*tabRef[token]+iRef]; // read nbRef aGMFNodeID + if (aGMFNodeID <= nbInitialNodes) // input nodes + { + aGMFNodeID--; + node[ iRef ] = theNodeByGhs3dId[aGMFNodeID]; + } + else + { + fullyCreatedElement = true; + aGMFNodeID -= nbInitialNodes; + nodeID[ iRef ] = aGMFNodeID ; + node [ iRef ] = GMFNode[ aGMFNodeID ]; + } + } + + switch (token) + { + case GmfEdges: + if (fullyCreatedElement) { + aCreatedElem = theHelper->AddEdge( node[0], node[1], /*id =*/0, /*force3d =*/false ); + if (anEdgeGroupByGhs3dId.size() && !anEdgeGroupByGhs3dId[iElem].empty()) + addElemInMeshGroup(theHelper->GetMesh(), aCreatedElem, anEdgeGroupByGhs3dId[iElem], groupsToRemove); + } + break; + case GmfTriangles: + if (fullyCreatedElement) { + aCreatedElem = theHelper->AddFace( node[0], node[1], node[2], /*id =*/0, /*force3d =*/false ); + // for ( int iRef = 0; iRef < nbRef; iRef++ ) + // nodeAssigne[ nodeID[ iRef ]] = 1; + if (aFaceGroupByGhs3dId.size() && !aFaceGroupByGhs3dId[iElem].empty()) + addElemInMeshGroup(theHelper->GetMesh(), aCreatedElem, aFaceGroupByGhs3dId[iElem], groupsToRemove); + } + break; + case GmfQuadrilaterals: + if (fullyCreatedElement) { + theHelper->AddFace( node[0], node[1], node[2], node[3], /*id =*/0, /*force3d =*/false ); + // for ( int iRef = 0; iRef < nbRef; iRef++ ) + // nodeAssigne[ nodeID[ iRef ]] = 1; + } + case GmfTetrahedra: + if ( elemSearcher ) { + // Issue 0020682. Avoid creating nodes and tetras at place where + // volumic elements already exist + if ( !node[1] || !node[0] || !node[2] || !node[3] ) + continue; + if ( elemSearcher->FindElementsByPoint((SMESH_TNodeXYZ(node[0]) + + SMESH_TNodeXYZ(node[1]) + + SMESH_TNodeXYZ(node[2]) + + SMESH_TNodeXYZ(node[3]) ) / 4., + SMDSAbs_Volume, foundVolumes )) + break; + } + theHelper->AddVolume( node[1], node[0], node[2], node[3], /*id =*/0, /*force3d =*/false ); +// theMeshDS->SetMeshElementOnShape( aTet, shapeID ); + break; + case GmfHexahedra: + if ( elemSearcher ) { + // Issue 0020682. Avoid creating nodes and tetras at place where + // volumic elements already exist + if ( !node[1] || !node[0] || !node[2] || !node[3] || !node[4] || !node[5] || !node[6] || !node[7]) + continue; + if ( elemSearcher->FindElementsByPoint((SMESH_TNodeXYZ(node[0]) + + SMESH_TNodeXYZ(node[1]) + + SMESH_TNodeXYZ(node[2]) + + SMESH_TNodeXYZ(node[3]) + + SMESH_TNodeXYZ(node[4]) + + SMESH_TNodeXYZ(node[5]) + + SMESH_TNodeXYZ(node[6]) + + SMESH_TNodeXYZ(node[7])) / 8., + SMDSAbs_Volume, foundVolumes )) + break; + } + theHelper->AddVolume( node[0], node[3], node[2], node[1], + node[4], node[7], node[6], node[5], /*id =*/0, /*force3d =*/false ); +// theMeshDS->SetMeshElementOnShape( aTet, shapeID ); + break; + default: continue; + } + } + break; + } + } + } + + // for ( int i = 0; i < nbVertices; ++i ) { + // if ( !nodeAssigne[ i+1 ]) + // theMeshDS->SetNodeInVolume( GMFNode[ i+1 ], shapeID ); + // } + + GmfCloseMesh(InpMsh); + delete [] GMFNode; + //delete [] nodeAssigne; +#ifdef _DEBUG_ + MESSAGE("Nb subdomains " << subdomainId2tetraId.size()); + std::map >::const_iterator subdomainIt = subdomainId2tetraId.begin(); + TCollection_AsciiString aSubdomainFileName = theFile; + aSubdomainFileName = aSubdomainFileName + ".subdomain"; + ofstream aSubdomainFile ( aSubdomainFileName.ToCString() , ios::out); + + aSubdomainFile << "Nb subdomains " << subdomainId2tetraId.size() << std::endl; + for(;subdomainIt != subdomainId2tetraId.end() ; ++subdomainIt) { + int subdomainId = subdomainIt->first; + std::set tetraIds = subdomainIt->second; + MESSAGE("Subdomain #"<::const_iterator tetraIdsIt = tetraIds.begin(); + aSubdomainFile << subdomainId << std::endl; + for(;tetraIdsIt != tetraIds.end() ; ++tetraIdsIt) { + aSubdomainFile << (*tetraIdsIt) << " "; + } + aSubdomainFile << std::endl; + } + aSubdomainFile.close(); +#endif + + return true; +} + +static bool writeGMFFile(const char* theMeshFileName, + const char* theRequiredFileName, + const char* theSolFileName, + const SMESH_ProxyMesh& theProxyMesh, + SMESH_Mesh * theMesh, + std::vector & theNodeByGhs3dId, + std::map & aNodeToGhs3dIdMap, + std::vector & aNodeGroupByGhs3dId, + std::vector & anEdgeGroupByGhs3dId, + std::vector & aFaceGroupByGhs3dId, + GHS3DPlugin_Hypothesis::TIDSortedNodeGroupMap & theEnforcedNodes, + GHS3DPlugin_Hypothesis::TIDSortedElemGroupMap & theEnforcedEdges, + GHS3DPlugin_Hypothesis::TIDSortedElemGroupMap & theEnforcedTriangles, + std::map, std::string> & enfVerticesWithGroup, + GHS3DPlugin_Hypothesis::TGHS3DEnforcedVertexCoordsValues & theEnforcedVertices) +{ + MESSAGE("writeGMFFile w/o geometry"); + std::string tmpStr; + int idx, idxRequired = 0, idxSol = 0; + const int dummyint = 0; + GHS3DPlugin_Hypothesis::TGHS3DEnforcedVertexCoordsValues::const_iterator vertexIt; + std::vector enfVertexSizes; + const SMDS_MeshElement* elem; + TIDSortedElemSet anElemSet, theKeptEnforcedEdges, theKeptEnforcedTriangles; + SMDS_ElemIteratorPtr nodeIt; + std::vector theEnforcedNodeByGhs3dId; + map anEnforcedNodeToGhs3dIdMap, anExistingEnforcedNodeToGhs3dIdMap; + std::vector< const SMDS_MeshElement* > foundElems; + map aNodeToTopAbs_StateMap; + int nbFoundElems; + GHS3DPlugin_Hypothesis::TIDSortedElemGroupMap::iterator elemIt; + TIDSortedElemSet::iterator elemSetIt; + bool isOK; + auto_ptr< SMESH_ElementSearcher > pntCls ( SMESH_MeshEditor( theMesh ).GetElementSearcher()); + + int nbEnforcedVertices = theEnforcedVertices.size(); + + // count faces + int nbFaces = theProxyMesh.NbFaces(); + int nbNodes; + + // groups management + int usedEnforcedNodes = 0; + std::string gn = ""; + + if ( nbFaces == 0 ) + return false; + + idx = GmfOpenMesh(theMeshFileName, GmfWrite, GMFVERSION, GMFDIMENSION); + if (!idx) + return false; + + /* ========================== FACES ========================== */ + /* TRIANGLES ========================== */ + SMDS_ElemIteratorPtr eIt = theProxyMesh.GetFaces(); + while ( eIt->more() ) + { + elem = eIt->next(); + anElemSet.insert(elem); + nodeIt = elem->nodesIterator(); + nbNodes = elem->NbCornerNodes(); + while ( nodeIt->more() && nbNodes--) + { + // find GHS3D ID + const SMDS_MeshNode* node = castToNode( nodeIt->next() ); + int newId = aNodeToGhs3dIdMap.size() + 1; // ghs3d ids count from 1 + aNodeToGhs3dIdMap.insert( make_pair( node, newId )); + } + } + + /* EDGES ========================== */ + + // Iterate over the enforced edges + for(elemIt = theEnforcedEdges.begin() ; elemIt != theEnforcedEdges.end() ; ++elemIt) { + elem = elemIt->first; + isOK = true; + nodeIt = elem->nodesIterator(); + nbNodes = 2; + while ( nodeIt->more() && nbNodes-- ) { + // find GHS3D ID + const SMDS_MeshNode* node = castToNode( nodeIt->next() ); + // Test if point is inside shape to mesh + gp_Pnt myPoint(node->X(),node->Y(),node->Z()); + TopAbs_State result = pntCls->GetPointState( myPoint ); + if ( result == TopAbs_OUT ) { + isOK = false; + break; + } + aNodeToTopAbs_StateMap.insert( make_pair( node, result )); + } + if (isOK) { + nodeIt = elem->nodesIterator(); + nbNodes = 2; + int newId = -1; + while ( nodeIt->more() && nbNodes-- ) { + // find GHS3D ID + const SMDS_MeshNode* node = castToNode( nodeIt->next() ); + gp_Pnt myPoint(node->X(),node->Y(),node->Z()); + nbFoundElems = pntCls->FindElementsByPoint(myPoint, SMDSAbs_Node, foundElems); +#ifdef _DEBUG_ + std::cout << "Node at "<X()<<", "<Y()<<", "<Z()<first; + isOK = true; + nodeIt = elem->nodesIterator(); + nbNodes = 3; + while ( nodeIt->more() && nbNodes--) { + // find GHS3D ID + const SMDS_MeshNode* node = castToNode( nodeIt->next() ); + // Test if point is inside shape to mesh + gp_Pnt myPoint(node->X(),node->Y(),node->Z()); + TopAbs_State result = pntCls->GetPointState( myPoint ); + if ( result == TopAbs_OUT ) { + isOK = false; + break; + } + aNodeToTopAbs_StateMap.insert( make_pair( node, result )); + } + if (isOK) { + nodeIt = elem->nodesIterator(); + nbNodes = 3; + int newId = -1; + while ( nodeIt->more() && nbNodes--) { + // find GHS3D ID + const SMDS_MeshNode* node = castToNode( nodeIt->next() ); + gp_Pnt myPoint(node->X(),node->Y(),node->Z()); + nbFoundElems = pntCls->FindElementsByPoint(myPoint, SMDSAbs_Node, foundElems); +#ifdef _DEBUG_ + std::cout << "Nb nodes found : "<::const_iterator n2id = aNodeToGhs3dIdMap.begin(); + for ( ; n2id != aNodeToGhs3dIdMap.end(); ++ n2id) + { +// std::cout << "n2id->first: "<first<second - 1 ] = n2id->first; // ghs3d ids count from 1 + } + + // put nodes to anEnforcedNodeToGhs3dIdMap vector +#ifdef _DEBUG_ + std::cout << "anEnforcedNodeToGhs3dIdMap.size(): "<second > aNodeToGhs3dIdMap.size()) { + theEnforcedNodeByGhs3dId[ n2id->second - aNodeToGhs3dIdMap.size() - 1 ] = n2id->first; // ghs3d ids count from 1 + } + } + + + /* ========================== NODES ========================== */ + vector theOrderedNodes, theRequiredNodes; + std::set< std::vector > nodesCoords; + vector::const_iterator ghs3dNodeIt = theNodeByGhs3dId.begin(); + vector::const_iterator after = theNodeByGhs3dId.end(); + + (theNodeByGhs3dId.size() <= 1) ? tmpStr = " node" : " nodes"; + std::cout << theNodeByGhs3dId.size() << tmpStr << " from mesh ..." << std::endl; + for ( ; ghs3dNodeIt != after; ++ghs3dNodeIt ) + { + const SMDS_MeshNode* node = *ghs3dNodeIt; + std::vector coords; + coords.push_back(node->X()); + coords.push_back(node->Y()); + coords.push_back(node->Z()); + nodesCoords.insert(coords); + theOrderedNodes.push_back(node); + } + + // Iterate over the enforced nodes given by enforced elements + ghs3dNodeIt = theEnforcedNodeByGhs3dId.begin(); + after = theEnforcedNodeByGhs3dId.end(); + (theEnforcedNodeByGhs3dId.size() <= 1) ? tmpStr = " node" : " nodes"; + std::cout << theEnforcedNodeByGhs3dId.size() << tmpStr << " from enforced elements ..." << std::endl; + for ( ; ghs3dNodeIt != after; ++ghs3dNodeIt ) + { + const SMDS_MeshNode* node = *ghs3dNodeIt; + std::vector coords; + coords.push_back(node->X()); + coords.push_back(node->Y()); + coords.push_back(node->Z()); +#ifdef _DEBUG_ + std::cout << "Node at " << node->X()<<", " <Y()<<", " <Z(); +#endif + + if (nodesCoords.find(coords) != nodesCoords.end()) { + // node already exists in original mesh +#ifdef _DEBUG_ + std::cout << " found" << std::endl; +#endif + continue; + } + + if (theEnforcedVertices.find(coords) != theEnforcedVertices.end()) { + // node already exists in enforced vertices +#ifdef _DEBUG_ + std::cout << " found" << std::endl; +#endif + continue; + } + +// gp_Pnt myPoint(node->X(),node->Y(),node->Z()); +// nbFoundElems = pntCls->FindElementsByPoint(myPoint, SMDSAbs_Node, foundElems); +// if (nbFoundElems ==0) { +// std::cout << " not found" << std::endl; +// if ((*aNodeToTopAbs_StateMap.find(node)).second == TopAbs_IN) { +// nodesCoords.insert(coords); +// theOrderedNodes.push_back(node); +// } +// } +// else { +// std::cout << " found in initial mesh" << std::endl; +// const SMDS_MeshNode* existingNode = (SMDS_MeshNode*) foundElems.at(0); +// nodesCoords.insert(coords); +// theOrderedNodes.push_back(existingNode); +// } + +#ifdef _DEBUG_ + std::cout << " not found" << std::endl; +#endif + + nodesCoords.insert(coords); + theOrderedNodes.push_back(node); +// theRequiredNodes.push_back(node); + } + + + // Iterate over the enforced nodes + GHS3DPlugin_Hypothesis::TIDSortedNodeGroupMap::const_iterator enfNodeIt; + (theEnforcedNodes.size() <= 1) ? tmpStr = " node" : " nodes"; + std::cout << theEnforcedNodes.size() << tmpStr << " from enforced nodes ..." << std::endl; + for(enfNodeIt = theEnforcedNodes.begin() ; enfNodeIt != theEnforcedNodes.end() ; ++enfNodeIt) + { + const SMDS_MeshNode* node = enfNodeIt->first; + std::vector coords; + coords.push_back(node->X()); + coords.push_back(node->Y()); + coords.push_back(node->Z()); +#ifdef _DEBUG_ + std::cout << "Node at " << node->X()<<", " <Y()<<", " <Z(); +#endif + + // Test if point is inside shape to mesh + gp_Pnt myPoint(node->X(),node->Y(),node->Z()); + TopAbs_State result = pntCls->GetPointState( myPoint ); + if ( result == TopAbs_OUT ) { +#ifdef _DEBUG_ + std::cout << " out of volume" << std::endl; +#endif + continue; + } + + if (nodesCoords.find(coords) != nodesCoords.end()) { +#ifdef _DEBUG_ + std::cout << " found in nodesCoords" << std::endl; +#endif +// theRequiredNodes.push_back(node); + continue; + } + + if (theEnforcedVertices.find(coords) != theEnforcedVertices.end()) { +#ifdef _DEBUG_ + std::cout << " found in theEnforcedVertices" << std::endl; +#endif + continue; + } + +// nbFoundElems = pntCls->FindElementsByPoint(myPoint, SMDSAbs_Node, foundElems); +// if (nbFoundElems ==0) { +// std::cout << " not found" << std::endl; +// if (result == TopAbs_IN) { +// nodesCoords.insert(coords); +// theRequiredNodes.push_back(node); +// } +// } +// else { +// std::cout << " found in initial mesh" << std::endl; +// const SMDS_MeshNode* existingNode = (SMDS_MeshNode*) foundElems.at(0); +// // nodesCoords.insert(coords); +// theRequiredNodes.push_back(existingNode); +// } +// +// +// +// if (pntCls->FindElementsByPoint(myPoint, SMDSAbs_Node, foundElems) == 0) +// continue; + +// if ( result != TopAbs_IN ) +// continue; + +#ifdef _DEBUG_ + std::cout << " not found" << std::endl; +#endif + nodesCoords.insert(coords); +// theOrderedNodes.push_back(node); + theRequiredNodes.push_back(node); + } + int requiredNodes = theRequiredNodes.size(); + + int solSize = 0; + std::vector > ReqVerTab; + if (nbEnforcedVertices) { +// ReqVerTab.clear(); + (nbEnforcedVertices <= 1) ? tmpStr = " node" : " nodes"; + std::cout << nbEnforcedVertices << tmpStr << " from enforced vertices ..." << std::endl; + // Iterate over the enforced vertices + for(vertexIt = theEnforcedVertices.begin() ; vertexIt != theEnforcedVertices.end() ; ++vertexIt) { + double x = vertexIt->first[0]; + double y = vertexIt->first[1]; + double z = vertexIt->first[2]; + // Test if point is inside shape to mesh + gp_Pnt myPoint(x,y,z); + TopAbs_State result = pntCls->GetPointState( myPoint ); + if ( result == TopAbs_OUT ) + continue; + if (pntCls->FindElementsByPoint(myPoint, SMDSAbs_Node, foundElems) == 0) + continue; + +// if ( result != TopAbs_IN ) +// continue; + std::vector coords; + coords.push_back(x); + coords.push_back(y); + coords.push_back(z); + ReqVerTab.push_back(coords); + enfVertexSizes.push_back(vertexIt->second); + solSize++; + } + } + + + // GmfVertices + std::cout << "Begin writting required nodes in GmfVertices" << std::endl; + std::cout << "Nb vertices: " << theOrderedNodes.size() << std::endl; + GmfSetKwd(idx, GmfVertices, theOrderedNodes.size()/*+solSize*/); + for (ghs3dNodeIt = theOrderedNodes.begin();ghs3dNodeIt != theOrderedNodes.end();++ghs3dNodeIt) { + GmfSetLin(idx, GmfVertices, (*ghs3dNodeIt)->X(), (*ghs3dNodeIt)->Y(), (*ghs3dNodeIt)->Z(), dummyint); + } + + std::cout << "End writting required nodes in GmfVertices" << std::endl; + + if (requiredNodes + solSize) { + std::cout << "Begin writting in req and sol file" << std::endl; + aNodeGroupByGhs3dId.resize( requiredNodes + solSize ); + idxRequired = GmfOpenMesh(theRequiredFileName, GmfWrite, GMFVERSION, GMFDIMENSION); + if (!idxRequired) { + GmfCloseMesh(idx); + return false; + } + idxSol = GmfOpenMesh(theSolFileName, GmfWrite, GMFVERSION, GMFDIMENSION); + if (!idxSol) { + GmfCloseMesh(idx); + if (idxRequired) + GmfCloseMesh(idxRequired); + return false; + } + int TypTab[] = {GmfSca}; + GmfSetKwd(idxRequired, GmfVertices, requiredNodes + solSize); + GmfSetKwd(idxSol, GmfSolAtVertices, requiredNodes + solSize, 1, TypTab); +// int usedEnforcedNodes = 0; +// std::string gn = ""; + for (ghs3dNodeIt = theRequiredNodes.begin();ghs3dNodeIt != theRequiredNodes.end();++ghs3dNodeIt) { + GmfSetLin(idxRequired, GmfVertices, (*ghs3dNodeIt)->X(), (*ghs3dNodeIt)->Y(), (*ghs3dNodeIt)->Z(), dummyint); + GmfSetLin(idxSol, GmfSolAtVertices, 0.0); + if (theEnforcedNodes.find((*ghs3dNodeIt)) != theEnforcedNodes.end()) + gn = theEnforcedNodes.find((*ghs3dNodeIt))->second; + aNodeGroupByGhs3dId[usedEnforcedNodes] = gn; + usedEnforcedNodes++; + } + + for (int i=0;isecond; +#ifdef _DEBUG_ + std::cout << "aNodeGroupByGhs3dId["<nodesIterator(); + int index=0; + while ( nodeIt->more() ) { + // find GHS3D ID + const SMDS_MeshNode* node = castToNode( nodeIt->next() ); + map< const SMDS_MeshNode*,int >::iterator it = anEnforcedNodeToGhs3dIdMap.find(node); + if (it == anEnforcedNodeToGhs3dIdMap.end()) { + it = anExistingEnforcedNodeToGhs3dIdMap.find(node); + if (it == anEnforcedNodeToGhs3dIdMap.end()) + throw "Node not found"; + } + nedge[index] = it->second; + index++; + } + GmfSetLin(idx, GmfEdges, nedge[0], nedge[1], dummyint); + anEdgeGroupByGhs3dId[usedEnforcedEdges] = theEnforcedEdges.find(elem)->second; +// GmfSetLin(idxRequired, GmfEdges, nedge[0], nedge[1], dummyint); + usedEnforcedEdges++; + } +// GmfCloseMesh(idxRequired); + } + + + if (usedEnforcedEdges) { + GmfSetKwd(idx, GmfRequiredEdges, usedEnforcedEdges); + for (int enfID=1;enfID<=usedEnforcedEdges;enfID++) { + GmfSetLin(idx, GmfRequiredEdges, enfID); + } + } + + // GmfTriangles + int usedEnforcedTriangles = 0; + if (anElemSet.size()+theKeptEnforcedTriangles.size()) { + aFaceGroupByGhs3dId.resize( anElemSet.size()+theKeptEnforcedTriangles.size() ); + GmfSetKwd(idx, GmfTriangles, anElemSet.size()+theKeptEnforcedTriangles.size()); + int k=0; + for(elemSetIt = anElemSet.begin() ; elemSetIt != anElemSet.end() ; ++elemSetIt,++k) { + elem = (*elemSetIt); + nodeIt = elem->nodesIterator(); + int index=0; + for ( int j = 0; j < 3; ++j ) { + // find GHS3D ID + const SMDS_MeshNode* node = castToNode( nodeIt->next() ); + map< const SMDS_MeshNode*,int >::iterator it = aNodeToGhs3dIdMap.find(node); + if (it == aNodeToGhs3dIdMap.end()) + throw "Node not found"; + ntri[index] = it->second; + index++; + } + GmfSetLin(idx, GmfTriangles, ntri[0], ntri[1], ntri[2], dummyint); + aFaceGroupByGhs3dId[k] = ""; + } + if (theKeptEnforcedTriangles.size()) { + for(elemSetIt = theKeptEnforcedTriangles.begin() ; elemSetIt != theKeptEnforcedTriangles.end() ; ++elemSetIt,++k) { + elem = (*elemSetIt); + nodeIt = elem->nodesIterator(); + int index=0; + for ( int j = 0; j < 3; ++j ) { + // find GHS3D ID + const SMDS_MeshNode* node = castToNode( nodeIt->next() ); + map< const SMDS_MeshNode*,int >::iterator it = anEnforcedNodeToGhs3dIdMap.find(node); + if (it == anEnforcedNodeToGhs3dIdMap.end()) { + it = anExistingEnforcedNodeToGhs3dIdMap.find(node); + if (it == anEnforcedNodeToGhs3dIdMap.end()) + throw "Node not found"; + } + ntri[index] = it->second; + index++; + } + GmfSetLin(idx, GmfTriangles, ntri[0], ntri[1], ntri[2], dummyint); + aFaceGroupByGhs3dId[k] = theEnforcedTriangles.find(elem)->second; + usedEnforcedTriangles++; + } + } + } + + + if (usedEnforcedTriangles) { + GmfSetKwd(idx, GmfRequiredTriangles, usedEnforcedTriangles); + for (int enfID=1;enfID<=usedEnforcedTriangles;enfID++) + GmfSetLin(idx, GmfRequiredTriangles, anElemSet.size()+enfID); + } + + GmfCloseMesh(idx); + if (idxRequired) + GmfCloseMesh(idxRequired); + if (idxSol) + GmfCloseMesh(idxSol); + + return true; + +} + +// static bool writeGMFFile(const char* theMeshFileName, +// const char* theRequiredFileName, +// const char* theSolFileName, +// SMESH_MesherHelper& theHelper, +// const SMESH_ProxyMesh& theProxyMesh, +// std::map & theNodeId2NodeIndexMap, +// std::map & theSmdsToGhs3dIdMap, +// std::map & theGhs3dIdToNodeMap, +// TIDSortedNodeSet & theEnforcedNodes, +// TIDSortedElemSet & theEnforcedEdges, +// TIDSortedElemSet & theEnforcedTriangles, +// // TIDSortedElemSet & theEnforcedQuadrangles, +// GHS3DPlugin_Hypothesis::TGHS3DEnforcedVertexCoordsValues & theEnforcedVertices) +// { +// MESSAGE("writeGMFFile with geometry"); +// int idx, idxRequired, idxSol; +// int nbv, nbev, nben, aGhs3dID = 0; +// const int dummyint = 0; +// GHS3DPlugin_Hypothesis::TGHS3DEnforcedVertexCoordsValues::const_iterator vertexIt; +// std::vector enfVertexSizes; +// TIDSortedNodeSet::const_iterator enfNodeIt; +// const SMDS_MeshNode* node; +// SMDS_NodeIteratorPtr nodeIt; +// +// idx = GmfOpenMesh(theMeshFileName, GmfWrite, GMFVERSION, GMFDIMENSION); +// if (!idx) +// return false; +// +// SMESHDS_Mesh * theMeshDS = theHelper.GetMeshDS(); +// +// /* ========================== NODES ========================== */ +// // NB_NODES +// nbv = theMeshDS->NbNodes(); +// if ( nbv == 0 ) +// return false; +// nbev = theEnforcedVertices.size(); +// nben = theEnforcedNodes.size(); +// +// // Issue 020674: EDF 870 SMESH: Mesh generated by Netgen not usable by GHS3D +// // The problem is in nodes on degenerated edges, we need to skip nodes which are free +// // and replace not-free nodes on edges by the node on vertex +// TNodeNodeMap n2nDegen; // map a node on degenerated edge to a node on vertex +// TNodeNodeMap::iterator n2nDegenIt; +// if ( theHelper.HasDegeneratedEdges() ) +// { +// set checkedSM; +// for (TopExp_Explorer e(theMeshDS->ShapeToMesh(), TopAbs_EDGE ); e.More(); e.Next()) +// { +// SMESH_subMesh* sm = theHelper.GetMesh()->GetSubMesh( e.Current() ); +// if ( checkedSM.insert( sm->GetId() ).second && theHelper.IsDegenShape(sm->GetId() )) +// { +// if ( SMESHDS_SubMesh* smDS = sm->GetSubMeshDS() ) +// { +// TopoDS_Shape vertex = TopoDS_Iterator( e.Current() ).Value(); +// const SMDS_MeshNode* vNode = SMESH_Algo::VertexNode( TopoDS::Vertex( vertex ), theMeshDS); +// { +// SMDS_NodeIteratorPtr nIt = smDS->GetNodes(); +// while ( nIt->more() ) +// n2nDegen.insert( make_pair( nIt->next(), vNode )); +// } +// } +// } +// } +// } +// +// const bool isQuadMesh = +// theHelper.GetMesh()->NbEdges( ORDER_QUADRATIC ) || +// theHelper.GetMesh()->NbFaces( ORDER_QUADRATIC ) || +// theHelper.GetMesh()->NbVolumes( ORDER_QUADRATIC ); +// +// std::vector > VerTab; +// std::set > VerMap; +// VerTab.clear(); +// std::vector aVerTab; +// // Loop from 1 to NB_NODES +// +// nodeIt = theMeshDS->nodesIterator(); +// +// while ( nodeIt->more() ) +// { +// node = nodeIt->next(); +// if ( isQuadMesh && theHelper.IsMedium( node )) // Issue 0021238 +// continue; +// if ( n2nDegen.count( node ) ) // Issue 0020674 +// continue; +// +// std::vector coords; +// coords.push_back(node->X()); +// coords.push_back(node->Y()); +// coords.push_back(node->Z()); +// if (VerMap.find(coords) != VerMap.end()) { +// aGhs3dID = theSmdsToGhs3dIdMap[node->GetID()]; +// theGhs3dIdToNodeMap[theSmdsToGhs3dIdMap[node->GetID()]] = node; +// continue; +// } +// VerTab.push_back(coords); +// VerMap.insert(coords); +// aGhs3dID++; +// theSmdsToGhs3dIdMap.insert( make_pair( node->GetID(), aGhs3dID )); +// theGhs3dIdToNodeMap.insert( make_pair( aGhs3dID, node )); +// } +// +// +// /* ENFORCED NODES ========================== */ +// if (nben) { +// std::cout << "Add " << nben << " enforced nodes to input .mesh file" << std::endl; +// for(enfNodeIt = theEnforcedNodes.begin() ; enfNodeIt != theEnforcedNodes.end() ; ++enfNodeIt) { +// double x = (*enfNodeIt)->X(); +// double y = (*enfNodeIt)->Y(); +// double z = (*enfNodeIt)->Z(); +// // Test if point is inside shape to mesh +// gp_Pnt myPoint(x,y,z); +// BRepClass3d_SolidClassifier scl(theMeshDS->ShapeToMesh()); +// scl.Perform(myPoint, 1e-7); +// TopAbs_State result = scl.State(); +// if ( result != TopAbs_IN ) +// continue; +// std::vector coords; +// coords.push_back(x); +// coords.push_back(y); +// coords.push_back(z); +// if (theEnforcedVertices.find(coords) != theEnforcedVertices.end()) +// continue; +// if (VerMap.find(coords) != VerMap.end()) +// continue; +// VerTab.push_back(coords); +// VerMap.insert(coords); +// aGhs3dID++; +// theNodeId2NodeIndexMap.insert( make_pair( (*enfNodeIt)->GetID(), aGhs3dID )); +// } +// } +// +// +// /* ENFORCED VERTICES ========================== */ +// int solSize = 0; +// std::vector > ReqVerTab; +// ReqVerTab.clear(); +// if (nbev) { +// std::cout << "Add " << nbev << " enforced vertices to input .mesh file" << std::endl; +// for(vertexIt = theEnforcedVertices.begin() ; vertexIt != theEnforcedVertices.end() ; ++vertexIt) { +// double x = vertexIt->first[0]; +// double y = vertexIt->first[1]; +// double z = vertexIt->first[2]; +// // Test if point is inside shape to mesh +// gp_Pnt myPoint(x,y,z); +// BRepClass3d_SolidClassifier scl(theMeshDS->ShapeToMesh()); +// scl.Perform(myPoint, 1e-7); +// TopAbs_State result = scl.State(); +// if ( result != TopAbs_IN ) +// continue; +// enfVertexSizes.push_back(vertexIt->second); +// std::vector coords; +// coords.push_back(x); +// coords.push_back(y); +// coords.push_back(z); +// if (VerMap.find(coords) != VerMap.end()) +// continue; +// ReqVerTab.push_back(coords); +// VerMap.insert(coords); +// solSize++; +// } +// } +// +// +// /* ========================== FACES ========================== */ +// +// int nbTriangles = 0/*, nbQuadrangles = 0*/, aSmdsID; +// TopTools_IndexedMapOfShape facesMap, trianglesMap/*, quadranglesMap*/; +// TIDSortedElemSet::const_iterator elemIt; +// const SMESHDS_SubMesh* theSubMesh; +// TopoDS_Shape aShape; +// SMDS_ElemIteratorPtr itOnSubMesh, itOnSubFace; +// const SMDS_MeshElement* aFace; +// map::const_iterator itOnMap; +// std::vector > tt, qt,et; +// tt.clear(); +// qt.clear(); +// et.clear(); +// std::vector att, aqt, aet; +// +// TopExp::MapShapes( theMeshDS->ShapeToMesh(), TopAbs_FACE, facesMap ); +// +// for ( int i = 1; i <= facesMap.Extent(); ++i ) +// if (( theSubMesh = theProxyMesh.GetSubMesh( facesMap(i)))) +// { +// SMDS_ElemIteratorPtr it = theSubMesh->GetElements(); +// while (it->more()) +// { +// const SMDS_MeshElement *elem = it->next(); +// int nbCornerNodes = elem->NbCornerNodes(); +// if (nbCornerNodes == 3) +// { +// trianglesMap.Add(facesMap(i)); +// nbTriangles ++; +// } +// // else if (nbCornerNodes == 4) +// // { +// // quadranglesMap.Add(facesMap(i)); +// // nbQuadrangles ++; +// // } +// } +// } +// +// /* TRIANGLES ========================== */ +// if (nbTriangles) { +// for ( int i = 1; i <= trianglesMap.Extent(); i++ ) +// { +// aShape = trianglesMap(i); +// theSubMesh = theProxyMesh.GetSubMesh(aShape); +// if ( !theSubMesh ) continue; +// itOnSubMesh = theSubMesh->GetElements(); +// while ( itOnSubMesh->more() ) +// { +// aFace = itOnSubMesh->next(); +// itOnSubFace = aFace->nodesIterator(); +// att.clear(); +// for ( int j = 0; j < 3; ++j ) { +// // find GHS3D ID +// node = castToNode( itOnSubFace->next() ); +// if (( n2nDegenIt = n2nDegen.find( node )) != n2nDegen.end() ) +// node = n2nDegenIt->second; +// aSmdsID = node->GetID(); +// itOnMap = theSmdsToGhs3dIdMap.find( aSmdsID ); +// ASSERT( itOnMap != theSmdsToGhs3dIdMap.end() ); +// att.push_back((*itOnMap).second); +// } +// tt.push_back(att); +// } +// } +// } +// +// if (theEnforcedTriangles.size()) { +// std::cout << "Add " << theEnforcedTriangles.size() << " enforced triangles to input .mesh file" << std::endl; +// // Iterate over the enforced triangles +// for(elemIt = theEnforcedTriangles.begin() ; elemIt != theEnforcedTriangles.end() ; ++elemIt) { +// aFace = (*elemIt); +// itOnSubFace = aFace->nodesIterator(); +// bool isOK = true; +// att.clear(); +// +// for ( int j = 0; j < 3; ++j ) { +// node = castToNode( itOnSubFace->next() ); +// if (( n2nDegenIt = n2nDegen.find( node )) != n2nDegen.end() ) +// node = n2nDegenIt->second; +// // std::cout << node; +// double x = node->X(); +// double y = node->Y(); +// double z = node->Z(); +// // Test if point is inside shape to mesh +// gp_Pnt myPoint(x,y,z); +// BRepClass3d_SolidClassifier scl(theMeshDS->ShapeToMesh()); +// scl.Perform(myPoint, 1e-7); +// TopAbs_State result = scl.State(); +// if ( result != TopAbs_IN ) { +// isOK = false; +// theEnforcedTriangles.erase(elemIt); +// continue; +// } +// std::vector coords; +// coords.push_back(x); +// coords.push_back(y); +// coords.push_back(z); +// if (VerMap.find(coords) != VerMap.end()) { +// att.push_back(theNodeId2NodeIndexMap[node->GetID()]); +// continue; +// } +// VerTab.push_back(coords); +// VerMap.insert(coords); +// aGhs3dID++; +// theNodeId2NodeIndexMap.insert( make_pair( node->GetID(), aGhs3dID )); +// att.push_back(aGhs3dID); +// } +// if (isOK) +// tt.push_back(att); +// } +// } +// +// +// /* ========================== EDGES ========================== */ +// +// if (theEnforcedEdges.size()) { +// // Iterate over the enforced edges +// std::cout << "Add " << theEnforcedEdges.size() << " enforced edges to input .mesh file" << std::endl; +// for(elemIt = theEnforcedEdges.begin() ; elemIt != theEnforcedEdges.end() ; ++elemIt) { +// aFace = (*elemIt); +// bool isOK = true; +// itOnSubFace = aFace->nodesIterator(); +// aet.clear(); +// for ( int j = 0; j < 2; ++j ) { +// node = castToNode( itOnSubFace->next() ); +// if (( n2nDegenIt = n2nDegen.find( node )) != n2nDegen.end() ) +// node = n2nDegenIt->second; +// double x = node->X(); +// double y = node->Y(); +// double z = node->Z(); +// // Test if point is inside shape to mesh +// gp_Pnt myPoint(x,y,z); +// BRepClass3d_SolidClassifier scl(theMeshDS->ShapeToMesh()); +// scl.Perform(myPoint, 1e-7); +// TopAbs_State result = scl.State(); +// if ( result != TopAbs_IN ) { +// isOK = false; +// theEnforcedEdges.erase(elemIt); +// continue; +// } +// std::vector coords; +// coords.push_back(x); +// coords.push_back(y); +// coords.push_back(z); +// if (VerMap.find(coords) != VerMap.end()) { +// aet.push_back(theNodeId2NodeIndexMap[node->GetID()]); +// continue; +// } +// VerTab.push_back(coords); +// VerMap.insert(coords); +// +// aGhs3dID++; +// theNodeId2NodeIndexMap.insert( make_pair( node->GetID(), aGhs3dID )); +// aet.push_back(aGhs3dID); +// } +// if (isOK) +// et.push_back(aet); +// } +// } +// +// +// /* Write vertices number */ +// MESSAGE("Number of vertices: "<GetElements(); +// // for ( int j = 0; j < 4; ++j ) +// // { +// // aFace = itOnSubMesh->next(); +// // itOnSubFace = aFace->nodesIterator(); +// // aqt.clear(); +// // while ( itOnSubFace->more() ) { +// // // find GHS3D ID +// // aSmdsID = itOnSubFace->next()->GetID(); +// // itOnMap = theSmdsToGhs3dIdMap.find( aSmdsID ); +// // ASSERT( itOnMap != theSmdsToGhs3dIdMap.end() ); +// // aqt.push_back((*itOnMap).second); +// // } +// // qt.push_back(aqt); +// // } +// // } +// // } +// // +// // if (theEnforcedQuadrangles.size()) { +// // // Iterate over the enforced triangles +// // for(elemIt = theEnforcedQuadrangles.begin() ; elemIt != theEnforcedQuadrangles.end() ; ++elemIt) { +// // aFace = (*elemIt); +// // bool isOK = true; +// // itOnSubFace = aFace->nodesIterator(); +// // aqt.clear(); +// // for ( int j = 0; j < 4; ++j ) { +// // int aNodeID = itOnSubFace->next()->GetID(); +// // itOnMap = theNodeId2NodeIndexMap.find(aNodeID); +// // if (itOnMap != theNodeId2NodeIndexMap.end()) +// // aqt.push_back((*itOnMap).second); +// // else { +// // isOK = false; +// // theEnforcedQuadrangles.erase(elemIt); +// // break; +// // } +// // } +// // if (isOK) +// // qt.push_back(aqt); +// // } +// // } +// // +// +// // /* Write quadrilaterals number */ +// // if (qt.size()) { +// // GmfSetKwd(idx, GmfQuadrilaterals, qt.size()); +// // for (int i=0;i & theSmdsToGhs3dIdMap, + const map & theEnforcedNodeIdToGhs3dIdMap, + GHS3DPlugin_Hypothesis::TIDSortedElemGroupMap & theEnforcedEdges, + GHS3DPlugin_Hypothesis::TIDSortedElemGroupMap & theEnforcedTriangles) +{ + // record structure: + // + // NB_ELEMS DUMMY_INT + // Loop from 1 to NB_ELEMS + // NB_NODES NODE_NB_1 NODE_NB_2 ... (NB_NODES + 1) times: DUMMY_INT + + TopoDS_Shape aShape; + const SMESHDS_SubMesh* theSubMesh; + const SMDS_MeshElement* aFace; + const char* space = " "; + const int dummyint = 0; + map::const_iterator itOnMap; + SMDS_ElemIteratorPtr itOnSubMesh, itOnSubFace; + int nbNodes, aSmdsID; + + TIDSortedElemSet::const_iterator elemIt; + int nbEnforcedEdges = theEnforcedEdges.size(); + int nbEnforcedTriangles = theEnforcedTriangles.size(); + + // count triangles bound to geometry + int nbTriangles = 0; + + TopTools_IndexedMapOfShape facesMap, trianglesMap; + TopExp::MapShapes( theShape, TopAbs_FACE, facesMap ); + + int nbFaces = facesMap.Extent(); + + for ( int i = 1; i <= nbFaces; ++i ) + if (( theSubMesh = theMesh.GetSubMesh( facesMap(i)))) + nbTriangles += theSubMesh->NbElements(); + std::string tmpStr; + (nbFaces == 0 || nbFaces == 1) ? tmpStr = " shape " : tmpStr = " shapes " ; + std::cout << " " << nbFaces << tmpStr << "of 2D dimension"; + int nbEnforcedElements = nbEnforcedEdges+nbEnforcedTriangles; + if (nbEnforcedElements > 0) { + (nbEnforcedElements == 1) ? tmpStr = "shape:" : tmpStr = "shapes:"; + std::cout << " and" << std::endl; + std::cout << " " << nbEnforcedElements + << " enforced " << tmpStr << std::endl; + } + else + std::cout << std::endl; + if (nbEnforcedEdges) { + (nbEnforcedEdges == 1) ? tmpStr = "edge" : tmpStr = "edges"; + std::cout << " " << nbEnforcedEdges << " enforced " << tmpStr << std::endl; + } + if (nbEnforcedTriangles) { + (nbEnforcedTriangles == 1) ? tmpStr = "triangle" : tmpStr = "triangles"; + std::cout << " " << nbEnforcedTriangles << " enforced " << tmpStr << std::endl; + } + std::cout << std::endl; + +// theFile << space << nbTriangles << space << dummyint << std::endl; + std::ostringstream globalStream, localStream, aStream; + + for ( int i = 1; i <= facesMap.Extent(); i++ ) + { + aShape = facesMap(i); + theSubMesh = theMesh.GetSubMesh(aShape); + if ( !theSubMesh ) continue; + itOnSubMesh = theSubMesh->GetElements(); + while ( itOnSubMesh->more() ) + { + aFace = itOnSubMesh->next(); + nbNodes = aFace->NbCornerNodes(); + + localStream << nbNodes << space; + + itOnSubFace = aFace->nodesIterator(); + for ( int j = 0; j < 3; ++j ) { + // find GHS3D ID + aSmdsID = itOnSubFace->next()->GetID(); + itOnMap = theSmdsToGhs3dIdMap.find( aSmdsID ); + // if ( itOnMap == theSmdsToGhs3dIdMap.end() ) { + // cout << "not found node: " << aSmdsID << endl; + // return false; + // } + ASSERT( itOnMap != theSmdsToGhs3dIdMap.end() ); + + localStream << (*itOnMap).second << space ; + } + + // (NB_NODES + 1) times: DUMMY_INT + for ( int j=0; j<=nbNodes; j++) + localStream << dummyint << space ; + + localStream << std::endl; + } + } + + globalStream << localStream.str(); + localStream.str(""); + + // + // FACES : END + // + +// // +// // ENFORCED EDGES : BEGIN +// // +// +// // Iterate over the enforced edges +// int usedEnforcedEdges = 0; +// bool isOK; +// for(elemIt = theEnforcedEdges.begin() ; elemIt != theEnforcedEdges.end() ; ++elemIt) { +// aFace = (*elemIt); +// isOK = true; +// itOnSubFace = aFace->nodesIterator(); +// aStream.str(""); +// aStream << "2" << space ; +// for ( int j = 0; j < 2; ++j ) { +// aSmdsID = itOnSubFace->next()->GetID(); +// itOnMap = theEnforcedNodeIdToGhs3dIdMap.find(aSmdsID); +// if (itOnMap != theEnforcedNodeIdToGhs3dIdMap.end()) +// aStream << (*itOnMap).second << space; +// else { +// isOK = false; +// break; +// } +// } +// if (isOK) { +// for ( int j=0; j<=2; j++) +// aStream << dummyint << space ; +// // aStream << dummyint << space << dummyint; +// localStream << aStream.str() << std::endl; +// usedEnforcedEdges++; +// } +// } +// +// if (usedEnforcedEdges) { +// globalStream << localStream.str(); +// localStream.str(""); +// } +// +// // +// // ENFORCED EDGES : END +// // +// // +// +// // +// // ENFORCED TRIANGLES : BEGIN +// // +// // Iterate over the enforced triangles +// int usedEnforcedTriangles = 0; +// for(elemIt = theEnforcedTriangles.begin() ; elemIt != theEnforcedTriangles.end() ; ++elemIt) { +// aFace = (*elemIt); +// nbNodes = aFace->NbCornerNodes(); +// isOK = true; +// itOnSubFace = aFace->nodesIterator(); +// aStream.str(""); +// aStream << nbNodes << space ; +// for ( int j = 0; j < 3; ++j ) { +// aSmdsID = itOnSubFace->next()->GetID(); +// itOnMap = theEnforcedNodeIdToGhs3dIdMap.find(aSmdsID); +// if (itOnMap != theEnforcedNodeIdToGhs3dIdMap.end()) +// aStream << (*itOnMap).second << space; +// else { +// isOK = false; +// break; +// } +// } +// if (isOK) { +// for ( int j=0; j<=3; j++) +// aStream << dummyint << space ; +// localStream << aStream.str() << std::endl; +// usedEnforcedTriangles++; +// } +// } +// +// if (usedEnforcedTriangles) { +// globalStream << localStream.str(); +// localStream.str(""); +// } +// +// // +// // ENFORCED TRIANGLES : END +// // + + theFile + << nbTriangles/*+usedEnforcedTriangles+usedEnforcedEdges*/ + << " 0" << std::endl + << globalStream.str(); + + return true; +} + +//======================================================================= +//function : writePoints +//purpose : +//======================================================================= + +static bool writePoints (ofstream & theFile, + SMESH_MesherHelper& theHelper, + map & theSmdsToGhs3dIdMap, + map & theEnforcedNodeIdToGhs3dIdMap, + map & theGhs3dIdToNodeMap, + GHS3DPlugin_Hypothesis::TID2SizeMap & theNodeIDToSizeMap, + GHS3DPlugin_Hypothesis::TGHS3DEnforcedVertexCoordsValues & theEnforcedVertices, + GHS3DPlugin_Hypothesis::TIDSortedNodeGroupMap & theEnforcedNodes, + GHS3DPlugin_Hypothesis::TIDSortedElemGroupMap & theEnforcedEdges, + GHS3DPlugin_Hypothesis::TIDSortedElemGroupMap & theEnforcedTriangles) +{ + // record structure: + // + // NB_NODES + // Loop from 1 to NB_NODES + // X Y Z DUMMY_INT + + SMESHDS_Mesh * theMeshDS = theHelper.GetMeshDS(); + int nbNodes = theMeshDS->NbNodes(); + if ( nbNodes == 0 ) + return false; + + int nbEnforcedVertices = theEnforcedVertices.size(); + int nbEnforcedNodes = theEnforcedNodes.size(); + + const TopoDS_Shape shapeToMesh = theMeshDS->ShapeToMesh(); + + int aGhs3dID = 1; + SMDS_NodeIteratorPtr nodeIt = theMeshDS->nodesIterator(); + const SMDS_MeshNode* node; + + // Issue 020674: EDF 870 SMESH: Mesh generated by Netgen not usable by GHS3D + // The problem is in nodes on degenerated edges, we need to skip nodes which are free + // and replace not-free nodes on degenerated edges by the node on vertex + TNodeNodeMap n2nDegen; // map a node on degenerated edge to a node on vertex + TNodeNodeMap::iterator n2nDegenIt; + if ( theHelper.HasDegeneratedEdges() ) + { + set checkedSM; + for (TopExp_Explorer e(theMeshDS->ShapeToMesh(), TopAbs_EDGE ); e.More(); e.Next()) + { + SMESH_subMesh* sm = theHelper.GetMesh()->GetSubMesh( e.Current() ); + if ( checkedSM.insert( sm->GetId() ).second && theHelper.IsDegenShape(sm->GetId() )) + { + if ( SMESHDS_SubMesh* smDS = sm->GetSubMeshDS() ) + { + TopoDS_Shape vertex = TopoDS_Iterator( e.Current() ).Value(); + const SMDS_MeshNode* vNode = SMESH_Algo::VertexNode( TopoDS::Vertex( vertex ), theMeshDS); + { + SMDS_NodeIteratorPtr nIt = smDS->GetNodes(); + while ( nIt->more() ) + n2nDegen.insert( make_pair( nIt->next(), vNode )); + } + } + } + } + nbNodes -= n2nDegen.size(); + } + + const bool isQuadMesh = + theHelper.GetMesh()->NbEdges( ORDER_QUADRATIC ) || + theHelper.GetMesh()->NbFaces( ORDER_QUADRATIC ) || + theHelper.GetMesh()->NbVolumes( ORDER_QUADRATIC ); + if ( isQuadMesh ) + { + // descrease nbNodes by nb of medium nodes + while ( nodeIt->more() ) + { + node = nodeIt->next(); + if ( !theHelper.IsDegenShape( node->getshapeId() )) + nbNodes -= int( theHelper.IsMedium( node )); + } + nodeIt = theMeshDS->nodesIterator(); + } + + const char* space = " "; + const int dummyint = 0; + + std::string tmpStr; + (nbNodes == 0 || nbNodes == 1) ? tmpStr = " node" : tmpStr = " nodes"; + // NB_NODES + std::cout << std::endl; + std::cout << "The initial 2D mesh contains :" << std::endl; + std::cout << " " << nbNodes << tmpStr << std::endl; + if (nbEnforcedVertices > 0) { + (nbEnforcedVertices == 1) ? tmpStr = "vertex" : tmpStr = "vertices"; + std::cout << " " << nbEnforcedVertices << " enforced " << tmpStr << std::endl; + } + if (nbEnforcedNodes > 0) { + (nbEnforcedNodes == 1) ? tmpStr = "node" : tmpStr = "nodes"; + std::cout << " " << nbEnforcedNodes << " enforced " << tmpStr << std::endl; + } + std::cout << std::endl; + std::cout << "Start writing in 'points' file ..." << std::endl; + + theFile << nbNodes << std::endl; + + // Loop from 1 to NB_NODES + + while ( nodeIt->more() ) + { + node = nodeIt->next(); + if ( isQuadMesh && theHelper.IsMedium( node )) // Issue 0021238 + continue; + if ( n2nDegen.count( node ) ) // Issue 0020674 + continue; + + theSmdsToGhs3dIdMap.insert( make_pair( node->GetID(), aGhs3dID )); + theGhs3dIdToNodeMap.insert( make_pair( aGhs3dID, node )); + aGhs3dID++; + + // X Y Z DUMMY_INT + theFile + << node->X() << space + << node->Y() << space + << node->Z() << space + << dummyint; + + theFile << std::endl; + + } + + // Iterate over the enforced nodes + std::map enfVertexIndexSizeMap; + if (nbEnforcedNodes) { + GHS3DPlugin_Hypothesis::TIDSortedNodeGroupMap::const_iterator nodeIt = theEnforcedNodes.begin(); + for( ; nodeIt != theEnforcedNodes.end() ; ++nodeIt) { + double x = nodeIt->first->X(); + double y = nodeIt->first->Y(); + double z = nodeIt->first->Z(); + // Test if point is inside shape to mesh + gp_Pnt myPoint(x,y,z); + BRepClass3d_SolidClassifier scl(shapeToMesh); + scl.Perform(myPoint, 1e-7); + TopAbs_State result = scl.State(); + if ( result != TopAbs_IN ) + continue; + std::vector coords; + coords.push_back(x); + coords.push_back(y); + coords.push_back(z); + if (theEnforcedVertices.find(coords) != theEnforcedVertices.end()) + continue; + + double size = theNodeIDToSizeMap.find(nodeIt->first->GetID())->second; + // theGhs3dIdToNodeMap.insert( make_pair( nbNodes + i, (*nodeIt) )); + // MESSAGE("Adding enforced node (" << x << "," << y <<"," << z << ")"); + // X Y Z PHY_SIZE DUMMY_INT + theFile + << x << space + << y << space + << z << space + << size << space + << dummyint << space; + theFile << std::endl; + theEnforcedNodeIdToGhs3dIdMap.insert( make_pair( nodeIt->first->GetID(), aGhs3dID )); + enfVertexIndexSizeMap[aGhs3dID] = -1; + aGhs3dID++; + // else + // MESSAGE("Enforced vertex (" << x << "," << y <<"," << z << ") is not inside the geometry: it was not added "); + } + } + + if (nbEnforcedVertices) { + // Iterate over the enforced vertices + GHS3DPlugin_Hypothesis::TGHS3DEnforcedVertexCoordsValues::const_iterator vertexIt = theEnforcedVertices.begin(); + for( ; vertexIt != theEnforcedVertices.end() ; ++vertexIt) { + double x = vertexIt->first[0]; + double y = vertexIt->first[1]; + double z = vertexIt->first[2]; + // Test if point is inside shape to mesh + gp_Pnt myPoint(x,y,z); + BRepClass3d_SolidClassifier scl(shapeToMesh); + scl.Perform(myPoint, 1e-7); + TopAbs_State result = scl.State(); + if ( result != TopAbs_IN ) + continue; + MESSAGE("Adding enforced vertex (" << x << "," << y <<"," << z << ") = " << vertexIt->second); + // X Y Z PHY_SIZE DUMMY_INT + theFile + << x << space + << y << space + << z << space + << vertexIt->second << space + << dummyint << space; + theFile << std::endl; + enfVertexIndexSizeMap[aGhs3dID] = vertexIt->second; + aGhs3dID++; + } + } + + + std::cout << std::endl; + std::cout << "End writing in 'points' file." << std::endl; + + return true; +} + +//======================================================================= +//function : readResultFile +//purpose : readResultFile with geometry +//======================================================================= + +static bool readResultFile(const int fileOpen, +#ifdef WNT + const char* fileName, +#endif +#ifdef WITH_SMESH_CANCEL_COMPUTE + GHS3DPlugin_GHS3D* theAlgo, +#endif + SMESH_MesherHelper& theHelper, + TopoDS_Shape tabShape[], + double** tabBox, + const int nbShape, + map & theGhs3dIdToNodeMap, + std::map & theNodeId2NodeIndexMap, + bool toMeshHoles, + int nbEnforcedVertices, + int nbEnforcedNodes, + GHS3DPlugin_Hypothesis::TIDSortedElemGroupMap & theEnforcedEdges, + GHS3DPlugin_Hypothesis::TIDSortedElemGroupMap & theEnforcedTriangles) +{ + MESSAGE("GHS3DPlugin_GHS3D::readResultFile()"); + Kernel_Utils::Localizer loc; + struct stat status; + size_t length; + + std::string tmpStr; + + char *ptr, *mapPtr; + char *tetraPtr; + char *shapePtr; + + SMESHDS_Mesh* theMeshDS = theHelper.GetMeshDS(); + + int nbElems, nbNodes, nbInputNodes; + int nbTriangle; + int ID, shapeID, ghs3dShapeID; + int IdShapeRef = 1; + int compoundID = + nbShape ? theMeshDS->ShapeToIndex( tabShape[0] ) : theMeshDS->ShapeToIndex( theMeshDS->ShapeToMesh() ); + + int *tab, *tabID, *nodeID, *nodeAssigne; + double *coord; + const SMDS_MeshNode **node; + + tab = new int[3]; + nodeID = new int[4]; + coord = new double[3]; + node = new const SMDS_MeshNode*[4]; + + TopoDS_Shape aSolid; + SMDS_MeshNode * aNewNode; + map ::iterator itOnNode; + SMDS_MeshElement* aTet; +#ifdef _DEBUG_ + set shapeIDs; +#endif + + // Read the file state + fstat(fileOpen, &status); + length = status.st_size; + + // Mapping the result file into memory +#ifdef WNT + HANDLE fd = CreateFile(fileName, GENERIC_READ, FILE_SHARE_READ, + NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + HANDLE hMapObject = CreateFileMapping(fd, NULL, PAGE_READONLY, + 0, (DWORD)length, NULL); + ptr = ( char* ) MapViewOfFile(hMapObject, FILE_MAP_READ, 0, 0, 0 ); +#else + ptr = (char *) mmap(0,length,PROT_READ,MAP_PRIVATE,fileOpen,0); +#endif + mapPtr = ptr; + + ptr = readMapIntLine(ptr, tab); + tetraPtr = ptr; + + nbElems = tab[0]; + nbNodes = tab[1]; + nbInputNodes = tab[2]; + + nodeAssigne = new int[ nbNodes+1 ]; + + if (nbShape > 0) + aSolid = tabShape[0]; + + // Reading the nodeId + for (int i=0; i < 4*nbElems; i++) + strtol(ptr, &ptr, 10); + + MESSAGE("nbInputNodes: "<computeCanceled()) + return false; +#endif + for (int iCoor=0; iCoor < 3; iCoor++) + coord[ iCoor ] = strtod(ptr, &ptr); + nodeAssigne[ iNode ] = 1; + if ( iNode > (nbInputNodes-(nbEnforcedVertices+nbEnforcedNodes)) ) { + // Creating SMESH nodes + // - for enforced vertices + // - for vertices of forced edges + // - for ghs3d nodes + nodeAssigne[ iNode ] = 0; + aNewNode = theMeshDS->AddNode( coord[0],coord[1],coord[2] ); + theGhs3dIdToNodeMap.insert(theGhs3dIdToNodeMap.end(), make_pair( iNode, aNewNode )); + } + } + + // Reading the number of triangles which corresponds to the number of sub-domains + nbTriangle = strtol(ptr, &ptr, 10); + + tabID = new int[nbTriangle]; + for (int i=0; i < nbTriangle; i++) { +#ifdef WITH_SMESH_CANCEL_COMPUTE + if(theAlgo->computeCanceled()) + return false; +#endif + tabID[i] = 0; + // find the solid corresponding to GHS3D sub-domain following + // the technique proposed in GHS3D manual in chapter + // "B.4 Subdomain (sub-region) assignment" + int nodeId1 = strtol(ptr, &ptr, 10); + int nodeId2 = strtol(ptr, &ptr, 10); + int nodeId3 = strtol(ptr, &ptr, 10); + if ( nbTriangle > 1 ) { + const SMDS_MeshNode* n1 = theGhs3dIdToNodeMap[ nodeId1 ]; + const SMDS_MeshNode* n2 = theGhs3dIdToNodeMap[ nodeId2 ]; + const SMDS_MeshNode* n3 = theGhs3dIdToNodeMap[ nodeId3 ]; + if (!n1 || !n2 || !n3) { + tabID[i] = HOLE_ID; + continue; + } + try { + OCC_CATCH_SIGNALS; +// tabID[i] = findShapeID( theHelper, n1, n2, n3, toMeshHoles ); + tabID[i] = findShapeID( *theHelper.GetMesh(), n1, n2, n3, toMeshHoles ); + // -- 0020330: Pb with ghs3d as a submesh + // check that found shape is to be meshed + if ( tabID[i] > 0 ) { + const TopoDS_Shape& foundShape = theMeshDS->IndexToShape( tabID[i] ); + bool isToBeMeshed = false; + for ( int iS = 0; !isToBeMeshed && iS < nbShape; ++iS ) + isToBeMeshed = foundShape.IsSame( tabShape[ iS ]); + if ( !isToBeMeshed ) + tabID[i] = HOLE_ID; + } + // END -- 0020330: Pb with ghs3d as a submesh +#ifdef _DEBUG_ + std::cout << i+1 << " subdomain: findShapeID() returns " << tabID[i] << std::endl; +#endif + } + catch ( Standard_Failure & ex) + { +#ifdef _DEBUG_ + std::cout << i+1 << " subdomain: Exception caugt: " << ex.GetMessageString() << std::endl; +#endif + } + catch (...) { +#ifdef _DEBUG_ + std::cout << i+1 << " subdomain: unknown exception caught " << std::endl; +#endif + } + } + } + + shapePtr = ptr; + + if ( nbTriangle <= nbShape ) // no holes + toMeshHoles = true; // not avoid creating tetras in holes + + // Associating the tetrahedrons to the shapes + shapeID = compoundID; + for (int iElem = 0; iElem < nbElems; iElem++) { +#ifdef WITH_SMESH_CANCEL_COMPUTE + if(theAlgo->computeCanceled()) + return false; +#endif + for (int iNode = 0; iNode < 4; iNode++) { + ID = strtol(tetraPtr, &tetraPtr, 10); + itOnNode = theGhs3dIdToNodeMap.find(ID); + node[ iNode ] = itOnNode->second; + nodeID[ iNode ] = ID; + } + // We always run GHS3D with "to mesh holes"==TRUE but we must not create + // tetras within holes depending on hypo option, + // so we first check if aTet is inside a hole and then create it + //aTet = theMeshDS->AddVolume( node[1], node[0], node[2], node[3] ); + if ( nbTriangle > 1 ) { + shapeID = HOLE_ID; // negative shapeID means not to create tetras if !toMeshHoles + ghs3dShapeID = strtol(shapePtr, &shapePtr, 10) - IdShapeRef; + if ( tabID[ ghs3dShapeID ] == 0 ) { + TopAbs_State state; + aSolid = findShape(node, aSolid, tabShape, tabBox, nbShape, &state); + if ( toMeshHoles || state == TopAbs_IN ) + shapeID = theMeshDS->ShapeToIndex( aSolid ); + tabID[ ghs3dShapeID ] = shapeID; + } + else + shapeID = tabID[ ghs3dShapeID ]; + } + else if ( nbShape > 1 ) { + // Case where nbTriangle == 1 while nbShape == 2 encountered + // with compound of 2 boxes and "To mesh holes"==False, + // so there are no subdomains specified for each tetrahedron. + // Try to guess a solid by a node already bound to shape + shapeID = 0; + for ( int i=0; i<4 && shapeID==0; i++ ) { + if ( nodeAssigne[ nodeID[i] ] == 1 && + node[i]->GetPosition()->GetTypeOfPosition() == SMDS_TOP_3DSPACE && + node[i]->getshapeId() > 1 ) + { + shapeID = node[i]->getshapeId(); + } + } + if ( shapeID==0 ) { + aSolid = findShape(node, aSolid, tabShape, tabBox, nbShape); + shapeID = theMeshDS->ShapeToIndex( aSolid ); + } + } + // set new nodes and tetrahedron onto the shape + for ( int i=0; i<4; i++ ) { + if ( nodeAssigne[ nodeID[i] ] == 0 ) { + if ( shapeID != HOLE_ID ) + theMeshDS->SetNodeInVolume( node[i], shapeID ); + nodeAssigne[ nodeID[i] ] = shapeID; + } + } + if ( toMeshHoles || shapeID != HOLE_ID ) { + aTet = theHelper.AddVolume( node[1], node[0], node[2], node[3], + /*id=*/0, /*force3d=*/false); + theMeshDS->SetMeshElementOnShape( aTet, shapeID ); + } +#ifdef _DEBUG_ + shapeIDs.insert( shapeID ); +#endif + } + + // Add enforced elements + GHS3DPlugin_Hypothesis::TIDSortedElemGroupMap::const_iterator elemIt; + const SMDS_MeshElement* anElem; + SMDS_ElemIteratorPtr itOnEnfElem; + map::const_iterator itOnMap; + shapeID = compoundID; + // Enforced edges + if (theEnforcedEdges.size()) { + (theEnforcedEdges.size() <= 1) ? tmpStr = " enforced edge" : " enforced edges"; + std::cout << "Add " << theEnforcedEdges.size() << tmpStr << std::endl; + std::vector< const SMDS_MeshNode* > node( 2 ); + // Iterate over the enforced edges + for(elemIt = theEnforcedEdges.begin() ; elemIt != theEnforcedEdges.end() ; ++elemIt) { + anElem = elemIt->first; + bool addElem = true; + itOnEnfElem = anElem->nodesIterator(); + for ( int j = 0; j < 2; ++j ) { + int aNodeID = itOnEnfElem->next()->GetID(); + itOnMap = theNodeId2NodeIndexMap.find(aNodeID); + if (itOnMap != theNodeId2NodeIndexMap.end()) { + itOnNode = theGhs3dIdToNodeMap.find((*itOnMap).second); + if (itOnNode != theGhs3dIdToNodeMap.end()) { + node.push_back((*itOnNode).second); +// shapeID =(*itOnNode).second->getshapeId(); + } + else + addElem = false; + } + else + addElem = false; + } + if (addElem) { + aTet = theHelper.AddEdge( node[0], node[1], 0, false); + theMeshDS->SetMeshElementOnShape( aTet, shapeID ); + } + } + } + // Enforced faces + if (theEnforcedTriangles.size()) { + (theEnforcedTriangles.size() <= 1) ? tmpStr = " enforced triangle" : " enforced triangles"; + std::cout << "Add " << theEnforcedTriangles.size() << " enforced triangles" << std::endl; + std::vector< const SMDS_MeshNode* > node( 3 ); + // Iterate over the enforced triangles + for(elemIt = theEnforcedTriangles.begin() ; elemIt != theEnforcedTriangles.end() ; ++elemIt) { + anElem = elemIt->first; + bool addElem = true; + itOnEnfElem = anElem->nodesIterator(); + for ( int j = 0; j < 3; ++j ) { + int aNodeID = itOnEnfElem->next()->GetID(); + itOnMap = theNodeId2NodeIndexMap.find(aNodeID); + if (itOnMap != theNodeId2NodeIndexMap.end()) { + itOnNode = theGhs3dIdToNodeMap.find((*itOnMap).second); + if (itOnNode != theGhs3dIdToNodeMap.end()) { + node.push_back((*itOnNode).second); +// shapeID =(*itOnNode).second->getshapeId(); + } + else + addElem = false; + } + else + addElem = false; + } + if (addElem) { + aTet = theHelper.AddFace( node[0], node[1], node[2], 0, false); + theMeshDS->SetMeshElementOnShape( aTet, shapeID ); + } + } + } + + // Remove nodes of tetras inside holes if !toMeshHoles + if ( !toMeshHoles ) { + itOnNode = theGhs3dIdToNodeMap.find( nbInputNodes ); + for ( ; itOnNode != theGhs3dIdToNodeMap.end(); ++itOnNode) { + ID = itOnNode->first; + if ( nodeAssigne[ ID ] == HOLE_ID ) + theMeshDS->RemoveFreeNode( itOnNode->second, 0 ); + } + } + + + if ( nbElems ) { + (nbElems <= 1) ? tmpStr = " tetrahedra" : " tetrahedrons"; + cout << nbElems << tmpStr << " have been associated to " << nbShape; + (nbShape <= 1) ? tmpStr = " shape" : " shapes"; + cout << tmpStr << endl; + } +#ifdef WNT + UnmapViewOfFile(mapPtr); + CloseHandle(hMapObject); + CloseHandle(fd); +#else + munmap(mapPtr, length); +#endif + close(fileOpen); + + delete [] tab; + delete [] tabID; + delete [] nodeID; + delete [] coord; + delete [] node; + delete [] nodeAssigne; + +#ifdef _DEBUG_ + shapeIDs.erase(-1); + if ( shapeIDs.size() != nbShape ) { + (shapeIDs.size() <= 1) ? tmpStr = " solid" : " solids"; + std::cout << "Only " << shapeIDs.size() << tmpStr << " of " << nbShape << " found" << std::endl; + for (int i=0; iShapeToIndex( tabShape[i] ); + if ( shapeIDs.find( shapeID ) == shapeIDs.end() ) + std::cout << " Solid #" << shapeID << " not found" << std::endl; + } + } +#endif + + return true; +} + + +//============================================================================= +/*! + *Here we are going to use the GHS3D mesher with geometry + */ +//============================================================================= + +bool GHS3DPlugin_GHS3D::Compute(SMESH_Mesh& theMesh, + const TopoDS_Shape& theShape) +{ + bool Ok(false); + //SMESHDS_Mesh* meshDS = theMesh.GetMeshDS(); + + // we count the number of shapes + // _nbShape = countShape( meshDS, TopAbs_SOLID ); -- 0020330: Pb with ghs3d as a submesh + _nbShape = 0; + TopExp_Explorer expBox ( theShape, TopAbs_SOLID ); + for ( ; expBox.More(); expBox.Next() ) + _nbShape++; + + // create bounding box for every shape inside the compound + + int iShape = 0; + TopoDS_Shape* tabShape; + double** tabBox; + tabShape = new TopoDS_Shape[_nbShape]; + tabBox = new double*[_nbShape]; + for (int i=0; i<_nbShape; i++) + tabBox[i] = new double[6]; + Standard_Real Xmin, Ymin, Zmin, Xmax, Ymax, Zmax; + + for (expBox.ReInit(); expBox.More(); expBox.Next()) { + tabShape[iShape] = expBox.Current(); + Bnd_Box BoundingBox; + BRepBndLib::Add(expBox.Current(), BoundingBox); + BoundingBox.Get(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax); + tabBox[iShape][0] = Xmin; tabBox[iShape][1] = Xmax; + tabBox[iShape][2] = Ymin; tabBox[iShape][3] = Ymax; + tabBox[iShape][4] = Zmin; tabBox[iShape][5] = Zmax; + iShape++; + } + + // a unique working file name + // to avoid access to the same files by eg different users + TCollection_AsciiString aGenericName + = (char*) GHS3DPlugin_Hypothesis::GetFileName(_hyp).c_str(); + + TCollection_AsciiString aResultFileName; + TCollection_AsciiString aLogFileName = aGenericName + ".log"; // log + // The output .mesh file does not contain yet the subdomain-info (Ghs3D 4.2) +// TCollection_AsciiString aGMFFileName, aRequiredVerticesFileName, aSolFileName; +// TCollection_AsciiString aGenericNameRequired = aGenericName + "_required"; +// #ifdef _DEBUG_ +// aGMFFileName = aGenericName + ".mesh"; // GMF mesh file +// aResultFileName = aGenericName + "Vol.mesh"; // GMF mesh file +// aRequiredVerticesFileName = aGenericNameRequired + ".mesh"; // GMF required vertices mesh file +// aSolFileName = aGenericName + "_required.sol"; // GMF solution file +// #else +// aGMFFileName = aGenericName + ".meshb"; // GMF mesh file +// aResultFileName = aGenericName + "Vol.meshb"; // GMF mesh file +// aRequiredVerticesFileName = aGenericNameRequired + ".meshb"; // GMF required vertices mesh file +// aSolFileName = aGenericName + "_required.solb"; // GMF solution file +// #endif + + TCollection_AsciiString aFacesFileName, aPointsFileName, aBadResFileName, aBbResFileName; + + aFacesFileName = aGenericName + ".faces"; // in faces + aPointsFileName = aGenericName + ".points"; // in points + aResultFileName = aGenericName + ".noboite";// out points and volumes + aBadResFileName = aGenericName + ".boite"; // out bad result + aBbResFileName = aGenericName + ".bb"; // out vertex stepsize + + // ----------------- + // make input files + // ----------------- + + ofstream aFacesFile ( aFacesFileName.ToCString() , ios::out); + ofstream aPointsFile ( aPointsFileName.ToCString() , ios::out); + + Ok = + aFacesFile.rdbuf()->is_open() && aPointsFile.rdbuf()->is_open(); + if (!Ok) { + INFOS( "Can't write into " << aFacesFileName); + return error(SMESH_Comment("Can't write into ") << aFacesFileName); + } + + std::map aNodeId2NodeIndexMap, aSmdsToGhs3dIdMap, anEnforcedNodeIdToGhs3dIdMap; + std::map aGhs3dIdToNodeMap; + std::map nodeID2nodeIndexMap; + GHS3DPlugin_Hypothesis::TGHS3DEnforcedVertexCoordsValues coordsSizeMap = GHS3DPlugin_Hypothesis::GetEnforcedVerticesCoordsSize(_hyp); + GHS3DPlugin_Hypothesis::TIDSortedNodeGroupMap enforcedNodes = GHS3DPlugin_Hypothesis::GetEnforcedNodes(_hyp); + GHS3DPlugin_Hypothesis::TIDSortedElemGroupMap enforcedEdges = GHS3DPlugin_Hypothesis::GetEnforcedEdges(_hyp); + GHS3DPlugin_Hypothesis::TIDSortedElemGroupMap enforcedTriangles = GHS3DPlugin_Hypothesis::GetEnforcedTriangles(_hyp); +// TIDSortedElemSet enforcedQuadrangles = GHS3DPlugin_Hypothesis::GetEnforcedQuadrangles(_hyp); + GHS3DPlugin_Hypothesis::TID2SizeMap nodeIDToSizeMap = GHS3DPlugin_Hypothesis::GetNodeIDToSizeMap(_hyp); + + int nbEnforcedVertices = coordsSizeMap.size(); + int nbEnforcedNodes = enforcedNodes.size(); + + std::string tmpStr; + (nbEnforcedNodes <= 1) ? tmpStr = "node" : "nodes"; + std::cout << nbEnforcedNodes << " enforced " << tmpStr << " from hypo" << std::endl; + (nbEnforcedVertices <= 1) ? tmpStr = "vertex" : "vertices"; + std::cout << nbEnforcedVertices << " enforced " << tmpStr << " from hypo" << std::endl; + + SMESH_MesherHelper helper( theMesh ); + helper.SetSubShape( theShape ); + + { + SMESH_ProxyMesh::Ptr proxyMesh( new SMESH_ProxyMesh( theMesh )); + + // make prisms on quadrangles + if ( theMesh.NbQuadrangles() > 0 ) + { + vector components; + for (expBox.ReInit(); expBox.More(); expBox.Next()) + { + if ( _viscousLayersHyp ) + { + proxyMesh = _viscousLayersHyp->Compute( theMesh, expBox.Current() ); + if ( !proxyMesh ) + return false; + } + StdMeshers_QuadToTriaAdaptor* q2t = new StdMeshers_QuadToTriaAdaptor; + q2t->Compute( theMesh, expBox.Current(), proxyMesh.get() ); + components.push_back( SMESH_ProxyMesh::Ptr( q2t )); + } + proxyMesh.reset( new SMESH_ProxyMesh( components )); + } + // build viscous layers + else if ( _viscousLayersHyp ) + { + proxyMesh = _viscousLayersHyp->Compute( theMesh, theShape ); + if ( !proxyMesh ) + return false; + } + + Ok = (writePoints( aPointsFile, helper, + aSmdsToGhs3dIdMap, anEnforcedNodeIdToGhs3dIdMap, aGhs3dIdToNodeMap, + nodeIDToSizeMap, + coordsSizeMap, enforcedNodes, enforcedEdges, enforcedTriangles) + && + writeFaces ( aFacesFile, *proxyMesh, theShape, + aSmdsToGhs3dIdMap, anEnforcedNodeIdToGhs3dIdMap, + enforcedEdges, enforcedTriangles )); +// Ok = writeGMFFile(aGMFFileName.ToCString(), aRequiredVerticesFileName.ToCString(), aSolFileName.ToCString(), +// helper, *proxyMesh, +// aNodeId2NodeIndexMap, aSmdsToGhs3dIdMap, aGhs3dIdToNodeMap, +// enforcedNodes, enforcedEdges, enforcedTriangles, /*enforcedQuadrangles,*/ +// coordsSizeMap); + } + + // Write aSmdsToGhs3dIdMap to temp file + TCollection_AsciiString aSmdsToGhs3dIdMapFileName; + aSmdsToGhs3dIdMapFileName = aGenericName + ".ids"; // ids relation + ofstream aIdsFile ( aSmdsToGhs3dIdMapFileName.ToCString() , ios::out); + Ok = aIdsFile.rdbuf()->is_open(); + if (!Ok) { + INFOS( "Can't write into " << aSmdsToGhs3dIdMapFileName); + return error(SMESH_Comment("Can't write into ") << aSmdsToGhs3dIdMapFileName); + } + INFOS( "Writing ids relation into " << aSmdsToGhs3dIdMapFileName); + aIdsFile << "Smds Ghs3d" << std::endl; + map ::const_iterator myit; + for (myit=aSmdsToGhs3dIdMap.begin() ; myit != aSmdsToGhs3dIdMap.end() ; ++myit) { + aIdsFile << myit->first << " " << myit->second << std::endl; + } + + aIdsFile.close(); + aFacesFile.close(); + aPointsFile.close(); + + if ( ! Ok ) { + if ( !_keepFiles ) { +// removeFile( aGMFFileName ); +// removeFile( aRequiredVerticesFileName ); +// removeFile( aSolFileName ); + removeFile( aFacesFileName ); + removeFile( aPointsFileName ); + removeFile( aSmdsToGhs3dIdMapFileName ); + } + return error(COMPERR_BAD_INPUT_MESH); + } + removeFile( aResultFileName ); // needed for boundary recovery module usage + + // ----------------- + // run ghs3d mesher + // ----------------- + + TCollection_AsciiString cmd = TCollection_AsciiString((char*)GHS3DPlugin_Hypothesis::CommandToRun( _hyp ).c_str() ); + cmd += TCollection_AsciiString(" -f ") + aGenericName; // file to read + cmd += TCollection_AsciiString(" 1>" ) + aLogFileName; // dump into file + // The output .mesh file does not contain yet the subdomain-info (Ghs3D 4.2) +// cmd += TCollection_AsciiString(" --in ") + aGenericName; +// cmd += TCollection_AsciiString(" --required_vertices ") + aGenericNameRequired; +// cmd += TCollection_AsciiString(" --out ") + aResultGMFFileName; +// cmd += TCollection_AsciiString(" 1>" ) + aLogFileName; // dump into file + + std::cout << std::endl; + std::cout << "Ghs3d execution..." << std::endl; + std::cout << cmd << std::endl; + +#ifdef WITH_SMESH_CANCEL_COMPUTE + _compute_canceled = false; +#endif + + system( cmd.ToCString() ); // run + + std::cout << std::endl; + std::cout << "End of Ghs3d execution !" << std::endl; + + // -------------- + // read a result + // -------------- + + // Mapping the result file + + int fileOpen; + fileOpen = open( aResultFileName.ToCString(), O_RDONLY); + if ( fileOpen < 0 ) { + std::cout << std::endl; + std::cout << "Can't open the " << aResultFileName.ToCString() << " GHS3D output file" << std::endl; + std::cout << "Log: " << aLogFileName << std::endl; + Ok = false; + } + else { + bool toMeshHoles = + _hyp ? _hyp->GetToMeshHoles(true) : GHS3DPlugin_Hypothesis::DefaultMeshHoles(); + + helper.IsQuadraticSubMesh( theShape ); + helper.SetElementsOnShape( false ); + + Ok = readResultFile( fileOpen, +#ifdef WNT + aResultFileName.ToCString(), +#endif +#ifdef WITH_SMESH_CANCEL_COMPUTE + this, +#endif + /*theMesh, */helper, tabShape, tabBox, _nbShape, + aGhs3dIdToNodeMap, aNodeId2NodeIndexMap, + toMeshHoles, + nbEnforcedVertices, nbEnforcedNodes, + enforcedEdges, enforcedTriangles ); + +// Ok = readGMFFile( +// #ifndef GMF_HAS_SUBDOMAIN_INFO +// fileOpen, +// #endif +// aGenericName.ToCString(), theMesh, +// _nbShape, tabShape, tabBox, +// aGhs3dIdToNodeMap, toMeshHoles, +// nbEnforcedVertices, nbEnforcedNodes); + } + + + + + // --------------------- + // remove working files + // --------------------- + + if ( Ok ) + { + if ( !_keepFiles ) + removeFile( aLogFileName ); + } + else if ( OSD_File( aLogFileName ).Size() > 0 ) + { + // get problem description from the log file + _Ghs2smdsConvertor conv( aGhs3dIdToNodeMap ); + storeErrorDescription( aLogFileName, conv ); + } + else + { + // the log file is empty + removeFile( aLogFileName ); + INFOS( "GHS3D Error, command '" << cmd.ToCString() << "' failed" ); + error(COMPERR_ALGO_FAILED, "ghs3d: command not found" ); + } + + if ( !_keepFiles ) { +#ifdef WITH_SMESH_CANCEL_COMPUTE + if (! Ok) + if(_compute_canceled) + removeFile( aLogFileName ); +#endif + removeFile( aFacesFileName ); + removeFile( aPointsFileName ); + removeFile( aResultFileName ); + removeFile( aBadResFileName ); + removeFile( aBbResFileName ); + removeFile( aSmdsToGhs3dIdMapFileName ); + } + std::cout << "<" << aResultFileName.ToCString() << "> GHS3D output file "; + if ( !Ok ) + std::cout << "not "; + std::cout << "treated !" << std::endl; + std::cout << std::endl; + + _nbShape = 0; // re-initializing _nbShape for the next Compute() method call + delete [] tabShape; + delete [] tabBox; + + return Ok; +} + +//============================================================================= +/*! + *Here we are going to use the GHS3D mesher w/o geometry + */ +//============================================================================= +bool GHS3DPlugin_GHS3D::Compute(SMESH_Mesh& theMesh, + SMESH_MesherHelper* theHelper) +{ + MESSAGE("GHS3DPlugin_GHS3D::Compute()"); + + //SMESHDS_Mesh* meshDS = theMesh.GetMeshDS(); + TopoDS_Shape theShape = theHelper->GetSubShape(); + + // a unique working file name + // to avoid access to the same files by eg different users + TCollection_AsciiString aGenericName + = (char*) GHS3DPlugin_Hypothesis::GetFileName(_hyp).c_str(); + TCollection_AsciiString aGenericNameRequired = aGenericName + "_required"; + + TCollection_AsciiString aLogFileName = aGenericName + ".log"; // log + TCollection_AsciiString aResultFileName; + bool Ok; + + TCollection_AsciiString aGMFFileName, aRequiredVerticesFileName, aSolFileName; +//#ifdef _DEBUG_ + aGMFFileName = aGenericName + ".mesh"; // GMF mesh file + aResultFileName = aGenericName + "Vol.mesh"; // GMF mesh file + aRequiredVerticesFileName = aGenericNameRequired + ".mesh"; // GMF required vertices mesh file + aSolFileName = aGenericNameRequired + ".sol"; // GMF solution file +//#else +// aGMFFileName = aGenericName + ".meshb"; // GMF mesh file +// aResultFileName = aGenericName + "Vol.meshb"; // GMF mesh file +// aRequiredVerticesFileName = aGenericNameRequired + ".meshb"; // GMF required vertices mesh file +// aSolFileName = aGenericNameRequired + ".solb"; // GMF solution file +//#endif + + std::map nodeID2nodeIndexMap; + std::map, std::string> enfVerticesWithGroup; + GHS3DPlugin_Hypothesis::TGHS3DEnforcedVertexCoordsValues coordsSizeMap; + TopoDS_Shape GeomShape; +// TopAbs_ShapeEnum GeomType; + std::vector coords; + gp_Pnt aPnt; + GHS3DPlugin_Hypothesis::TGHS3DEnforcedVertex* enfVertex; + + GHS3DPlugin_Hypothesis::TGHS3DEnforcedVertexList enfVertices = GHS3DPlugin_Hypothesis::GetEnforcedVertices(_hyp); + GHS3DPlugin_Hypothesis::TGHS3DEnforcedVertexList::const_iterator enfVerIt = enfVertices.begin(); + + for ( ; enfVerIt != enfVertices.end() ; ++enfVerIt) + { + enfVertex = (*enfVerIt); +// if (enfVertex->geomEntry.empty() && enfVertex->coords.size()) { + if (enfVertex->coords.size()) { + coordsSizeMap.insert(make_pair(enfVertex->coords,enfVertex->size)); + enfVerticesWithGroup.insert(make_pair(enfVertex->coords,enfVertex->groupName)); +// MESSAGE("enfVerticesWithGroup.insert(make_pair(("<coords[0]<<","<coords[1]<<","<coords[2]<<"),\""<groupName<<"\"))"); + } + else { +// if (!enfVertex->geomEntry.empty()) { + GeomShape = entryToShape(enfVertex->geomEntry); +// GeomType = GeomShape.ShapeType(); + +// if (!enfVertex->isCompound) { +// // if (GeomType == TopAbs_VERTEX) { +// coords.clear(); +// aPnt = BRep_Tool::Pnt(TopoDS::Vertex(GeomShape)); +// coords.push_back(aPnt.X()); +// coords.push_back(aPnt.Y()); +// coords.push_back(aPnt.Z()); +// if (coordsSizeMap.find(coords) == coordsSizeMap.end()) { +// coordsSizeMap.insert(make_pair(coords,enfVertex->size)); +// enfVerticesWithGroup.insert(make_pair(coords,enfVertex->groupName)); +// } +// } +// +// // Group Management +// else { +// if (GeomType == TopAbs_COMPOUND){ + for (TopoDS_Iterator it (GeomShape); it.More(); it.Next()){ + coords.clear(); + if (it.Value().ShapeType() == TopAbs_VERTEX){ + aPnt = BRep_Tool::Pnt(TopoDS::Vertex(it.Value())); + coords.push_back(aPnt.X()); + coords.push_back(aPnt.Y()); + coords.push_back(aPnt.Z()); + if (coordsSizeMap.find(coords) == coordsSizeMap.end()) { + coordsSizeMap.insert(make_pair(coords,enfVertex->size)); + enfVerticesWithGroup.insert(make_pair(coords,enfVertex->groupName)); +// MESSAGE("enfVerticesWithGroup.insert(make_pair(("<groupName<<"\"))"); + } + } + } +// } + } + } + +// const SMDS_MeshNode* enfNode; + GHS3DPlugin_Hypothesis::TIDSortedNodeGroupMap enforcedNodes = GHS3DPlugin_Hypothesis::GetEnforcedNodes(_hyp); +// GHS3DPlugin_Hypothesis::TIDSortedNodeGroupMap::const_iterator enfNodeIt = enforcedNodes.begin(); +// for ( ; enfNodeIt != enforcedNodes.end() ; ++enfNodeIt) +// { +// enfNode = enfNodeIt->first; +// coords.clear(); +// coords.push_back(enfNode->X()); +// coords.push_back(enfNode->Y()); +// coords.push_back(enfNode->Z()); +// if (enfVerticesWithGro +// enfVerticesWithGroup.insert(make_pair(coords,enfNodeIt->second)); +// } + + + GHS3DPlugin_Hypothesis::TIDSortedElemGroupMap enforcedEdges = GHS3DPlugin_Hypothesis::GetEnforcedEdges(_hyp); + GHS3DPlugin_Hypothesis::TIDSortedElemGroupMap enforcedTriangles = GHS3DPlugin_Hypothesis::GetEnforcedTriangles(_hyp); +// TIDSortedElemSet enforcedQuadrangles = GHS3DPlugin_Hypothesis::GetEnforcedQuadrangles(_hyp); + GHS3DPlugin_Hypothesis::TID2SizeMap nodeIDToSizeMap = GHS3DPlugin_Hypothesis::GetNodeIDToSizeMap(_hyp); + + std::string tmpStr; + + int nbEnforcedVertices = coordsSizeMap.size(); + int nbEnforcedNodes = enforcedNodes.size(); + (nbEnforcedNodes <= 1) ? tmpStr = "node" : tmpStr = "nodes"; + std::cout << nbEnforcedNodes << " enforced " << tmpStr << " from hypo" << std::endl; + (nbEnforcedVertices <= 1) ? tmpStr = "vertex" : tmpStr = "vertices"; + std::cout << nbEnforcedVertices << " enforced " << tmpStr << " from hypo" << std::endl; + + std::vector aNodeByGhs3dId, anEnforcedNodeByGhs3dId; + std::map aNodeToGhs3dIdMap; + std::vector aNodeGroupByGhs3dId, anEdgeGroupByGhs3dId, aFaceGroupByGhs3dId; + { + SMESH_ProxyMesh::Ptr proxyMesh( new SMESH_ProxyMesh( theMesh )); + if ( theMesh.NbQuadrangles() > 0 ) + { + StdMeshers_QuadToTriaAdaptor* aQuad2Trias = new StdMeshers_QuadToTriaAdaptor; + aQuad2Trias->Compute( theMesh ); + proxyMesh.reset( aQuad2Trias ); + } + + Ok = writeGMFFile(aGMFFileName.ToCString(), aRequiredVerticesFileName.ToCString(), aSolFileName.ToCString(), + *proxyMesh, &theMesh, + aNodeByGhs3dId, aNodeToGhs3dIdMap, + aNodeGroupByGhs3dId, anEdgeGroupByGhs3dId, aFaceGroupByGhs3dId, + enforcedNodes, enforcedEdges, enforcedTriangles, + enfVerticesWithGroup, coordsSizeMap); + } + + // ----------------- + // run ghs3d mesher + // ----------------- + + TCollection_AsciiString cmd = TCollection_AsciiString((char*)GHS3DPlugin_Hypothesis::CommandToRun( _hyp, false ).c_str()); + + cmd += TCollection_AsciiString(" --in ") + aGenericName; + if ( nbEnforcedVertices + nbEnforcedNodes) + cmd += TCollection_AsciiString(" --required_vertices ") + aGenericNameRequired; + cmd += TCollection_AsciiString(" --out ") + aResultFileName; + cmd += TCollection_AsciiString(" 1>" ) + aLogFileName; // dump into file + + std::cout << std::endl; + std::cout << "Ghs3d execution..." << std::endl; + std::cout << cmd << std::endl; + +#ifdef WITH_SMESH_CANCEL_COMPUTE + _compute_canceled = false; +#endif + + system( cmd.ToCString() ); // run + + std::cout << std::endl; + std::cout << "End of Ghs3d execution !" << std::endl; + + // -------------- + // read a result + // -------------- + GHS3DPlugin_Hypothesis::TSetStrings groupsToRemove = GHS3DPlugin_Hypothesis::GetGroupsToRemove(_hyp); + + Ok = readGMFFile(aResultFileName.ToCString(), +#ifdef WITH_SMESH_CANCEL_COMPUTE + this, +#endif + theHelper, theShape, aNodeByGhs3dId, aNodeToGhs3dIdMap, + aNodeGroupByGhs3dId, anEdgeGroupByGhs3dId, aFaceGroupByGhs3dId, + groupsToRemove); + + updateMeshGroups(theHelper->GetMesh(), groupsToRemove); + + if ( Ok ) { + GHS3DPlugin_Hypothesis* that = (GHS3DPlugin_Hypothesis*)this->_hyp; + if (that) + that->ClearGroupsToRemove(); + } + // --------------------- + // remove working files + // --------------------- + + if ( Ok ) + { + if ( !_keepFiles ) + removeFile( aLogFileName ); + } + else if ( OSD_File( aLogFileName ).Size() > 0 ) + { + // get problem description from the log file + _Ghs2smdsConvertor conv( aNodeByGhs3dId ); + storeErrorDescription( aLogFileName, conv ); + } + else { + // the log file is empty + removeFile( aLogFileName ); + INFOS( "GHS3D Error, command '" << cmd.ToCString() << "' failed" ); + error(COMPERR_ALGO_FAILED, "ghs3d: command not found" ); + } + + if ( !_keepFiles ) + { +#ifdef WITH_SMESH_CANCEL_COMPUTE + if (! Ok) + if(_compute_canceled) + removeFile( aLogFileName ); +#endif + removeFile( aGMFFileName ); + removeFile( aResultFileName ); + removeFile( aRequiredVerticesFileName ); + removeFile( aSolFileName ); + } + return Ok; +} + +#ifdef WITH_SMESH_CANCEL_COMPUTE +void GHS3DPlugin_GHS3D::CancelCompute() +{ + _compute_canceled = true; +#ifdef WNT +#else + TCollection_AsciiString aGenericName + = (char*) GHS3DPlugin_Hypothesis::GetFileName(_hyp).c_str(); + TCollection_AsciiString cmd = + TCollection_AsciiString("ps ux | grep ") + aGenericName; + cmd += TCollection_AsciiString(" | grep -v grep | awk '{print $2}' | xargs kill -9 > /dev/null 2>&1"); + system( cmd.ToCString() ); +#endif +} +#endif + +//================================================================================ +/*! + * \brief Provide human readable text by error code reported by ghs3d + */ +//================================================================================ + +static string translateError(const int errNum) +{ + switch ( errNum ) { + case 0: + return "The surface mesh includes a face of type other than edge, " + "triangle or quadrilateral. This face type is not supported."; + case 1: + return "Not enough memory for the face table."; + case 2: + return "Not enough memory."; + case 3: + return "Not enough memory."; + case 4: + return "Face is ignored."; + case 5: + return "End of file. Some data are missing in the file."; + case 6: + return "Read error on the file. There are wrong data in the file."; + case 7: + return "the metric file is inadequate (dimension other than 3)."; + case 8: + return "the metric file is inadequate (values not per vertices)."; + case 9: + return "the metric file contains more than one field."; + case 10: + return "the number of values in the \".bb\" (metric file) is incompatible with the expected" + "value of number of mesh vertices in the \".noboite\" file."; + case 12: + return "Too many sub-domains."; + case 13: + return "the number of vertices is negative or null."; + case 14: + return "the number of faces is negative or null."; + case 15: + return "A face has a null vertex."; + case 22: + return "incompatible data."; + case 131: + return "the number of vertices is negative or null."; + case 132: + return "the number of vertices is negative or null (in the \".mesh\" file)."; + case 133: + return "the number of faces is negative or null."; + case 1000: + return "A face appears more than once in the input surface mesh."; + case 1001: + return "An edge appears more than once in the input surface mesh."; + case 1002: + return "A face has a vertex negative or null."; + case 1003: + return "NOT ENOUGH MEMORY."; + case 2000: + return "Not enough available memory."; + case 2002: + return "Some initial points cannot be inserted. The surface mesh is probably very bad " + "in terms of quality or the input list of points is wrong."; + case 2003: + return "Some vertices are too close to one another or coincident."; + case 2004: + return "Some vertices are too close to one another or coincident."; + case 2012: + return "A vertex cannot be inserted."; + case 2014: + return "There are at least two points considered as coincident."; + case 2103: + return "Some vertices are too close to one another or coincident."; + case 3000: + return "The surface mesh regeneration step has failed."; + case 3009: + return "Constrained edge cannot be enforced."; + case 3019: + return "Constrained face cannot be enforced."; + case 3029: + return "Missing faces."; + case 3100: + return "No guess to start the definition of the connected component(s)."; + case 3101: + return "The surface mesh includes at least one hole. The domain is not well defined."; + case 3102: + return "Impossible to define a component."; + case 3103: + return "The surface edge intersects another surface edge."; + case 3104: + return "The surface edge intersects the surface face."; + case 3105: + return "One boundary point lies within a surface face."; + case 3106: + return "One surface edge intersects a surface face."; + case 3107: + return "One boundary point lies within a surface edge."; + case 3108: + return "Insufficient memory ressources detected due to a bad quality surface mesh leading " + "to too many swaps."; + case 3109: + return "Edge is unique (i.e., bounds a hole in the surface)."; + case 3122: + return "Presumably, the surface mesh is not compatible with the domain being processed."; + case 3123: + return "Too many components, too many sub-domain."; + case 3209: + return "The surface mesh includes at least one hole. " + "Therefore there is no domain properly defined."; + case 3300: + return "Statistics."; + case 3400: + return "Statistics."; + case 3500: + return "Warning, it is dramatically tedious to enforce the boundary items."; + case 4000: + return "Not enough memory at this time, nevertheless, the program continues. " + "The expected mesh will be correct but not really as large as required."; + case 4002: + return "see above error code, resulting quality may be poor."; + case 4003: + return "Not enough memory at this time, nevertheless, the program continues (warning)."; + case 8000: + return "Unknown face type."; + case 8005: + case 8006: + return "End of file. Some data are missing in the file."; + case 9000: + return "A too small volume element is detected."; + case 9001: + return "There exists at least a null or negative volume element."; + case 9002: + return "There exist null or negative volume elements."; + case 9003: + return "A too small volume element is detected. A face is considered being degenerated."; + case 9100: + return "Some element is suspected to be very bad shaped or wrong."; + case 9102: + return "A too bad quality face is detected. This face is considered degenerated."; + case 9112: + return "A too bad quality face is detected. This face is degenerated."; + case 9122: + return "Presumably, the surface mesh is not compatible with the domain being processed."; + case 9999: + return "Abnormal error occured, contact hotline."; + case 23600: + return "Not enough memory for the face table."; + case 23601: + return "The algorithm cannot run further. " + "The surface mesh is probably very bad in terms of quality."; + case 23602: + return "Bad vertex number."; + } + return ""; +} + +//================================================================================ +/*! + * \brief Retrieve from a string given number of integers + */ +//================================================================================ + +static char* getIds( char* ptr, int nbIds, vector& ids ) +{ + ids.clear(); + ids.reserve( nbIds ); + while ( nbIds ) + { + while ( !isdigit( *ptr )) ++ptr; + if ( ptr[-1] == '-' ) --ptr; + ids.push_back( strtol( ptr, &ptr, 10 )); + --nbIds; + } + return ptr; +} + +//================================================================================ +/*! + * \brief Retrieve problem description form a log file + * \retval bool - always false + */ +//================================================================================ + +bool GHS3DPlugin_GHS3D::storeErrorDescription(const TCollection_AsciiString& logFile, + const _Ghs2smdsConvertor & toSmdsConvertor ) +{ +#ifdef WITH_SMESH_CANCEL_COMPUTE + if(_compute_canceled) + return error(SMESH_Comment("interruption initiated by user")); +#endif + // open file +#ifdef WNT + int file = ::_open (logFile.ToCString(), _O_RDONLY|_O_BINARY); +#else + int file = ::open (logFile.ToCString(), O_RDONLY); +#endif + if ( file < 0 ) + return error( SMESH_Comment("See ") << logFile << " for problem description"); + + // get file size +// struct stat status; +// fstat(file, &status); +// size_t length = status.st_size; + off_t length = lseek( file, 0, SEEK_END); + lseek( file, 0, SEEK_SET); + + // read file + vector< char > buf( length ); + int nBytesRead = ::read (file, & buf[0], length); + ::close (file); + char* ptr = & buf[0]; + char* bufEnd = ptr + nBytesRead; + + SMESH_Comment errDescription; + + enum { NODE = 1, EDGE, TRIA, VOL, ID = 1 }; + + // look for errors "ERR #" + + set foundErrorStr; // to avoid reporting same error several times + set elemErrorNums; // not to report different types of errors with bad elements + while ( ++ptr < bufEnd ) + { + if ( strncmp( ptr, "ERR ", 4 ) != 0 ) + continue; + + list badElems; + vector nodeIds; + + ptr += 4; + char* errBeg = ptr; + int errNum = strtol(ptr, &ptr, 10); + switch ( errNum ) { // we treat errors enumerated in [SALOME platform 0019316] issue + case 0015: + // The face number (numfac) with vertices (f 1, f 2, f 3) has a null vertex. + ptr = getIds(ptr, NODE, nodeIds); + ptr = getIds(ptr, TRIA, nodeIds); + badElems.push_back( toSmdsConvertor.getElement(nodeIds)); + break; + case 1000: // ERR 1000 : 1 3 2 + // Face (f 1, f 2, f 3) appears more than once in the input surface mesh. + ptr = getIds(ptr, TRIA, nodeIds); + badElems.push_back( toSmdsConvertor.getElement(nodeIds)); + break; + case 1001: + // Edge (e1, e2) appears more than once in the input surface mesh + ptr = getIds(ptr, EDGE, nodeIds); + badElems.push_back( toSmdsConvertor.getElement(nodeIds)); + break; + case 1002: + // Face (f 1, f 2, f 3) has a vertex negative or null + ptr = getIds(ptr, TRIA, nodeIds); + badElems.push_back( toSmdsConvertor.getElement(nodeIds)); + break; + case 2004: + // Vertex v1 and vertex v2 are too close to one another or coincident (warning). + ptr = getIds(ptr, NODE, nodeIds); + badElems.push_back( toSmdsConvertor.getElement(nodeIds)); + ptr = getIds(ptr, NODE, nodeIds); + badElems.push_back( toSmdsConvertor.getElement(nodeIds)); + break; + case 2012: + // Vertex v1 cannot be inserted (warning). + ptr = getIds(ptr, NODE, nodeIds); + badElems.push_back( toSmdsConvertor.getElement(nodeIds)); + break; + case 2014: + // There are at least two points whose distance is dist, i.e., considered as coincident + case 2103: // ERR 2103 : 16 WITH 3 + // Vertex v1 and vertex v2 are too close to one another or coincident (warning). + ptr = getIds(ptr, NODE, nodeIds); + badElems.push_back( toSmdsConvertor.getElement(nodeIds)); + ptr = getIds(ptr, NODE, nodeIds); + badElems.push_back( toSmdsConvertor.getElement(nodeIds)); + break; + case 3009: + // Constrained edge (e1, e2) cannot be enforced (warning). + ptr = getIds(ptr, EDGE, nodeIds); + badElems.push_back( toSmdsConvertor.getElement(nodeIds)); + break; + case 3019: + // Constrained face (f 1, f 2, f 3) cannot be enforced + ptr = getIds(ptr, TRIA, nodeIds); + badElems.push_back( toSmdsConvertor.getElement(nodeIds)); + break; + case 3103: // ERR 3103 : 1 2 WITH 7 3 + // The surface edge (e1, e2) intersects another surface edge (e3, e4) + ptr = getIds(ptr, EDGE, nodeIds); + badElems.push_back( toSmdsConvertor.getElement(nodeIds)); + ptr = getIds(ptr, EDGE, nodeIds); + badElems.push_back( toSmdsConvertor.getElement(nodeIds)); + break; + case 3104: // ERR 3104 : 9 10 WITH 1 2 3 + // The surface edge (e1, e2) intersects the surface face (f 1, f 2, f 3) + ptr = getIds(ptr, EDGE, nodeIds); + badElems.push_back( toSmdsConvertor.getElement(nodeIds)); + ptr = getIds(ptr, TRIA, nodeIds); + badElems.push_back( toSmdsConvertor.getElement(nodeIds)); + break; + case 3105: // ERR 3105 : 8 IN 2 3 5 + // One boundary point (say p1) lies within a surface face (f 1, f 2, f 3) + ptr = getIds(ptr, NODE, nodeIds); + badElems.push_back( toSmdsConvertor.getElement(nodeIds)); + ptr = getIds(ptr, TRIA, nodeIds); + badElems.push_back( toSmdsConvertor.getElement(nodeIds)); + break; + case 3106: + // One surface edge (say e1, e2) intersects a surface face (f 1, f 2, f 3) + ptr = getIds(ptr, EDGE, nodeIds); + badElems.push_back( toSmdsConvertor.getElement(nodeIds)); + ptr = getIds(ptr, TRIA, nodeIds); + badElems.push_back( toSmdsConvertor.getElement(nodeIds)); + break; + case 3107: // ERR 3107 : 2 IN 4 1 + // One boundary point (say p1) lies within a surface edge (e1, e2) (stop). + ptr = getIds(ptr, NODE, nodeIds); + badElems.push_back( toSmdsConvertor.getElement(nodeIds)); + ptr = getIds(ptr, EDGE, nodeIds); + badElems.push_back( toSmdsConvertor.getElement(nodeIds)); + break; + case 3109: // ERR 3109 : EDGE 5 6 UNIQUE + // Edge (e1, e2) is unique (i.e., bounds a hole in the surface) + ptr = getIds(ptr, EDGE, nodeIds); + badElems.push_back( toSmdsConvertor.getElement(nodeIds)); + break; + case 9000: // ERR 9000 + // ELEMENT 261 WITH VERTICES : 7 396 -8 242 + // VOLUME : -1.11325045E+11 W.R.T. EPSILON 0. + // A too small volume element is detected. Are reported the index of the element, + // its four vertex indices, its volume and the tolerance threshold value + ptr = getIds(ptr, ID, nodeIds); + ptr = getIds(ptr, VOL, nodeIds); + badElems.push_back( toSmdsConvertor.getElement(nodeIds)); + // even if all nodes found, volume it most probably invisible, + // add its faces to demenstrate it anyhow + { + vector faceNodes( nodeIds.begin(), --nodeIds.end() ); // 012 + badElems.push_back( toSmdsConvertor.getElement(faceNodes)); + faceNodes[2] = nodeIds[3]; // 013 + badElems.push_back( toSmdsConvertor.getElement(faceNodes)); + faceNodes[1] = nodeIds[2]; // 023 + badElems.push_back( toSmdsConvertor.getElement(faceNodes)); + faceNodes[0] = nodeIds[1]; // 123 + badElems.push_back( toSmdsConvertor.getElement(faceNodes)); + } + break; + case 9001: // ERR 9001 + // %% NUMBER OF NEGATIVE VOLUME TETS : 1 + // %% THE LARGEST NEGATIVE TET : 1.75376581E+11 + // %% NUMBER OF NULL VOLUME TETS : 0 + // There exists at least a null or negative volume element + break; + case 9002: + // There exist n null or negative volume elements + break; + case 9003: + // A too small volume element is detected + break; + case 9102: + // A too bad quality face is detected. This face is considered degenerated, + // its index, its three vertex indices together with its quality value are reported + break; // same as next + case 9112: // ERR 9112 + // FACE 2 WITH VERTICES : 4 2 5 + // SMALL INRADIUS : 0. + // A too bad quality face is detected. This face is degenerated, + // its index, its three vertex indices together with its inradius are reported + ptr = getIds(ptr, ID, nodeIds); + ptr = getIds(ptr, TRIA, nodeIds); + badElems.push_back( toSmdsConvertor.getElement(nodeIds)); + // add triangle edges as it most probably has zero area and hence invisible + { + vector edgeNodes(2); + edgeNodes[0] = nodeIds[0]; edgeNodes[1] = nodeIds[1]; // 0-1 + badElems.push_back( toSmdsConvertor.getElement(edgeNodes)); + edgeNodes[1] = nodeIds[2]; // 0-2 + badElems.push_back( toSmdsConvertor.getElement(edgeNodes)); + edgeNodes[0] = nodeIds[1]; // 1-2 + badElems.push_back( toSmdsConvertor.getElement(edgeNodes)); + } + break; + } + + bool isNewError = foundErrorStr.insert( string( errBeg, ptr )).second; + if ( !isNewError ) + continue; // not to report same error several times + +// const SMDS_MeshElement* nullElem = 0; +// bool allElemsOk = ( find( badElems.begin(), badElems.end(), nullElem) == badElems.end()); + +// if ( allElemsOk && !badElems.empty() && !elemErrorNums.empty() ) { +// bool oneMoreErrorType = elemErrorNums.insert( errNum ).second; +// if ( oneMoreErrorType ) +// continue; // not to report different types of errors with bad elements +// } + + // store bad elements + //if ( allElemsOk ) { + list::iterator elem = badElems.begin(); + for ( ; elem != badElems.end(); ++elem ) + addBadInputElement( *elem ); + //} + + // make error text + string text = translateError( errNum ); + if ( errDescription.find( text ) == text.npos ) { + if ( !errDescription.empty() ) + errDescription << "\n"; + errDescription << text; + } + + } // end while + + if ( errDescription.empty() ) { // no errors found + char msgLic1[] = "connection to server failed"; + char msgLic2[] = " Dlim "; + if ( search( &buf[0], bufEnd, msgLic1, msgLic1 + strlen(msgLic1)) != bufEnd || + search( &buf[0], bufEnd, msgLic2, msgLic2 + strlen(msgLic2)) != bufEnd ) + errDescription << "Licence problems."; + else + { + char msg2[] = "SEGMENTATION FAULT"; + if ( search( &buf[0], bufEnd, msg2, msg2 + strlen(msg2)) != bufEnd ) + errDescription << "ghs3d: SEGMENTATION FAULT. "; + } + } + + if ( errDescription.empty() ) + errDescription << "See " << logFile << " for problem description"; + else + errDescription << "\nSee " << logFile << " for more information"; + + return error( errDescription ); +} + +//================================================================================ +/*! + * \brief Creates _Ghs2smdsConvertor + */ +//================================================================================ + +_Ghs2smdsConvertor::_Ghs2smdsConvertor( const map & ghs2NodeMap) + :_ghs2NodeMap( & ghs2NodeMap ), _nodeByGhsId( 0 ) +{ +} + +//================================================================================ +/*! + * \brief Creates _Ghs2smdsConvertor + */ +//================================================================================ + +_Ghs2smdsConvertor::_Ghs2smdsConvertor( const vector & nodeByGhsId) + : _ghs2NodeMap( 0 ), _nodeByGhsId( &nodeByGhsId ) +{ +} + +//================================================================================ +/*! + * \brief Return SMDS element by ids of GHS3D nodes + */ +//================================================================================ + +const SMDS_MeshElement* _Ghs2smdsConvertor::getElement(const vector& ghsNodes) const +{ + size_t nbNodes = ghsNodes.size(); + vector nodes( nbNodes, 0 ); + for ( size_t i = 0; i < nbNodes; ++i ) { + int ghsNode = ghsNodes[ i ]; + if ( _ghs2NodeMap ) { + map ::const_iterator in = _ghs2NodeMap->find( ghsNode); + if ( in == _ghs2NodeMap->end() ) + return 0; + nodes[ i ] = in->second; + } + else { + if ( ghsNode < 1 || ghsNode > _nodeByGhsId->size() ) + return 0; + nodes[ i ] = (*_nodeByGhsId)[ ghsNode-1 ]; + } + } + if ( nbNodes == 1 ) + return nodes[0]; + + if ( nbNodes == 2 ) { + const SMDS_MeshElement* edge= SMDS_Mesh::FindEdge( nodes[0], nodes[1] ); + if ( !edge ) + edge = new SMDS_LinearEdge( nodes[0], nodes[1] ); + return edge; + } + if ( nbNodes == 3 ) { + const SMDS_MeshElement* face = SMDS_Mesh::FindFace( nodes ); + if ( !face ) + face = new SMDS_FaceOfNodes( nodes[0], nodes[1], nodes[2] ); + return face; + } + if ( nbNodes == 4 ) + return new SMDS_VolumeOfNodes( nodes[0], nodes[1], nodes[2], nodes[3] ); + + return 0; +} + + +//============================================================================= +/*! + * + */ +//============================================================================= +bool GHS3DPlugin_GHS3D::Evaluate(SMESH_Mesh& aMesh, + const TopoDS_Shape& aShape, + MapShapeNbElems& aResMap) +{ + int nbtri = 0, nbqua = 0; + double fullArea = 0.0; + for (TopExp_Explorer exp(aShape, TopAbs_FACE); exp.More(); exp.Next()) { + TopoDS_Face F = TopoDS::Face( exp.Current() ); + SMESH_subMesh *sm = aMesh.GetSubMesh(F); + MapShapeNbElemsItr anIt = aResMap.find(sm); + if( anIt==aResMap.end() ) { + SMESH_ComputeErrorPtr& smError = sm->GetComputeError(); + smError.reset( new SMESH_ComputeError(COMPERR_ALGO_FAILED, + "Submesh can not be evaluated",this)); + return false; + } + std::vector aVec = (*anIt).second; + nbtri += Max(aVec[SMDSEntity_Triangle],aVec[SMDSEntity_Quad_Triangle]); + nbqua += Max(aVec[SMDSEntity_Quadrangle],aVec[SMDSEntity_Quad_Quadrangle]); + GProp_GProps G; + BRepGProp::SurfaceProperties(F,G); + double anArea = G.Mass(); + fullArea += anArea; + } + + // collect info from edges + int nb0d_e = 0, nb1d_e = 0; + bool IsQuadratic = false; + bool IsFirst = true; + TopTools_MapOfShape tmpMap; + for (TopExp_Explorer exp(aShape, TopAbs_EDGE); exp.More(); exp.Next()) { + TopoDS_Edge E = TopoDS::Edge(exp.Current()); + if( tmpMap.Contains(E) ) + continue; + tmpMap.Add(E); + SMESH_subMesh *aSubMesh = aMesh.GetSubMesh(exp.Current()); + MapShapeNbElemsItr anIt = aResMap.find(aSubMesh); + std::vector aVec = (*anIt).second; + nb0d_e += aVec[SMDSEntity_Node]; + nb1d_e += Max(aVec[SMDSEntity_Edge],aVec[SMDSEntity_Quad_Edge]); + if(IsFirst) { + IsQuadratic = (aVec[SMDSEntity_Quad_Edge] > aVec[SMDSEntity_Edge]); + IsFirst = false; + } + } + tmpMap.Clear(); + + double ELen = sqrt(2.* ( fullArea/(nbtri+nbqua*2) ) / sqrt(3.0) ); + + GProp_GProps G; + BRepGProp::VolumeProperties(aShape,G); + double aVolume = G.Mass(); + double tetrVol = 0.1179*ELen*ELen*ELen; + double CoeffQuality = 0.9; + int nbVols = int(aVolume/tetrVol/CoeffQuality); + int nb1d_f = (nbtri*3 + nbqua*4 - nb1d_e) / 2; + int nb1d_in = (int) ( nbVols*6 - nb1d_e - nb1d_f ) / 5; + std::vector aVec(SMDSEntity_Last); + for(int i=SMDSEntity_Node; i dummyNodeVector; + std::map dummyNodeMap; + std::map, std::string> dummyEnfVertGroup; + std::vector dummyElemGroup; + std::set dummyGroupsToRemove; + + bool ok = readGMFFile(theGMFFileName, +#ifdef WITH_SMESH_CANCEL_COMPUTE + this, +#endif + helper, theMesh.GetShapeToMesh(), dummyNodeVector, dummyNodeMap, dummyElemGroup, dummyElemGroup, dummyElemGroup, dummyGroupsToRemove); + theMesh.GetMeshDS()->Modified(); + return ok; +} diff --git a/src/GHS3DPlugin_GHS3D.hxx b/src/GHS3DPlugin/GHS3DPlugin_GHS3D.hxx similarity index 53% rename from src/GHS3DPlugin_GHS3D.hxx rename to src/GHS3DPlugin/GHS3DPlugin_GHS3D.hxx index 8c9d7e3..7b9b02e 100644 --- a/src/GHS3DPlugin_GHS3D.hxx +++ b/src/GHS3DPlugin/GHS3DPlugin_GHS3D.hxx @@ -1,41 +1,55 @@ -// Copyright (C) 2004-2008 CEA/DEN, EDF R&D +// Copyright (C) 2004-2012 CEA/DEN, EDF R&D // -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License. +// 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. +// 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 +// 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 +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // + //============================================================================= // File : GHS3DPlugin_GHS3D.hxx // Author : Edward AGAPOV, modified by Lioka RAZAFINDRAZAKA (CEA) 09/02/2007 // Project : SALOME -// $Header$ //============================================================================= // #ifndef _GHS3DPlugin_GHS3D_HXX_ #define _GHS3DPlugin_GHS3D_HXX_ #include "SMESH_3D_Algo.hxx" +#include "SMESH_Gen.hxx" +#include "SMESH_Gen_i.hxx" #include #include -class SMESH_Mesh; +extern "C" +{ + #include "libmesh5.h" +} + +#ifndef GMFVERSION +#define GMFVERSION GmfDouble +#endif +#define GMFDIMENSION 3 + class GHS3DPlugin_Hypothesis; class SMDS_MeshNode; +class SMESH_Mesh; +class StdMeshers_ViscousLayers; class TCollection_AsciiString; class _Ghs2smdsConvertor; +class TopoDS_Shape; class GHS3DPlugin_GHS3D: public SMESH_3D_Algo { @@ -50,18 +64,37 @@ public: virtual bool Compute(SMESH_Mesh& aMesh, const TopoDS_Shape& aShape); +#ifdef WITH_SMESH_CANCEL_COMPUTE + virtual void CancelCompute(); + bool computeCanceled() { return _compute_canceled;}; +#endif + + virtual bool Evaluate(SMESH_Mesh& aMesh, const TopoDS_Shape& aShape, + MapShapeNbElems& aResMap); + virtual bool Compute(SMESH_Mesh& theMesh, SMESH_MesherHelper* aHelper); + bool importGMFMesh(const char* aGMFFileName, SMESH_Mesh& aMesh); + private: bool storeErrorDescription(const TCollection_AsciiString& logFile, const _Ghs2smdsConvertor & toSmdsConvertor ); - + TopoDS_Shape entryToShape(std::string entry); + int _iShape; int _nbShape; bool _keepFiles; const GHS3DPlugin_Hypothesis* _hyp; + const StdMeshers_ViscousLayers* _viscousLayersHyp; + SALOMEDS::Study_var myStudy; + SMESH_Gen_i* smeshGen_i; + +#ifdef WITH_SMESH_CANCEL_COMPUTE + volatile bool _compute_canceled; +#endif + }; /*! diff --git a/src/GHS3DPlugin/GHS3DPlugin_GHS3D_i.cxx b/src/GHS3DPlugin/GHS3DPlugin_GHS3D_i.cxx new file mode 100644 index 0000000..a9151b6 --- /dev/null +++ b/src/GHS3DPlugin/GHS3DPlugin_GHS3D_i.cxx @@ -0,0 +1,116 @@ +// Copyright (C) 2004-2012 CEA/DEN, EDF R&D +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// 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_I : idl implementation based on 'SMESH' unit's calsses +// File : GHS3DPlugin_GHS3D_i.cxx +// Author : Edward AGAPOV +// Module : GHS3DPlugin +// $Header$ +// +#include "GHS3DPlugin_GHS3D_i.hxx" +#include "SMESH_Gen.hxx" +#include "SMESH_Mesh_i.hxx" +#include "SMESH_Gen_i.hxx" +#include "GHS3DPlugin_GHS3D.hxx" +#include "SMESH_PythonDump.hxx" + +#include "utilities.h" +#include + +//============================================================================= +/*! + * GHS3DPlugin_GHS3D_i::GHS3DPlugin_GHS3D_i + * + * Constructor + */ +//============================================================================= + +GHS3DPlugin_GHS3D_i::GHS3DPlugin_GHS3D_i (PortableServer::POA_ptr thePOA, + int theStudyId, + ::SMESH_Gen* theGenImpl ) + : SALOME::GenericObj_i( thePOA ), + SMESH_Hypothesis_i( thePOA ), + SMESH_Algo_i( thePOA ), + SMESH_3D_Algo_i( thePOA ) +{ + MESSAGE( "GHS3DPlugin_GHS3D_i::GHS3DPlugin_GHS3D_i" ); + myBaseImpl = new ::GHS3DPlugin_GHS3D (theGenImpl->GetANewId(), + theStudyId, + theGenImpl ); +} + +//============================================================================= +/*! + * GHS3DPlugin_GHS3D_i::~GHS3DPlugin_GHS3D_i + * + * Destructor + */ +//============================================================================= + +GHS3DPlugin_GHS3D_i::~GHS3DPlugin_GHS3D_i() +{ + MESSAGE( "GHS3DPlugin_GHS3D_i::~GHS3DPlugin_GHS3D_i" ); +} + +//============================================================================= +/*! + * GHS3DPlugin_GHS3D_i::GetImpl + * + * Get implementation + */ +//============================================================================= + +::GHS3DPlugin_GHS3D* GHS3DPlugin_GHS3D_i::GetImpl() +{ + MESSAGE( "GHS3DPlugin_GHS3D_i::GetImpl" ); + return ( ::GHS3DPlugin_GHS3D* )myBaseImpl; +} + +//============================================================================= +/*! + * GHS3DPlugin_GHS3D_i::~GHS3DPlugin_GHS3D_i + * + * Destructor + */ +//============================================================================= + +SMESH::SMESH_Mesh_ptr GHS3DPlugin_GHS3D_i::importGMFMesh(const char* theGMFFileName) +{ + MESSAGE( "GHS3DPlugin_GHS3D_i::importGMFMesh" ); + SMESH_Gen_i* smeshGen = SMESH_Gen_i::GetSMESHGen(); + SMESH::SMESH_Mesh_ptr theMesh = smeshGen->CreateEmptyMesh(); + smeshGen->RemoveLastFromPythonScript(smeshGen->GetCurrentStudy()->StudyId()); + SALOMEDS::SObject_ptr theSMesh = smeshGen->ObjectToSObject(smeshGen->GetCurrentStudy(), theMesh); +#ifdef WINNT +#define SEP '\\' +#else +#define SEP '/' +#endif + string strFileName (theGMFFileName); + strFileName = strFileName.substr(strFileName.rfind(SEP)+1); + strFileName.erase(strFileName.rfind('.')); + smeshGen->SetName(theSMesh, strFileName.c_str()); + SMESH_Mesh_i* meshServant = dynamic_cast( smeshGen->GetServant( theMesh ).in() ); + ASSERT( meshServant ); + if ( meshServant ) { + if (GetImpl()->importGMFMesh(theGMFFileName, meshServant->GetImpl())) + SMESH::TPythonDump() << theSMesh << " = " << _this() << ".importGMFMesh( \"" << theGMFFileName << "\")"; + } + return theMesh; +} diff --git a/src/GHS3DPlugin_GHS3D_i.hxx b/src/GHS3DPlugin/GHS3DPlugin_GHS3D_i.hxx similarity index 51% rename from src/GHS3DPlugin_GHS3D_i.hxx rename to src/GHS3DPlugin/GHS3DPlugin_GHS3D_i.hxx index 6fea6fc..daea628 100644 --- a/src/GHS3DPlugin_GHS3D_i.hxx +++ b/src/GHS3DPlugin/GHS3DPlugin_GHS3D_i.hxx @@ -1,21 +1,22 @@ -// Copyright (C) 2004-2008 CEA/DEN, EDF R&D +// Copyright (C) 2004-2012 CEA/DEN, EDF R&D // -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License. +// 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. +// 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 +// 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 +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // + // File : GHS3DPlugin_GHS3D_i.hxx // Author : Edward AGAPOV // Module : GHS3DPlugin @@ -48,6 +49,8 @@ public: // Get implementation ::GHS3DPlugin_GHS3D* GetImpl(); + + virtual SMESH::SMESH_Mesh_ptr importGMFMesh(const char* theGMFFileName); }; #endif diff --git a/src/GHS3DPlugin/GHS3DPlugin_Hypothesis.cxx b/src/GHS3DPlugin/GHS3DPlugin_Hypothesis.cxx new file mode 100644 index 0000000..7aa5341 --- /dev/null +++ b/src/GHS3DPlugin/GHS3DPlugin_Hypothesis.cxx @@ -0,0 +1,1356 @@ +// Copyright (C) 2004-2012 CEA/DEN, EDF R&D +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// 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 : GHS3DPlugin_Hypothesis.cxx +// Created : Wed Apr 2 12:36:29 2008 +// Author : Edward AGAPOV (eap) +//============================================================================= +// +#include "GHS3DPlugin_Hypothesis.hxx" +#include +#include +#include + +#include + +#ifdef WNT +#include +#define getpid _getpid +#endif + +//======================================================================= +//function : GHS3DPlugin_Hypothesis +//======================================================================= + +GHS3DPlugin_Hypothesis::GHS3DPlugin_Hypothesis(int hypId, int studyId, SMESH_Gen * gen) + : SMESH_Hypothesis(hypId, studyId, gen), + myToMeshHoles(DefaultMeshHoles()), + myMaximumMemory(-1), + myInitialMemory(-1), + myOptimizationLevel(DefaultOptimizationLevel()), + myWorkingDirectory(DefaultWorkingDirectory()), + myKeepFiles(DefaultKeepFiles()), + myVerboseLevel(DefaultVerboseLevel()), + myToCreateNewNodes(DefaultToCreateNewNodes()), + myToUseBoundaryRecoveryVersion(DefaultToUseBoundaryRecoveryVersion()), + myToUseFemCorrection(DefaultToUseFEMCorrection()), + myToRemoveCentralPoint(DefaultToRemoveCentralPoint()), + _enfVertexList(DefaultGHS3DEnforcedVertexList()), + _enfVertexCoordsSizeList(DefaultGHS3DEnforcedVertexCoordsValues()), + _enfVertexEntrySizeList(DefaultGHS3DEnforcedVertexEntryValues()), + _coordsEnfVertexMap(DefaultCoordsGHS3DEnforcedVertexMap()), + _geomEntryEnfVertexMap(DefaultGeomEntryGHS3DEnforcedVertexMap()), + _enfMeshList(DefaultGHS3DEnforcedMeshList()), + _entryEnfMeshMap(DefaultEntryGHS3DEnforcedMeshListMap()), + _enfNodes(TIDSortedNodeGroupMap()), + _enfEdges(TIDSortedElemGroupMap()), + _enfTriangles(TIDSortedElemGroupMap()), + _nodeIDToSizeMap(DefaultID2SizeMap()), + _elementIDToSizeMap(DefaultID2SizeMap()), + _groupsToRemove(DefaultGroupsToRemove()) +{ + _name = "GHS3D_Parameters"; + _param_algo_dim = 3; +} + +//======================================================================= +//function : SetToMeshHoles +//======================================================================= + +void GHS3DPlugin_Hypothesis::SetToMeshHoles(bool toMesh) +{ + if ( myToMeshHoles != toMesh ) { + myToMeshHoles = toMesh; + NotifySubMeshesHypothesisModification(); + } +} + +//======================================================================= +//function : GetToMeshHoles +//======================================================================= + +bool GHS3DPlugin_Hypothesis::GetToMeshHoles(bool checkFreeOption) const +{ + if (checkFreeOption && !myTextOption.empty()) { + if ( myTextOption.find("-c 0")) + return true; + if ( myTextOption.find("-c 1")) + return false; + } + return myToMeshHoles; +} + +//======================================================================= +//function : SetMaximumMemory +//======================================================================= + +void GHS3DPlugin_Hypothesis::SetMaximumMemory(short MB) +{ + if ( myMaximumMemory != MB ) { + myMaximumMemory = MB; + NotifySubMeshesHypothesisModification(); + } +} + +//======================================================================= +//function : GetMaximumMemory +// * automatic memory adjustment mode. Default is zero +//======================================================================= + +short GHS3DPlugin_Hypothesis::GetMaximumMemory() const +{ + return myMaximumMemory; +} + +//======================================================================= +//function : SetInitialMemory +//======================================================================= + +void GHS3DPlugin_Hypothesis::SetInitialMemory(short MB) +{ + if ( myInitialMemory != MB ) { + myInitialMemory = MB; + NotifySubMeshesHypothesisModification(); + } +} + +//======================================================================= +//function : GetInitialMemory +//======================================================================= + +short GHS3DPlugin_Hypothesis::GetInitialMemory() const +{ + return myInitialMemory; +} + +//======================================================================= +//function : SetOptimizationLevel +//======================================================================= + +void GHS3DPlugin_Hypothesis::SetOptimizationLevel(OptimizationLevel level) +{ + if ( myOptimizationLevel != level ) { + myOptimizationLevel = level; + NotifySubMeshesHypothesisModification(); + } +} + +//======================================================================= +//function : GetOptimizationLevel +//======================================================================= + +GHS3DPlugin_Hypothesis::OptimizationLevel GHS3DPlugin_Hypothesis::GetOptimizationLevel() const +{ + return (OptimizationLevel) myOptimizationLevel; +} + +//======================================================================= +//function : SetWorkingDirectory +//======================================================================= + +void GHS3DPlugin_Hypothesis::SetWorkingDirectory(const std::string& path) +{ + if ( myWorkingDirectory != path ) { + myWorkingDirectory = path; + NotifySubMeshesHypothesisModification(); + } +} + +//======================================================================= +//function : GetWorkingDirectory +//======================================================================= + +std::string GHS3DPlugin_Hypothesis::GetWorkingDirectory() const +{ + return myWorkingDirectory; +} + +//======================================================================= +//function : SetKeepFiles +//======================================================================= + +void GHS3DPlugin_Hypothesis::SetKeepFiles(bool toKeep) +{ + if ( myKeepFiles != toKeep ) { + myKeepFiles = toKeep; + NotifySubMeshesHypothesisModification(); + } +} + +//======================================================================= +//function : GetKeepFiles +//======================================================================= + +bool GHS3DPlugin_Hypothesis::GetKeepFiles() const +{ + return myKeepFiles; +} + +//======================================================================= +//function : SetVerboseLevel +//======================================================================= + +void GHS3DPlugin_Hypothesis::SetVerboseLevel(short level) +{ + if ( myVerboseLevel != level ) { + myVerboseLevel = level; + NotifySubMeshesHypothesisModification(); + } +} + +//======================================================================= +//function : GetVerboseLevel +//======================================================================= + +short GHS3DPlugin_Hypothesis::GetVerboseLevel() const +{ + return myVerboseLevel; +} + +//======================================================================= +//function : SetToCreateNewNodes +//======================================================================= + +void GHS3DPlugin_Hypothesis::SetToCreateNewNodes(bool toCreate) +{ + if ( myToCreateNewNodes != toCreate ) { + myToCreateNewNodes = toCreate; + NotifySubMeshesHypothesisModification(); + } +} + +//======================================================================= +//function : GetToCreateNewNodes +//======================================================================= + +bool GHS3DPlugin_Hypothesis::GetToCreateNewNodes() const +{ + return myToCreateNewNodes; +} + +//======================================================================= +//function : SetToUseBoundaryRecoveryVersion +//======================================================================= + +void GHS3DPlugin_Hypothesis::SetToUseBoundaryRecoveryVersion(bool toUse) +{ + if ( myToUseBoundaryRecoveryVersion != toUse ) { + myToUseBoundaryRecoveryVersion = toUse; + NotifySubMeshesHypothesisModification(); + } +} + +//======================================================================= +//function : GetToUseBoundaryRecoveryVersion +//======================================================================= + +bool GHS3DPlugin_Hypothesis::GetToUseBoundaryRecoveryVersion() const +{ + return myToUseBoundaryRecoveryVersion; +} + +//======================================================================= +//function : SetFEMCorrection +//======================================================================= + +void GHS3DPlugin_Hypothesis::SetFEMCorrection(bool toUseFem) +{ + if ( myToUseFemCorrection != toUseFem ) { + myToUseFemCorrection = toUseFem; + NotifySubMeshesHypothesisModification(); + } +} + +//======================================================================= +//function : GetFEMCorrection +//======================================================================= + +bool GHS3DPlugin_Hypothesis::GetFEMCorrection() const +{ + return myToUseFemCorrection; +} + +//======================================================================= +//function : SetToRemoveCentralPoint +//======================================================================= + +void GHS3DPlugin_Hypothesis::SetToRemoveCentralPoint(bool toRemove) +{ + if ( myToRemoveCentralPoint != toRemove ) { + myToRemoveCentralPoint = toRemove; + NotifySubMeshesHypothesisModification(); + } +} + +//======================================================================= +//function : GetToRemoveCentralPoint +//======================================================================= + +bool GHS3DPlugin_Hypothesis::GetToRemoveCentralPoint() const +{ + return myToRemoveCentralPoint; +} + +//======================================================================= +//function : SetTextOption +//======================================================================= + +void GHS3DPlugin_Hypothesis::SetTextOption(const std::string& option) +{ + if ( myTextOption != option ) { + myTextOption = option; + NotifySubMeshesHypothesisModification(); + } +} + +//======================================================================= +//function : GetTextOption +//======================================================================= + +std::string GHS3DPlugin_Hypothesis::GetTextOption() const +{ + return myTextOption; +} + +//======================================================================= +//function : SetEnforcedVertex +//======================================================================= + +bool GHS3DPlugin_Hypothesis::SetEnforcedVertex(std::string theName, std::string theEntry, std::string theGroupName, + double size, double x, double y, double z, bool isCompound) +{ + MESSAGE("GHS3DPlugin_Hypothesis::SetEnforcedVertex(\""<< theName << "\", \""<< theEntry << "\", \"" << theGroupName << "\", " + << size << ", " << x << ", " << y << ", " << z << ", "<< isCompound << ")"); + + bool toNotify = false; + bool toCreate = true; + + TGHS3DEnforcedVertex *oldEnVertex; + TGHS3DEnforcedVertex *newEnfVertex = new TGHS3DEnforcedVertex(); + newEnfVertex->name = theName; + newEnfVertex->geomEntry = theEntry; + newEnfVertex->coords.clear(); + if (!isCompound) { + newEnfVertex->coords.push_back(x); + newEnfVertex->coords.push_back(y); + newEnfVertex->coords.push_back(z); + } + newEnfVertex->groupName = theGroupName; + newEnfVertex->size = size; + newEnfVertex->isCompound = isCompound; + + + // update _enfVertexList + TGHS3DEnforcedVertexList::iterator it = _enfVertexList.find(newEnfVertex); + if (it != _enfVertexList.end()) { + toCreate = false; + oldEnVertex = (*it); + MESSAGE("Enforced Vertex was found => Update"); + if (oldEnVertex->name != theName) { + MESSAGE("Update name from \"" << oldEnVertex->name << "\" to \"" << theName << "\""); + oldEnVertex->name = theName; + toNotify = true; + } + if (oldEnVertex->groupName != theGroupName) { + MESSAGE("Update group name from \"" << oldEnVertex->groupName << "\" to \"" << theGroupName << "\""); + oldEnVertex->groupName = theGroupName; + toNotify = true; + } + if (oldEnVertex->size != size) { + MESSAGE("Update size from \"" << oldEnVertex->size << "\" to \"" << size << "\""); + oldEnVertex->size = size; + toNotify = true; + } + if (toNotify) { + // update map coords / enf vertex if needed + if (oldEnVertex->coords.size()) { + _coordsEnfVertexMap[oldEnVertex->coords] = oldEnVertex; + _enfVertexCoordsSizeList[oldEnVertex->coords] = size; + } + + // update map geom entry / enf vertex if needed + if (oldEnVertex->geomEntry != "") { + _geomEntryEnfVertexMap[oldEnVertex->geomEntry] = oldEnVertex; + _enfVertexEntrySizeList[oldEnVertex->geomEntry] = size; + } + } + } + +// //////// CREATE //////////// + if (toCreate) { + toNotify = true; + MESSAGE("Creating new enforced vertex"); + _enfVertexList.insert(newEnfVertex); + if (theEntry == "") { + _coordsEnfVertexMap[newEnfVertex->coords] = newEnfVertex; + _enfVertexCoordsSizeList[newEnfVertex->coords] = size; + } + else { + _geomEntryEnfVertexMap[newEnfVertex->geomEntry] = newEnfVertex; + _enfVertexEntrySizeList[newEnfVertex->geomEntry] = size; + } + } + + if (toNotify) + NotifySubMeshesHypothesisModification(); + + MESSAGE("GHS3DPlugin_Hypothesis::SetEnforcedVertex END"); + return toNotify; +} + + +//======================================================================= +//function : SetEnforcedMesh +//======================================================================= +bool GHS3DPlugin_Hypothesis::SetEnforcedMesh(SMESH_Mesh& theMesh, SMESH::ElementType elementType, std::string name, std::string entry, double size, std::string groupName) +{ + TIDSortedElemSet theElemSet; + SMDS_ElemIteratorPtr eIt = theMesh.GetMeshDS()->elementsIterator(SMDSAbs_ElementType(elementType)); + while ( eIt->more() ) + theElemSet.insert( eIt->next() ); + MESSAGE("Add "<name = name; + newEnfMesh->entry = entry; + newEnfMesh->elementType = elementType; + newEnfMesh->size = size; + newEnfMesh->groupName = groupName; + + TGHS3DEnforcedMeshList::iterator it = _enfMeshList.find(newEnfMesh); + if (it == _enfMeshList.end()) { + _entryEnfMeshMap[entry].insert(newEnfMesh); + _enfMeshList.insert(newEnfMesh); + } + } + return added; +} + +//======================================================================= +//function : SetEnforcedGroup +//======================================================================= +bool GHS3DPlugin_Hypothesis::SetEnforcedGroup(const SMESHDS_Mesh* theMeshDS, SMESH::long_array_var theIDs, SMESH::ElementType elementType, std::string name, std::string entry, double size, std::string groupName) +{ + MESSAGE("GHS3DPlugin_Hypothesis::SetEnforcedGroup"); + TIDSortedElemSet theElemSet; + if ( theIDs->length() == 0 ){MESSAGE("The source group is empty");} + for (int i=0; i < theIDs->length(); i++) { + CORBA::Long ind = theIDs[i]; + if (elementType == SMESH::NODE) + { + const SMDS_MeshNode * node = theMeshDS->FindNode(ind); + if (node) + theElemSet.insert( node ); + } + else + { + const SMDS_MeshElement * elem = theMeshDS->FindElement(ind); + if (elem) + theElemSet.insert( elem ); + } + } + +// SMDS_ElemIteratorPtr it = theGroup->GetGroupDS()->GetElements(); +// while ( it->more() ) +// theElemSet.insert( it->next() ); + + MESSAGE("Add "<name = name; + newEnfMesh->entry = entry; + newEnfMesh->elementType = elementType; + newEnfMesh->size = size; + newEnfMesh->groupName = groupName; + + TGHS3DEnforcedMeshList::iterator it = _enfMeshList.find(newEnfMesh); + if (it == _enfMeshList.end()) { + _entryEnfMeshMap[entry].insert(newEnfMesh); + _enfMeshList.insert(newEnfMesh); + } + } + return added; +} + +//======================================================================= +//function : SetEnforcedElements +//======================================================================= +bool GHS3DPlugin_Hypothesis::SetEnforcedElements(TIDSortedElemSet theElemSet, SMESH::ElementType elementType, double size, std::string groupName) +{ + MESSAGE("GHS3DPlugin_Hypothesis::SetEnforcedElements"); + TIDSortedElemSet::const_iterator it = theElemSet.begin(); + const SMDS_MeshElement* elem; + const SMDS_MeshNode* node; + bool added = false; + for (;it != theElemSet.end();++it) + { + elem = (*it); + switch (elementType) { + case SMESH::NODE: + node = dynamic_cast(elem); + if (node) { + _enfNodes.insert(make_pair(node,groupName)); + _nodeIDToSizeMap.insert(make_pair(node->GetID(), size)); + added = true; + } + else { + SMDS_ElemIteratorPtr nodeIt = elem->nodesIterator(); + for (;nodeIt->more();) { + node = dynamic_cast(nodeIt->next()); + _enfNodes.insert(make_pair(node,groupName)); + _nodeIDToSizeMap.insert(make_pair(node->GetID(), size)); + } + added = true; + } + break; + case SMESH::EDGE: + if (elem->GetType() == SMDSAbs_Edge) { + _enfEdges.insert(make_pair(elem,groupName)); + _elementIDToSizeMap.insert(make_pair(elem->GetID(), size)); + added = true; + } + else if (elem->GetType() > SMDSAbs_Edge) { + SMDS_ElemIteratorPtr it = elem->edgesIterator(); + for (;it->more();) { + const SMDS_MeshElement* anEdge = it->next(); + _enfEdges.insert(make_pair(anEdge,groupName)); + _elementIDToSizeMap.insert(make_pair(anEdge->GetID(), size)); + } + added = true; + } + break; + case SMESH::FACE: + if (elem->GetType() == SMDSAbs_Face) + { + if (elem->NbCornerNodes() == 3) { + _enfTriangles.insert(make_pair(elem,groupName)); + _elementIDToSizeMap.insert(make_pair(elem->GetID(), size)); + added = true; + } + } + else if (elem->GetType() > SMDSAbs_Face) { // Group of faces + SMDS_ElemIteratorPtr it = elem->facesIterator(); + for (;it->more();) { + const SMDS_MeshElement* aFace = it->next(); + if (aFace->NbCornerNodes() == 3) { + _enfTriangles.insert(make_pair(aFace,groupName)); + _elementIDToSizeMap.insert(make_pair(aFace->GetID(), size)); + added = true; + } + } + } + break; + default: + break; + }; + } + if (added) + NotifySubMeshesHypothesisModification(); + return added; +} + + +//======================================================================= +//function : GetEnforcedVertex +//======================================================================= + +GHS3DPlugin_Hypothesis::TGHS3DEnforcedVertex* GHS3DPlugin_Hypothesis::GetEnforcedVertex(double x, double y, double z) + throw (std::invalid_argument) +{ + std::vector coord(3); + coord[0] = x; + coord[1] = y; + coord[2] = z; + if (_coordsEnfVertexMap.count(coord)>0) + return _coordsEnfVertexMap[coord]; + std::ostringstream msg ; + msg << "No enforced vertex at " << x << ", " << y << ", " << z; + throw std::invalid_argument(msg.str()); +} + +GHS3DPlugin_Hypothesis::TGHS3DEnforcedVertex* GHS3DPlugin_Hypothesis::GetEnforcedVertex(const std::string theEntry) + throw (std::invalid_argument) +{ + if (_geomEntryEnfVertexMap.count(theEntry)>0) + return _geomEntryEnfVertexMap[theEntry]; + + std::ostringstream msg ; + msg << "No enforced vertex with entry " << theEntry; + throw std::invalid_argument(msg.str()); +} + +//======================================================================= +//function : RemoveEnforcedVertex +//======================================================================= + +bool GHS3DPlugin_Hypothesis::RemoveEnforcedVertex(double x, double y, double z, const std::string theEntry) + throw (std::invalid_argument) +{ + bool toNotify = false; + std::ostringstream msg; + TGHS3DEnforcedVertex *oldEnfVertex; + std::vector coords(3); + coords[0] = x; + coords[1] = y; + coords[2] = z; + + // check that enf vertex with given enf vertex entry exists + TGeomEntryGHS3DEnforcedVertexMap::iterator it_enfVertexEntry = _geomEntryEnfVertexMap.find(theEntry); + if (it_enfVertexEntry != _geomEntryEnfVertexMap.end()) { + // Success + MESSAGE("Found enforced vertex with geom entry " << theEntry); + oldEnfVertex = it_enfVertexEntry->second; + _geomEntryEnfVertexMap.erase(it_enfVertexEntry); + } else { + // Fail + MESSAGE("Enforced vertex with geom entry " << theEntry << " not found"); + // check that enf vertex with given coords exists + TCoordsGHS3DEnforcedVertexMap::iterator it_coords_enf = _coordsEnfVertexMap.find(coords); + if (it_coords_enf != _coordsEnfVertexMap.end()) { + // Success + MESSAGE("Found enforced vertex with coords " << x << ", " << y << ", " << z); + oldEnfVertex = it_coords_enf->second; + _coordsEnfVertexMap.erase(it_coords_enf); + _enfVertexCoordsSizeList.erase(_enfVertexCoordsSizeList.find(coords)); + } else { + // Fail + MESSAGE("Enforced vertex with coords " << x << ", " << y << ", " << z << " not found"); + throw std::invalid_argument(msg.str()); + } + } + + MESSAGE("Remove enf vertex from _enfVertexList"); + + // update _enfVertexList + TGHS3DEnforcedVertexList::iterator it = _enfVertexList.find(oldEnfVertex); + if (it != _enfVertexList.end()) { + if ((*it)->groupName != "") + _groupsToRemove.insert((*it)->groupName); + _enfVertexList.erase(it); + toNotify = true; + MESSAGE("Done"); + } + + if (toNotify) + NotifySubMeshesHypothesisModification(); + + return toNotify; +} + +//======================================================================= +//function : ClearEnforcedVertices +//======================================================================= +void GHS3DPlugin_Hypothesis::ClearEnforcedVertices() +{ + TGHS3DEnforcedVertexList::const_iterator it = _enfVertexList.begin(); + for(;it != _enfVertexList.end();++it) { + if ((*it)->groupName != "") + _groupsToRemove.insert((*it)->groupName); + } + _enfVertexList.clear(); + _coordsEnfVertexMap.clear(); + _geomEntryEnfVertexMap.clear(); + _enfVertexCoordsSizeList.clear(); + _enfVertexEntrySizeList.clear(); + NotifySubMeshesHypothesisModification(); +} + +//======================================================================= +//function : ClearEnforcedMeshes +//======================================================================= +void GHS3DPlugin_Hypothesis::ClearEnforcedMeshes() +{ + TGHS3DEnforcedMeshList::const_iterator it = _enfMeshList.begin(); + for(;it != _enfMeshList.end();++it) { + if ((*it)->groupName != "") + _groupsToRemove.insert((*it)->groupName); + } + _enfNodes.clear(); + _enfEdges.clear(); + _enfTriangles.clear(); + _nodeIDToSizeMap.clear(); + _elementIDToSizeMap.clear(); + _enfMeshList.clear(); + _entryEnfMeshMap.clear(); + NotifySubMeshesHypothesisModification(); +} + + +//======================================================================= +//function : SetGroupsToRemove +//======================================================================= + +void GHS3DPlugin_Hypothesis::ClearGroupsToRemove() +{ + _groupsToRemove.clear(); +} + + +//======================================================================= +//function : DefaultMeshHoles +//======================================================================= + +bool GHS3DPlugin_Hypothesis::DefaultMeshHoles() +{ + return false; // PAL19680 +} + +//======================================================================= +//function : DefaultMaximumMemory +//======================================================================= + +#ifndef WIN32 +#include +#else +#include +#endif + +short GHS3DPlugin_Hypothesis::DefaultMaximumMemory() +{ +#ifndef WIN32 + struct sysinfo si; + int err = sysinfo( &si ); + if ( err == 0 ) { + int ramMB = si.totalram * si.mem_unit / 1024 / 1024; + return (int) ( 0.7 * ramMB ); + } +#else + // See http://msdn.microsoft.com/en-us/library/aa366589.aspx + MEMORYSTATUSEX statex; + statex.dwLength = sizeof (statex); + int err = GlobalMemoryStatusEx (&statex); + if (err != 0) { + int totMB = + statex.ullTotalPhys / 1024 / 1024 + + statex.ullTotalPageFile / 1024 / 1024 + + statex.ullTotalVirtual / 1024 / 1024; + return (int) ( 0.7 * totMB ); + } +#endif + return 1024; +} + +//======================================================================= +//function : DefaultInitialMemory +//======================================================================= + +short GHS3DPlugin_Hypothesis::DefaultInitialMemory() +{ + return DefaultMaximumMemory(); +} + +//======================================================================= +//function : DefaultOptimizationLevel +//======================================================================= + +short GHS3DPlugin_Hypothesis::DefaultOptimizationLevel() +{ + return Medium; +} + +//======================================================================= +//function : DefaultWorkingDirectory +//======================================================================= + +std::string GHS3DPlugin_Hypothesis::DefaultWorkingDirectory() +{ + TCollection_AsciiString aTmpDir; + + char *Tmp_dir = getenv("SALOME_TMP_DIR"); + if(Tmp_dir != NULL) { + aTmpDir = Tmp_dir; + } + else { +#ifdef WIN32 + aTmpDir = TCollection_AsciiString("C:\\"); +#else + aTmpDir = TCollection_AsciiString("/tmp/"); +#endif + } + return aTmpDir.ToCString(); +} + +//======================================================================= +//function : DefaultKeepFiles +//======================================================================= + +bool GHS3DPlugin_Hypothesis::DefaultKeepFiles() +{ + return false; +} + +//======================================================================= +//function : DefaultVerboseLevel +//======================================================================= + +short GHS3DPlugin_Hypothesis::DefaultVerboseLevel() +{ + return 10; +} + +//======================================================================= +//function : DefaultToCreateNewNodes +//======================================================================= + +bool GHS3DPlugin_Hypothesis::DefaultToCreateNewNodes() +{ + return true; +} + +//======================================================================= +//function : DefaultToUseBoundaryRecoveryVersion +//======================================================================= + +bool GHS3DPlugin_Hypothesis::DefaultToUseBoundaryRecoveryVersion() +{ + return false; +} + +//======================================================================= +//function : DefaultToUseFEMCorrection +//======================================================================= + +bool GHS3DPlugin_Hypothesis::DefaultToUseFEMCorrection() +{ + return false; +} + +//======================================================================= +//function : DefaultToRemoveCentralPoint +//======================================================================= + +bool GHS3DPlugin_Hypothesis::DefaultToRemoveCentralPoint() +{ + return false; +} + +// //======================================================================= +// //function : DefaultID2SizeMap +// //======================================================================= +// +// GHS3DPlugin_Hypothesis::TID2SizeMap GHS3DPlugin_Hypothesis::DefaultID2SizeMap() +// { +// return GHS3DPlugin_Hypothesis::TID2SizeMap(); +// } + + +//======================================================================= +//function : SaveTo +//======================================================================= + +std::ostream & GHS3DPlugin_Hypothesis::SaveTo(std::ostream & save) +{ + save << (int) myToMeshHoles << " "; + save << myMaximumMemory << " "; + save << myInitialMemory << " "; + save << myOptimizationLevel << " "; + save << myWorkingDirectory << " "; + save << (int)myKeepFiles << " "; + save << myVerboseLevel << " "; + save << (int)myToCreateNewNodes << " "; + save << (int)myToUseBoundaryRecoveryVersion << " "; + save << (int)myToUseFemCorrection << " "; + save << (int)myToRemoveCentralPoint << " "; + if (!myTextOption.empty()) { + save << "__OPTIONS_BEGIN__ "; + save << myTextOption << " "; + save << "__OPTIONS_END__ "; + } + + + TGHS3DEnforcedVertexList::iterator it = _enfVertexList.begin(); + if (it != _enfVertexList.end()) { + save << "__ENFORCED_VERTICES_BEGIN__ "; + for ( ; it != _enfVertexList.end(); ++it ) { + TGHS3DEnforcedVertex *enfVertex = (*it); + save << " " << "__BEGIN_VERTEX__"; + if (!enfVertex->name.empty()) { + save << " " << "__BEGIN_NAME__"; + save << " " << enfVertex->name; + save << " " << "__END_NAME__"; + } + if (!enfVertex->geomEntry.empty()) { + save << " " << "__BEGIN_ENTRY__"; + save << " " << enfVertex->geomEntry; + save << " " << enfVertex->isCompound; + save << " " << "__END_ENTRY__"; + } + if (!enfVertex->groupName.empty()) { + save << " " << "__BEGIN_GROUP__"; + save << " " << enfVertex->groupName; + save << " " << "__END_GROUP__"; + } + if (enfVertex->coords.size()) { + save << " " << "__BEGIN_COORDS__"; + for (int i=0;icoords.size();i++) + save << " " << enfVertex->coords[i]; + save << " " << "__END_COORDS__"; + } + save << " " << "__BEGIN_SIZE__"; + save << " " << enfVertex->size; + save << " " << "__END_SIZE__"; + save << " " << "__END_VERTEX__"; + } + save << "__ENFORCED_VERTICES_END__ "; + } + + return save; +} + +//======================================================================= +//function : LoadFrom +//======================================================================= + +std::istream & GHS3DPlugin_Hypothesis::LoadFrom(std::istream & load) +{ + bool isOK = true; + int i; + + isOK = (load >> i); + if (isOK) + myToMeshHoles = i; + else + load.clear(ios::badbit | load.rdstate()); + + isOK = (load >> i); + if (isOK) + myMaximumMemory = i; + else + load.clear(ios::badbit | load.rdstate()); + + isOK = (load >> i); + if (isOK) + myInitialMemory = i; + else + load.clear(ios::badbit | load.rdstate()); + + isOK = (load >> i); + if (isOK) + myOptimizationLevel = i; + else + load.clear(ios::badbit | load.rdstate()); + + isOK = (load >> myWorkingDirectory); + if (isOK) { + if ( myWorkingDirectory == "0") { // myWorkingDirectory was empty + myKeepFiles = false; + myWorkingDirectory.clear(); + } + else if ( myWorkingDirectory == "1" ) { + myKeepFiles = true; + myWorkingDirectory.clear(); + } + } + else + load.clear(ios::badbit | load.rdstate()); + + if ( !myWorkingDirectory.empty() ) { + isOK = (load >> i); + if (isOK) + myKeepFiles = i; + else + load.clear(ios::badbit | load.rdstate()); + } + + isOK = (load >> i); + if (isOK) + myVerboseLevel = (short) i; + else + load.clear(ios::badbit | load.rdstate()); + + isOK = (load >> i); + if (isOK) + myToCreateNewNodes = (bool) i; + else + load.clear(ios::badbit | load.rdstate()); + + isOK = (load >> i); + if (isOK) + myToUseBoundaryRecoveryVersion = (bool) i; + else + load.clear(ios::badbit | load.rdstate()); + + isOK = (load >> i); + if (isOK) + myToUseFemCorrection = (bool) i; + else + load.clear(ios::badbit | load.rdstate()); + + isOK = (load >> i); + if (isOK) + myToRemoveCentralPoint = (bool) i; + else + load.clear(ios::badbit | load.rdstate()); + + std::string separator; + bool hasOptions = false; + bool hasEnforcedVertices = false; + isOK = (load >> separator); + + if (isOK) { + if (separator == "__OPTIONS_BEGIN__") + hasOptions = true; + else if (separator == "__ENFORCED_VERTICES_BEGIN__") + hasEnforcedVertices = true; + } + + if (hasOptions) { + std::string txt; + while (isOK) { + isOK = (load >> txt); + if (isOK) { + if (txt == "__OPTIONS_END__") { + if (!myTextOption.empty()) { + // Remove last space + myTextOption.erase(myTextOption.end()-1); + } + isOK = false; + break; + } + myTextOption += txt; + myTextOption += " "; + } + } + } + + if (hasOptions) { + isOK = (load >> separator); + if (isOK && separator == "__ENFORCED_VERTICES_BEGIN__") + hasEnforcedVertices = true; + } + + if (hasEnforcedVertices) { + std::string txt, name, entry, groupName; + double size, coords[3]; + bool isCompound; + bool hasCoords = false; + while (isOK) { + isOK = (load >> txt); // __BEGIN_VERTEX__ + if (isOK) { + if (txt == "__ENFORCED_VERTICES_END__") + isOK = false; + + TGHS3DEnforcedVertex *enfVertex = new TGHS3DEnforcedVertex(); + while (isOK) { + isOK = (load >> txt); + if (txt == "__END_VERTEX__") { + enfVertex->name = name; + enfVertex->geomEntry = entry; + enfVertex->isCompound = isCompound; + enfVertex->groupName = groupName; + enfVertex->coords.clear(); + if (hasCoords) + enfVertex->coords.assign(coords,coords+3); + + _enfVertexList.insert(enfVertex); + + if (enfVertex->coords.size()) + _coordsEnfVertexMap[enfVertex->coords] = enfVertex; + if (!enfVertex->geomEntry.empty()) + _geomEntryEnfVertexMap[enfVertex->geomEntry] = enfVertex; + + name.clear(); + entry.clear(); + groupName.clear(); + hasCoords = false; + isOK = false; + } + + if (txt == "__BEGIN_NAME__") { // __BEGIN_NAME__ + while (isOK && (txt != "__END_NAME__")) { + isOK = (load >> txt); + if (txt != "__END_NAME__") { + if (!name.empty()) + name += " "; + name += txt; + } + } + MESSAGE("name: " <> entry); + isOK = (load >> isCompound); + isOK = (load >> txt); // __END_ENTRY__ + if (txt != "__END_ENTRY__") + throw std::exception(); + MESSAGE("entry: " << entry); + } + + if (txt == "__BEGIN_GROUP__") { // __BEGIN_GROUP__ + while (isOK && (txt != "__END_GROUP__")) { + isOK = (load >> txt); + if (txt != "__END_GROUP__") { + if (!groupName.empty()) + groupName += " "; + groupName += txt; + } + } + MESSAGE("groupName: " << groupName); + } + + if (txt == "__BEGIN_COORDS__") { // __BEGIN_COORDS__ + hasCoords = true; + isOK = (load >> coords[0] >> coords[1] >> coords[2]); + isOK = (load >> txt); // __END_COORDS__ + if (txt != "__END_COORDS__") + throw std::exception(); + MESSAGE("coords: " << coords[0] <<","<< coords[1] <<","<< coords[2]); + } + + if (txt == "__BEGIN_SIZE__") { // __BEGIN_ENTRY__ + isOK = (load >> size); + isOK = (load >> txt); // __END_ENTRY__ + if (txt != "__END_SIZE__") { + throw std::exception(); + } + MESSAGE("size: " << size); + } + } + } + } + } + + return load; +} + +//======================================================================= +//function : SetParametersByMesh +//======================================================================= + +bool GHS3DPlugin_Hypothesis::SetParametersByMesh(const SMESH_Mesh* ,const TopoDS_Shape&) +{ + return false; +} + + +//================================================================================ +/*! + * \brief Return false + */ +//================================================================================ + +bool GHS3DPlugin_Hypothesis::SetParametersByDefaults(const TDefaults& /*dflts*/, + const SMESH_Mesh* /*theMesh*/) +{ + return false; +} + +//================================================================================ +/*! + * \brief Return command to run ghs3d mesher excluding file prefix (-f) + */ +//================================================================================ + +std::string GHS3DPlugin_Hypothesis::CommandToRun(const GHS3DPlugin_Hypothesis* hyp, + const bool hasShapeToMesh) +{ + TCollection_AsciiString cmd; + if (hasShapeToMesh) + cmd = "ghs3d-41"; // to use old mesh2 format + else + cmd = "ghs3d"; // to use new mesh format + // check if any option is overridden by hyp->myTextOption + bool m = hyp ? ( hyp->myTextOption.find("-m") == std::string::npos ) : true; + bool M = hyp ? ( hyp->myTextOption.find("-M") == std::string::npos ) : true; + bool c = hyp ? ( hyp->myTextOption.find("-c") == std::string::npos ) : true; + bool o = hyp ? ( hyp->myTextOption.find("-o") == std::string::npos ) : true; + bool p0 = hyp ? ( hyp->myTextOption.find("-p0") == std::string::npos ) : true; + bool C = hyp ? ( hyp->myTextOption.find("-C") == std::string::npos ) : true; + bool v = hyp ? ( hyp->myTextOption.find("-v") == std::string::npos ) : true; + bool fem = hyp ? ( hyp->myTextOption.find("-FEM")== std::string::npos ) : true; + bool rem = hyp ? ( hyp->myTextOption.find("-no_initial_central_point")== std::string::npos ) : true; + + // if use boundary recovery version, few options are allowed + bool useBndRecovery = !C; + if ( !useBndRecovery && hyp ) + useBndRecovery = hyp->myToUseBoundaryRecoveryVersion; + + // ghs3d needs to know amount of memory it may use (MB). + // Default memory is defined at ghs3d installation but it may be not enough, + // so allow to use about all available memory + if ( m ) { + short aMaximumMemory = hyp ? hyp->myMaximumMemory : -1; + cmd += " -m "; + if ( aMaximumMemory < 0 ) + cmd += DefaultMaximumMemory(); + else + cmd += aMaximumMemory; + } + if ( M && !useBndRecovery ) { + short aInitialMemory = hyp ? hyp->myInitialMemory : -1; + cmd += " -M "; + if ( aInitialMemory > 0 ) + cmd += aInitialMemory; + else + cmd += "100"; + } + // component to mesh + // 0 , all components to be meshed + // 1 , only the main ( outermost ) component to be meshed + if ( c && !useBndRecovery ) { + // We always run GHS3D with "to mesh holes'==TRUE (see PAL19680) + if ( hasShapeToMesh ) + cmd += " -c 0"; + else { + bool aToMeshHoles = hyp ? hyp->myToMeshHoles : DefaultMeshHoles(); + if ( aToMeshHoles ) + cmd += " -c 0"; + else + cmd += " -c 1"; + } + } + + // optimization level + if ( o && hyp && !useBndRecovery ) { + if ( hyp->myOptimizationLevel >= 0 && hyp->myOptimizationLevel < 5 ) { + const char* level[] = { "none" , "light" , "standard" , "standard+" , "strong" }; + cmd += " -o "; + cmd += level[ hyp->myOptimizationLevel ]; + } + } + + // to create internal nodes + if ( p0 && hyp && !hyp->myToCreateNewNodes ) { + cmd += " -p0"; + } + + // verbose mode + if ( v && hyp ) { + cmd += " -v "; + cmd += hyp->myVerboseLevel; + } + + // boundary recovery version + if ( useBndRecovery ) { + cmd += " -C"; + } + + // to use FEM correction + if ( fem && hyp && hyp->myToUseFemCorrection) { + cmd += " -FEM"; + } + + // to remove initial central point. + if ( rem && hyp && hyp->myToRemoveCentralPoint) { + cmd += " -no_initial_central_point"; + } + + // options as text + if ( hyp && !hyp->myTextOption.empty() ) { + cmd += " "; + cmd += (char*) hyp->myTextOption.c_str(); + } + +#ifdef WNT + cmd += " < NUL"; +#endif + + return cmd.ToCString(); +} + +//================================================================================ +/*! + * \brief Return a unique file name + */ +//================================================================================ + +std::string GHS3DPlugin_Hypothesis::GetFileName(const GHS3DPlugin_Hypothesis* hyp) +{ + std::string aTmpDir = hyp ? hyp->GetWorkingDirectory() : DefaultWorkingDirectory(); + const char lastChar = *aTmpDir.rbegin(); +#ifdef WIN32 + if(lastChar != '\\') aTmpDir+='\\'; +#else + if(lastChar != '/') aTmpDir+='/'; +#endif + + TCollection_AsciiString aGenericName = (char*)aTmpDir.c_str(); + aGenericName += "GHS3D_"; + aGenericName += getpid(); + aGenericName += "_"; + aGenericName += Abs((Standard_Integer)(long) aGenericName.ToCString()); + + return aGenericName.ToCString(); +} + + +//================================================================================ +/*! +* \brief Return the enforced vertices +*/ +//================================================================================ + +GHS3DPlugin_Hypothesis::TGHS3DEnforcedVertexList GHS3DPlugin_Hypothesis::GetEnforcedVertices(const GHS3DPlugin_Hypothesis* hyp) +{ + return hyp ? hyp->_GetEnforcedVertices():DefaultGHS3DEnforcedVertexList(); +} + +GHS3DPlugin_Hypothesis::TGHS3DEnforcedVertexCoordsValues GHS3DPlugin_Hypothesis::GetEnforcedVerticesCoordsSize (const GHS3DPlugin_Hypothesis* hyp) +{ + return hyp ? hyp->_GetEnforcedVerticesCoordsSize(): DefaultGHS3DEnforcedVertexCoordsValues(); +} + +GHS3DPlugin_Hypothesis::TGHS3DEnforcedVertexEntryValues GHS3DPlugin_Hypothesis::GetEnforcedVerticesEntrySize (const GHS3DPlugin_Hypothesis* hyp) +{ + return hyp ? hyp->_GetEnforcedVerticesEntrySize(): DefaultGHS3DEnforcedVertexEntryValues(); +} + +GHS3DPlugin_Hypothesis::TCoordsGHS3DEnforcedVertexMap GHS3DPlugin_Hypothesis::GetEnforcedVerticesByCoords (const GHS3DPlugin_Hypothesis* hyp) +{ + return hyp ? hyp->_GetEnforcedVerticesByCoords(): DefaultCoordsGHS3DEnforcedVertexMap(); +} + +GHS3DPlugin_Hypothesis::TGeomEntryGHS3DEnforcedVertexMap GHS3DPlugin_Hypothesis::GetEnforcedVerticesByEntry (const GHS3DPlugin_Hypothesis* hyp) +{ + return hyp ? hyp->_GetEnforcedVerticesByEntry(): DefaultGeomEntryGHS3DEnforcedVertexMap(); +} + +GHS3DPlugin_Hypothesis::TIDSortedNodeGroupMap GHS3DPlugin_Hypothesis::GetEnforcedNodes(const GHS3DPlugin_Hypothesis* hyp) +{ + return hyp ? hyp->_GetEnforcedNodes():DefaultIDSortedNodeGroupMap(); +} + +GHS3DPlugin_Hypothesis::TIDSortedElemGroupMap GHS3DPlugin_Hypothesis::GetEnforcedEdges(const GHS3DPlugin_Hypothesis* hyp) +{ + return hyp ? hyp->_GetEnforcedEdges():DefaultIDSortedElemGroupMap(); +} + +GHS3DPlugin_Hypothesis::TIDSortedElemGroupMap GHS3DPlugin_Hypothesis::GetEnforcedTriangles(const GHS3DPlugin_Hypothesis* hyp) +{ + return hyp ? hyp->_GetEnforcedTriangles():DefaultIDSortedElemGroupMap(); +} + +GHS3DPlugin_Hypothesis::TID2SizeMap GHS3DPlugin_Hypothesis::GetNodeIDToSizeMap(const GHS3DPlugin_Hypothesis* hyp) +{ + return hyp ? hyp->_GetNodeIDToSizeMap(): DefaultID2SizeMap(); +} + +GHS3DPlugin_Hypothesis::TID2SizeMap GHS3DPlugin_Hypothesis::GetElementIDToSizeMap(const GHS3DPlugin_Hypothesis* hyp) +{ + return hyp ? hyp->_GetElementIDToSizeMap(): DefaultID2SizeMap(); +} + +GHS3DPlugin_Hypothesis::TSetStrings GHS3DPlugin_Hypothesis::GetGroupsToRemove(const GHS3DPlugin_Hypothesis* hyp) +{ + return hyp ? hyp->_GetGroupsToRemove(): DefaultGroupsToRemove(); +} diff --git a/src/GHS3DPlugin/GHS3DPlugin_Hypothesis.hxx b/src/GHS3DPlugin/GHS3DPlugin_Hypothesis.hxx new file mode 100644 index 0000000..93723bb --- /dev/null +++ b/src/GHS3DPlugin/GHS3DPlugin_Hypothesis.hxx @@ -0,0 +1,341 @@ +// Copyright (C) 2004-2012 CEA/DEN, EDF R&D +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// 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 +// + +// GHS3DPlugin : C++ implementation +// File : GHS3DPlugin_Hypothesis.hxx +// Created : Wed Apr 2 12:21:17 2008 +// Author : Edward AGAPOV (eap) +// +#ifndef GHS3DPlugin_Hypothesis_HeaderFile +#define GHS3DPlugin_Hypothesis_HeaderFile + +#include "GHS3DPlugin_Defs.hxx" + +#include + +#include "SMESH_Hypothesis.hxx" +#include "SMESH_Mesh_i.hxx" +#include "SMESH_Gen_i.hxx" +#include "SMESH_TypeDefs.hxx" +#include "utilities.h" + +#include +#include +#include +#include + +class GHS3DPLUGIN_EXPORT GHS3DPlugin_Hypothesis: public SMESH_Hypothesis +{ +public: + + GHS3DPlugin_Hypothesis(int hypId, int studyId, SMESH_Gen * gen); + + typedef std::map,double> TGHS3DEnforcedVertexCoordsValues; + typedef std::map TGHS3DEnforcedVertexEntryValues; + + struct TGHS3DEnforcedVertex { + std::string name; + std::string geomEntry; + bool isCompound; + std::vector coords; + std::string groupName; + double size; + }; + + struct CompareGHS3DEnforcedVertex { + bool operator () (const TGHS3DEnforcedVertex* e1, const TGHS3DEnforcedVertex* e2) const { + if (e1 && e2) { + if (e1->coords.size() && e2->coords.size()) + return (e1->coords < e2->coords); + else + return (e1->geomEntry < e2->geomEntry); + } + return false; + } + }; + typedef std::set< TGHS3DEnforcedVertex*, CompareGHS3DEnforcedVertex > TGHS3DEnforcedVertexList; + // Map Coords / Enforced node + typedef std::map< std::vector, TGHS3DEnforcedVertex* > TCoordsGHS3DEnforcedVertexMap; + // Map geom entry / Enforced node + typedef std::map< std::string, TGHS3DEnforcedVertex* > TGeomEntryGHS3DEnforcedVertexMap; + // Map groupName / Enforced node + typedef std::map< std::string, TGHS3DEnforcedVertexList > TGroupNameGHS3DEnforcedVertexMap; + + //////////////////// + // Enforced meshes + //////////////////// + + struct TGHS3DEnforcedMesh { + std::string name; + std::string entry; + SMESH::ElementType elementType; + std::string groupName; + double size; + }; + + struct CompareGHS3DEnforcedMesh { + bool operator () (const TGHS3DEnforcedMesh* e1, const TGHS3DEnforcedMesh* e2) const { + if (e1 && e2) { + if (e1->entry == e2->entry) + return (e1->elementType < e2->elementType); + else + return (e1->entry < e2->entry); + } + else + return false; + } + }; + typedef std::set< TGHS3DEnforcedMesh*, CompareGHS3DEnforcedMesh > TGHS3DEnforcedMeshList; + // Map mesh entry / Enforced mesh list + // ex: 0:1:2:1 -> [ ("Mesh_1", "0:1:2:1", TopAbs_NODE, "", -1), + // ("Mesh_1", "0:1:2:1", TopAbs_EDGE, "edge group", 5)] + typedef std::map< std::string, TGHS3DEnforcedMeshList > TEntryGHS3DEnforcedMeshListMap; + + typedef std::map TID2SizeMap; + + typedef std::map TIDSortedElemGroupMap; + typedef std::map TIDSortedNodeGroupMap; + typedef std::set TSetStrings; + + static const char* GetHypType() { return "GHS3D_Parameters"; } + /*! + * To mesh "holes" in a solid or not. Default is to mesh. + */ + void SetToMeshHoles(bool toMesh); + bool GetToMeshHoles(bool checkFreeOption = false) const; + /*! + * Maximal size of memory to be used by the algorithm (in Megabytes) + */ + void SetMaximumMemory(short MB); + short GetMaximumMemory() const; + /*! + * Initial size of memory to be used by the algorithm (in Megabytes) in + * automatic memory adjustment mode. Default is zero + */ + void SetInitialMemory(short MB); + short GetInitialMemory() const; + /*! + * Optimization level: 0-none, 1-light, 2-medium, 3-standard+, 4-strong. Default is medium + */ + enum OptimizationLevel { None = 0, Light, Medium, StandardPlus, Strong }; + void SetOptimizationLevel(OptimizationLevel level); + OptimizationLevel GetOptimizationLevel() const; + /*! + * Path to working directory + */ + void SetWorkingDirectory(const std::string& path); + std::string GetWorkingDirectory() const; + /*! + * To keep working files or remove them. Log file remains in case of errors anyway. + */ + void SetKeepFiles(bool toKeep); + bool GetKeepFiles() const; + /*! + * Verbose level [0-10] + * 0 - no standard output, + * 2 - prints the data, quality statistics of the skin and final meshes and + * indicates when the final mesh is being saved. In addition the software + * gives indication regarding the CPU time. + * 10 - same as 2 plus the main steps in the computation, quality statistics + * histogram of the skin mesh, quality statistics histogram together with + * the characteristics of the final mesh. + */ + void SetVerboseLevel(short level); + short GetVerboseLevel() const; + /*! + * To create new nodes + */ + void SetToCreateNewNodes(bool toCreate); + bool GetToCreateNewNodes() const; + /*! + * To use boundary recovery version which tries to create mesh on a very poor + * quality surface mesh + */ + void SetToUseBoundaryRecoveryVersion(bool toUse); + bool GetToUseBoundaryRecoveryVersion() const; + /*! + * Applies finite-element correction by replacing overconstrained elements where + * it is possible. The process is cutting first the overconstrained edges and + * second the overconstrained facets. This insure that no edges have two boundary + * vertices and that no facets have three boundary vertices. + */ + void SetFEMCorrection(bool toUseFem); + bool GetFEMCorrection() const; + /*! + * To removes initial central point. + */ + void SetToRemoveCentralPoint(bool toRemove); + bool GetToRemoveCentralPoint() const; + /*! + * To set hiden/undocumented/advanced options + */ + void SetTextOption(const std::string& option); + std::string GetTextOption() const; + + +// struct TEnforcedEdge { +// long ID; +// long node1; +// long node2; +// std::string groupName; +// }; + + + /*! + * \brief Return command to run ghs3d mesher excluding file prefix (-f) + */ + static std::string CommandToRun(const GHS3DPlugin_Hypothesis* hyp, + const bool hasShapeToMesh=true); + /*! + * \brief Return a unique file name + */ + static std::string GetFileName(const GHS3DPlugin_Hypothesis* hyp); + + /*! + * To set an enforced vertex + */ + bool SetEnforcedVertex(std::string aName, std::string anEntry, std::string aGroupName, + double size, double x=0.0, double y=0.0, double z=0.0, bool isCompound = false); + TGHS3DEnforcedVertex* GetEnforcedVertex(double x, double y, double z) throw (std::invalid_argument); + TGHS3DEnforcedVertex* GetEnforcedVertex(const std::string anEntry) throw (std::invalid_argument); + bool RemoveEnforcedVertex(double x=0.0, double y=0.0, double z=0.0, const std::string anEntry="" ) throw (std::invalid_argument); + const TGHS3DEnforcedVertexCoordsValues _GetEnforcedVerticesCoordsSize() const {return _enfVertexCoordsSizeList; } + const TGHS3DEnforcedVertexEntryValues _GetEnforcedVerticesEntrySize() const {return _enfVertexEntrySizeList; } + const TGHS3DEnforcedVertexList _GetEnforcedVertices() const { return _enfVertexList; } + const TCoordsGHS3DEnforcedVertexMap _GetEnforcedVerticesByCoords() const { return _coordsEnfVertexMap; } + const TGeomEntryGHS3DEnforcedVertexMap _GetEnforcedVerticesByEntry() const { return _geomEntryEnfVertexMap; } + void ClearEnforcedVertices(); + + /*! + * To set enforced elements + */ + bool SetEnforcedMesh(SMESH_Mesh& theMesh, SMESH::ElementType elementType, std::string name, std::string entry, double size, std::string groupName = ""); + bool SetEnforcedGroup(const SMESHDS_Mesh* theMeshDS, SMESH::long_array_var theIDs, SMESH::ElementType elementType, std::string name, std::string entry, double size, std::string groupName = ""); + bool SetEnforcedElements(TIDSortedElemSet theElemSet, SMESH::ElementType elementType, double size, std::string groupName = ""); + const TGHS3DEnforcedMeshList _GetEnforcedMeshes() const { return _enfMeshList; } + const TEntryGHS3DEnforcedMeshListMap _GetEnforcedMeshesByEntry() const { return _entryEnfMeshMap; } + void ClearEnforcedMeshes(); + const TIDSortedNodeGroupMap _GetEnforcedNodes() const { return _enfNodes; } + const TIDSortedElemGroupMap _GetEnforcedEdges() const { return _enfEdges; } + const TIDSortedElemGroupMap _GetEnforcedTriangles() const { return _enfTriangles; } + const TID2SizeMap _GetNodeIDToSizeMap() const {return _nodeIDToSizeMap; } + const TID2SizeMap _GetElementIDToSizeMap() const {return _elementIDToSizeMap; } + const TSetStrings _GetGroupsToRemove() const {return _groupsToRemove; } + /*! + * \brief Return the enforced vertices + */ + static TGHS3DEnforcedVertexList GetEnforcedVertices(const GHS3DPlugin_Hypothesis* hyp); + static TGHS3DEnforcedVertexCoordsValues GetEnforcedVerticesCoordsSize(const GHS3DPlugin_Hypothesis* hyp); + static TGHS3DEnforcedVertexEntryValues GetEnforcedVerticesEntrySize(const GHS3DPlugin_Hypothesis* hyp); + static TCoordsGHS3DEnforcedVertexMap GetEnforcedVerticesByCoords(const GHS3DPlugin_Hypothesis* hyp); + static TGeomEntryGHS3DEnforcedVertexMap GetEnforcedVerticesByEntry(const GHS3DPlugin_Hypothesis* hyp); + + static TGHS3DEnforcedMeshList GetEnforcedMeshes(const GHS3DPlugin_Hypothesis* hyp); + static TEntryGHS3DEnforcedMeshListMap GetEnforcedMeshesByEntry(const GHS3DPlugin_Hypothesis* hyp); + static TIDSortedNodeGroupMap GetEnforcedNodes(const GHS3DPlugin_Hypothesis* hyp); + static TIDSortedElemGroupMap GetEnforcedEdges(const GHS3DPlugin_Hypothesis* hyp); + static TIDSortedElemGroupMap GetEnforcedTriangles(const GHS3DPlugin_Hypothesis* hyp); + static TID2SizeMap GetNodeIDToSizeMap(const GHS3DPlugin_Hypothesis* hyp); + static TID2SizeMap GetElementIDToSizeMap(const GHS3DPlugin_Hypothesis* hyp); + static TSetStrings GetGroupsToRemove(const GHS3DPlugin_Hypothesis* hyp); + void ClearGroupsToRemove(); + + static bool DefaultMeshHoles(); + static short DefaultMaximumMemory(); + static short DefaultInitialMemory(); + static short DefaultOptimizationLevel(); + static std::string DefaultWorkingDirectory(); + static bool DefaultKeepFiles(); + static short DefaultVerboseLevel(); + static bool DefaultToCreateNewNodes(); + static bool DefaultToUseBoundaryRecoveryVersion(); + static bool DefaultToUseFEMCorrection(); + static bool DefaultToRemoveCentralPoint(); + + static TGHS3DEnforcedVertex DefaultGHS3DEnforcedVertex() {return TGHS3DEnforcedVertex();} + static TGHS3DEnforcedVertexList DefaultGHS3DEnforcedVertexList() {return TGHS3DEnforcedVertexList();} + static TGHS3DEnforcedVertexCoordsValues DefaultGHS3DEnforcedVertexCoordsValues() {return TGHS3DEnforcedVertexCoordsValues();} + static TGHS3DEnforcedVertexEntryValues DefaultGHS3DEnforcedVertexEntryValues() {return TGHS3DEnforcedVertexEntryValues();} + static TCoordsGHS3DEnforcedVertexMap DefaultCoordsGHS3DEnforcedVertexMap() {return TCoordsGHS3DEnforcedVertexMap();} + static TGeomEntryGHS3DEnforcedVertexMap DefaultGeomEntryGHS3DEnforcedVertexMap() {return TGeomEntryGHS3DEnforcedVertexMap();} + static TGroupNameGHS3DEnforcedVertexMap DefaultGroupNameGHS3DEnforcedVertexMap() {return TGroupNameGHS3DEnforcedVertexMap();} + + static TGHS3DEnforcedMesh DefaultGHS3DEnforcedMesh() {return TGHS3DEnforcedMesh();} + static TGHS3DEnforcedMeshList DefaultGHS3DEnforcedMeshList() {return TGHS3DEnforcedMeshList();} + static TEntryGHS3DEnforcedMeshListMap DefaultEntryGHS3DEnforcedMeshListMap() {return TEntryGHS3DEnforcedMeshListMap();} + static TIDSortedNodeGroupMap DefaultIDSortedNodeGroupMap() {return TIDSortedNodeGroupMap();} + static TIDSortedElemGroupMap DefaultIDSortedElemGroupMap() {return TIDSortedElemGroupMap();} + static TID2SizeMap DefaultID2SizeMap() {return TID2SizeMap();} + static TSetStrings DefaultGroupsToRemove() {return TSetStrings();} + + // Persistence + virtual std::ostream & SaveTo(std::ostream & save); + virtual std::istream & LoadFrom(std::istream & load); + friend GHS3DPLUGIN_EXPORT std::ostream & operator <<(std::ostream & save, GHS3DPlugin_Hypothesis & hyp); + friend GHS3DPLUGIN_EXPORT std::istream & operator >>(std::istream & load, GHS3DPlugin_Hypothesis & hyp); + + /*! + * \brief Does nothing + */ + virtual bool SetParametersByMesh(const SMESH_Mesh* theMesh, const TopoDS_Shape& theShape); + + /*! + * \brief Does nothing + */ + virtual bool SetParametersByDefaults(const TDefaults& dflts, const SMESH_Mesh* theMesh=0); + +private: + + bool myToMeshHoles; + short myMaximumMemory; + short myInitialMemory; + short myOptimizationLevel; + bool myKeepFiles; + std::string myWorkingDirectory; + short myVerboseLevel; + bool myToCreateNewNodes; + bool myToUseBoundaryRecoveryVersion; + bool myToUseFemCorrection; + bool myToRemoveCentralPoint; + std::string myTextOption; + + TGHS3DEnforcedVertexList _enfVertexList; + TGHS3DEnforcedVertexCoordsValues _enfVertexCoordsSizeList; + TGHS3DEnforcedVertexEntryValues _enfVertexEntrySizeList; + // map to get "manual" enf vertex (through the coordinates) + TCoordsGHS3DEnforcedVertexMap _coordsEnfVertexMap; + // map to get "geom" enf vertex (through the geom entries) + TGeomEntryGHS3DEnforcedVertexMap _geomEntryEnfVertexMap; + + + TGHS3DEnforcedMeshList _enfMeshList; + // map to get enf meshes through the entries + TEntryGHS3DEnforcedMeshListMap _entryEnfMeshMap; + TIDSortedNodeGroupMap _enfNodes; + TIDSortedElemGroupMap _enfEdges; + TIDSortedElemGroupMap _enfTriangles; + TID2SizeMap _nodeIDToSizeMap; + TID2SizeMap _elementIDToSizeMap; + std::map _entryToElemsMap; + + TSetStrings _groupsToRemove; +}; + + +#endif diff --git a/src/GHS3DPlugin/GHS3DPlugin_Hypothesis_i.cxx b/src/GHS3DPlugin/GHS3DPlugin_Hypothesis_i.cxx new file mode 100644 index 0000000..5b8466b --- /dev/null +++ b/src/GHS3DPlugin/GHS3DPlugin_Hypothesis_i.cxx @@ -0,0 +1,1163 @@ +// Copyright (C) 2004-2012 CEA/DEN, EDF R&D +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// 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 : GHS3DPlugin_Hypothesis_i.cxx +// Created : Wed Apr 2 13:53:01 2008 +// Author : Edward AGAPOV (eap) +// +#include "GHS3DPlugin_Hypothesis_i.hxx" + +#include "SMESH_Gen.hxx" +#include "SMESH_PythonDump.hxx" +//#include "SMESH_Mesh.hxx" +//#include "SMESH_ProxyMesh.hxx" +//#include + +#include "Utils_CorbaException.hxx" +#include "utilities.h" +#include "SMESH_Mesh_i.hxx" +#include "SMESH_Group_i.hxx" +#include "SMESH_Gen_i.hxx" +#include "SMESH_TypeDefs.hxx" +#include "SMESHDS_GroupBase.hxx" + +// SALOME KERNEL includes +#include "SALOMEDSClient.hxx" +#include +// // IDL headers +// #include +// #include CORBA_SERVER_HEADER(SALOMEDS) + +#ifndef GHS3D_VERSION +#define GHS3D_VERSION 41 +#endif +//======================================================================= +//function : GHS3DPlugin_Hypothesis_i +//======================================================================= + +GHS3DPlugin_Hypothesis_i::GHS3DPlugin_Hypothesis_i (PortableServer::POA_ptr thePOA, + int theStudyId, + ::SMESH_Gen* theGenImpl) + : SALOME::GenericObj_i( thePOA ), + SMESH_Hypothesis_i( thePOA ) +{ + MESSAGE( "GHS3DPlugin_Hypothesis_i::GHS3DPlugin_Hypothesis_i" ); + myBaseImpl = new ::GHS3DPlugin_Hypothesis (theGenImpl->GetANewId(), + theStudyId, + theGenImpl); +} + +//======================================================================= +//function : ~GHS3DPlugin_Hypothesis_i +//======================================================================= + +GHS3DPlugin_Hypothesis_i::~GHS3DPlugin_Hypothesis_i() +{ + MESSAGE( "GHS3DPlugin_Hypothesis_i::~GHS3DPlugin_Hypothesis_i" ); +} + +//======================================================================= +//function : SetToMeshHoles +//======================================================================= + +void GHS3DPlugin_Hypothesis_i::SetToMeshHoles(CORBA::Boolean toMesh) +{ + ASSERT(myBaseImpl); + this->GetImpl()->SetToMeshHoles(toMesh); + SMESH::TPythonDump() << _this() << ".SetToMeshHoles( " << toMesh << " )"; +} + +//======================================================================= +//function : GetToMeshHoles +//======================================================================= + +CORBA::Boolean GHS3DPlugin_Hypothesis_i::GetToMeshHoles() +{ + ASSERT(myBaseImpl); + return this->GetImpl()->GetToMeshHoles(); +} + +//======================================================================= +//function : SetMaximumMemory +//======================================================================= + +void GHS3DPlugin_Hypothesis_i::SetMaximumMemory(CORBA::Short MB) + throw ( SALOME::SALOME_Exception ) +{ + if ( MB == 0 ) + THROW_SALOME_CORBA_EXCEPTION( "Invalid memory size",SALOME::BAD_PARAM ); + ASSERT(myBaseImpl); + this->GetImpl()->SetMaximumMemory(MB); + SMESH::TPythonDump() << _this() << ".SetMaximumMemory( " << MB << " )"; +} + +//======================================================================= +//function : GetMaximumMemory +//======================================================================= + +CORBA::Short GHS3DPlugin_Hypothesis_i::GetMaximumMemory() +{ + ASSERT(myBaseImpl); + return this->GetImpl()->GetMaximumMemory(); +} + +//======================================================================= +//function : SetInitialMemory +//======================================================================= + +void GHS3DPlugin_Hypothesis_i::SetInitialMemory(CORBA::Short MB) + throw ( SALOME::SALOME_Exception ) +{ + if ( MB == 0 ) + THROW_SALOME_CORBA_EXCEPTION( "Invalid memory size",SALOME::BAD_PARAM ); + ASSERT(myBaseImpl); + this->GetImpl()->SetInitialMemory(MB); + SMESH::TPythonDump() << _this() << ".SetInitialMemory( " << MB << " )"; +} + +//======================================================================= +//function : GetInitialMemory +//======================================================================= + +CORBA::Short GHS3DPlugin_Hypothesis_i::GetInitialMemory() +{ + ASSERT(myBaseImpl); + return this->GetImpl()->GetInitialMemory(); +} + +//======================================================================= +//function : SetOptimizationLevel +//======================================================================= + +void GHS3DPlugin_Hypothesis_i::SetOptimizationLevel(CORBA::Short level) + throw ( SALOME::SALOME_Exception ) +{ + ::GHS3DPlugin_Hypothesis::OptimizationLevel l = + (::GHS3DPlugin_Hypothesis::OptimizationLevel) level; + if ( l < ::GHS3DPlugin_Hypothesis::None || + l > ::GHS3DPlugin_Hypothesis::Strong ) + THROW_SALOME_CORBA_EXCEPTION( "Invalid optimization level",SALOME::BAD_PARAM ); + + ASSERT(myBaseImpl); + this->GetImpl()->SetOptimizationLevel(l); + SMESH::TPythonDump() << _this() << ".SetOptimizationLevel( " << level << " )"; +} + +//======================================================================= +//function : GetOptimizationLevel +//======================================================================= + +CORBA::Short GHS3DPlugin_Hypothesis_i::GetOptimizationLevel() +{ + ASSERT(myBaseImpl); + return this->GetImpl()->GetOptimizationLevel(); +} + +//======================================================================= +//function : SetWorkingDirectory +//======================================================================= + +void GHS3DPlugin_Hypothesis_i::SetWorkingDirectory(const char* path) throw ( SALOME::SALOME_Exception ) +{ + if (!path ) + THROW_SALOME_CORBA_EXCEPTION( "Null working directory",SALOME::BAD_PARAM ); + + string file(path); + const char lastChar = *file.rbegin(); +#ifdef WIN32 + if ( lastChar != '\\' ) file += '\\'; +#else + if ( lastChar != '/' ) file += '/'; +#endif + file += "GHS3D.log"; + SMESH_Mesh_i::PrepareForWriting (file.c_str()); + + ASSERT(myBaseImpl); + this->GetImpl()->SetWorkingDirectory(path); + SMESH::TPythonDump() << _this() << ".SetWorkingDirectory( '" << path << "' )"; +} + +//======================================================================= +//function : GetWorkingDirectory +//======================================================================= + +char* GHS3DPlugin_Hypothesis_i::GetWorkingDirectory() +{ + ASSERT(myBaseImpl); + return CORBA::string_dup( this->GetImpl()->GetWorkingDirectory().c_str() ); +} + +//======================================================================= +//function : SetKeepFiles +//======================================================================= + +void GHS3DPlugin_Hypothesis_i::SetKeepFiles(CORBA::Boolean toKeep) +{ + ASSERT(myBaseImpl); + this->GetImpl()->SetKeepFiles(toKeep); + SMESH::TPythonDump() << _this() << ".SetKeepFiles( " << toKeep << " )"; +} + +//======================================================================= +//function : GetKeepFiles +//======================================================================= + +CORBA::Boolean GHS3DPlugin_Hypothesis_i::GetKeepFiles() +{ + ASSERT(myBaseImpl); + return this->GetImpl()->GetKeepFiles(); +} + +//======================================================================= +//function : SetVerboseLevel +//======================================================================= + +void GHS3DPlugin_Hypothesis_i::SetVerboseLevel(CORBA::Short level) + throw ( SALOME::SALOME_Exception ) +{ + if (level < 0 || level > 10 ) + THROW_SALOME_CORBA_EXCEPTION( "Invalid verbose level, valid range is [0-10]", + SALOME::BAD_PARAM ); + ASSERT(myBaseImpl); + this->GetImpl()->SetVerboseLevel(level); + SMESH::TPythonDump() << _this() << ".SetVerboseLevel( " << level << " )"; +} + +//======================================================================= +//function : GetVerboseLevel +//======================================================================= + +CORBA::Short GHS3DPlugin_Hypothesis_i::GetVerboseLevel() +{ + ASSERT(myBaseImpl); + return this->GetImpl()->GetVerboseLevel(); +} + +//======================================================================= +//function : SetToCreateNewNodes +//======================================================================= + +void GHS3DPlugin_Hypothesis_i::SetToCreateNewNodes(CORBA::Boolean toCreate) +{ + ASSERT(myBaseImpl); + this->GetImpl()->SetToCreateNewNodes(toCreate); + SMESH::TPythonDump() << _this() << ".SetToCreateNewNodes( " << toCreate << " )"; +} + +//======================================================================= +//function : GetToCreateNewNodes +//======================================================================= + +CORBA::Boolean GHS3DPlugin_Hypothesis_i::GetToCreateNewNodes() +{ + ASSERT(myBaseImpl); + return this->GetImpl()->GetToCreateNewNodes(); +} + +//======================================================================= +//function : SetToUseBoundaryRecoveryVersion +//======================================================================= + +void GHS3DPlugin_Hypothesis_i::SetToUseBoundaryRecoveryVersion(CORBA::Boolean toUse) +{ + ASSERT(myBaseImpl); + this->GetImpl()->SetToUseBoundaryRecoveryVersion(toUse); + SMESH::TPythonDump() << _this() << ".SetToUseBoundaryRecoveryVersion( " << toUse << " )"; +} + +//======================================================================= +//function : GetToUseBoundaryRecoveryVersion +//======================================================================= + +CORBA::Boolean GHS3DPlugin_Hypothesis_i::GetToUseBoundaryRecoveryVersion() +{ + ASSERT(myBaseImpl); + return this->GetImpl()->GetToUseBoundaryRecoveryVersion(); +} + +//======================================================================= +//function : SetFEMCorrection +//======================================================================= + +void GHS3DPlugin_Hypothesis_i::SetFEMCorrection(CORBA::Boolean toUseFem) +{ + ASSERT(myBaseImpl); + this->GetImpl()->SetFEMCorrection(toUseFem); + SMESH::TPythonDump() << _this() << ".SetFEMCorrection( " << toUseFem << " )"; +} + +//======================================================================= +//function : GetFEMCorrection +//======================================================================= + +CORBA::Boolean GHS3DPlugin_Hypothesis_i::GetFEMCorrection() +{ + ASSERT(myBaseImpl); + return this->GetImpl()->GetFEMCorrection(); +} + +//======================================================================= +//function : SetToRemoveCentralPoint +//======================================================================= + +void GHS3DPlugin_Hypothesis_i::SetToRemoveCentralPoint(CORBA::Boolean toRemove) +{ + ASSERT(myBaseImpl); + this->GetImpl()->SetToRemoveCentralPoint(toRemove); + SMESH::TPythonDump() << _this() << ".SetToRemoveCentralPoint( " << toRemove << " )"; +} + +//======================================================================= +//function : GetToRemoveCentralPoint +//======================================================================= + +CORBA::Boolean GHS3DPlugin_Hypothesis_i::GetToRemoveCentralPoint() +{ + ASSERT(myBaseImpl); + return this->GetImpl()->GetToRemoveCentralPoint(); +} + +//======================================================================= +//function : SetTextOption +//======================================================================= + +void GHS3DPlugin_Hypothesis_i::SetTextOption(const char* option) +{ + ASSERT(myBaseImpl); + this->GetImpl()->SetTextOption(option); + SMESH::TPythonDump() << _this() << ".SetTextOption( '" << option << "' )"; +} + +//======================================================================= +//function : GetTextOption +//======================================================================= + +char* GHS3DPlugin_Hypothesis_i::GetTextOption() +{ + ASSERT(myBaseImpl); + return CORBA::string_dup( this->GetImpl()->GetTextOption().c_str() ); +} + +//======================================================================= +//function : SetEnforcedVertex +//======================================================================= + +bool GHS3DPlugin_Hypothesis_i::SetEnforcedVertex(CORBA::Double x, CORBA::Double y, CORBA::Double z, CORBA::Double size) + throw (SALOME::SALOME_Exception) { + ASSERT(myBaseImpl); + MESSAGE("IDL : SetEnforcedVertex( "<< x << ", " << y << ", " << z << ", " << size << ")"); + return p_SetEnforcedVertex(size, x, y, z); +} + +bool GHS3DPlugin_Hypothesis_i::SetEnforcedVertexNamed(CORBA::Double x, CORBA::Double y, CORBA::Double z, CORBA::Double size, const char* theVertexName) + throw (SALOME::SALOME_Exception) { + ASSERT(myBaseImpl); + MESSAGE("IDL : SetEnforcedVertexNamed( "<< x << ", " << y << ", " << z << ", " << size << ", " << theVertexName << ")"); + return p_SetEnforcedVertex(size, x, y, z, theVertexName, "", ""); +} + +bool GHS3DPlugin_Hypothesis_i::SetEnforcedVertexWithGroup(CORBA::Double x, CORBA::Double y, CORBA::Double z, CORBA::Double size, const char* theGroupName) + throw (SALOME::SALOME_Exception) { + ASSERT(myBaseImpl); + MESSAGE("IDL : SetEnforcedVertexWithGroup( "<< x << ", " << y << ", " << z << ", " << size << ", " << theGroupName << ")"); + return p_SetEnforcedVertex(size, x, y, z, "", "", theGroupName); +} + +bool GHS3DPlugin_Hypothesis_i::SetEnforcedVertexNamedWithGroup(CORBA::Double x, CORBA::Double y, CORBA::Double z, CORBA::Double size, const char* theVertexName, const char* theGroupName) + throw (SALOME::SALOME_Exception) { + ASSERT(myBaseImpl); + MESSAGE("IDL : SetEnforcedVertexNamedWithGroup( "<< x << ", " << y << ", " << z << ", " << size << ", " << theVertexName << ", " << theGroupName << ")"); + return p_SetEnforcedVertex(size, x, y, z, theVertexName, "", theGroupName); +} + +bool GHS3DPlugin_Hypothesis_i::SetEnforcedVertexGeom(GEOM::GEOM_Object_ptr theVertex, CORBA::Double size) + throw (SALOME::SALOME_Exception) { + ASSERT(myBaseImpl); + + if ((theVertex->GetShapeType() != GEOM::VERTEX) && (theVertex->GetShapeType() != GEOM::COMPOUND)) { + MESSAGE("theVertex shape type is not VERTEX or COMPOUND"); + THROW_SALOME_CORBA_EXCEPTION("theVertex shape type is not VERTEX or COMPOUND", SALOME::BAD_PARAM); + } + + string theVertexEntry = theVertex->GetStudyEntry(); + CORBA::Double x = 0, y = 0, z = 0; + CORBA::Boolean isCompound = false; + GEOM::GEOM_Gen_ptr geomGen = SMESH_Gen_i::GetGeomEngine(); + SMESH_Gen_i *smeshGen = SMESH_Gen_i::GetSMESHGen(); + if (theVertexEntry.empty()) { + string aName; + if (theVertex->GetShapeType() == GEOM::VERTEX) { + aName = "Vertex_"; + } + if (theVertex->GetShapeType() == GEOM::COMPOUND) { + aName = "Compound_"; + isCompound = true; + } + aName += theVertex->GetEntry(); + SALOMEDS::SObject_ptr theSVertex = geomGen->PublishInStudy(smeshGen->GetCurrentStudy(), NULL, theVertex, aName.c_str()); + if (!theSVertex->_is_nil()) + theVertexEntry = theSVertex->GetID(); + } + if (theVertexEntry.empty()) + THROW_SALOME_CORBA_EXCEPTION( "Geom object is not published in study" ,SALOME::BAD_PARAM ); + + if (theVertex->GetShapeType() == GEOM::VERTEX) { + GEOM::GEOM_IMeasureOperations_var measureOp = geomGen->GetIMeasureOperations( smeshGen->GetCurrentStudy()->StudyId() ); + if (CORBA::is_nil(measureOp)) + return false; + + measureOp->PointCoordinates (theVertex, x, y, z); + MESSAGE("Point coordinates from measureOp: " << x << ", " << y << ", " << z); + } + + string theVertexName = theVertex->GetName(); + MESSAGE("IDL : SetEnforcedVertexGeom( "<< theVertexEntry << ", " << size<< ")"); + + return p_SetEnforcedVertex(size, x, y, z, theVertexName.c_str(), theVertexEntry.c_str(), "", isCompound); +} + +bool GHS3DPlugin_Hypothesis_i::SetEnforcedVertexGeomWithGroup(GEOM::GEOM_Object_ptr theVertex, CORBA::Double size, const char* theGroupName) + throw (SALOME::SALOME_Exception) { + ASSERT(myBaseImpl); + + if ((theVertex->GetShapeType() != GEOM::VERTEX) && (theVertex->GetShapeType() != GEOM::COMPOUND)) { + MESSAGE("theVertex shape type is not VERTEX or COMPOUND"); + THROW_SALOME_CORBA_EXCEPTION("theVertex shape type is not VERTEX or COMPOUND", SALOME::BAD_PARAM); + } + + string theVertexEntry = theVertex->GetStudyEntry(); + CORBA::Double x = 0, y = 0, z = 0; + CORBA::Boolean isCompound = false; + GEOM::GEOM_Gen_ptr geomGen = SMESH_Gen_i::GetGeomEngine(); + SMESH_Gen_i *smeshGen = SMESH_Gen_i::GetSMESHGen(); + if (theVertexEntry.empty()) { + string aName; + if (theVertex->GetShapeType() == GEOM::VERTEX) { + aName = "Vertex_"; + } + if (theVertex->GetShapeType() == GEOM::COMPOUND) { + aName = "Compound_"; + isCompound = true; + } + aName += theVertex->GetEntry(); + SALOMEDS::SObject_ptr theSVertex = geomGen->PublishInStudy(smeshGen->GetCurrentStudy(), NULL, theVertex, aName.c_str()); + if (!theSVertex->_is_nil()) + theVertexEntry = theSVertex->GetID(); + } + if (theVertexEntry.empty()) + THROW_SALOME_CORBA_EXCEPTION( "Geom object is not published in study" ,SALOME::BAD_PARAM ); + + if (theVertex->GetShapeType() == GEOM::VERTEX) { + GEOM::GEOM_IMeasureOperations_var measureOp = geomGen->GetIMeasureOperations( smeshGen->GetCurrentStudy()->StudyId() ); + if (CORBA::is_nil(measureOp)) + return false; + + measureOp->PointCoordinates (theVertex, x, y, z); + MESSAGE("Point coordinates from measureOp: " << x << ", " << y << ", " << z); + } + + string theVertexName = theVertex->GetName(); + MESSAGE("IDL : SetEnforcedVertexGeomWithGroup( "<< theVertexEntry << ", " << size<< ", " << theGroupName << ")"); + + return p_SetEnforcedVertex(size, x, y, z, theVertexName.c_str(), theVertexEntry.c_str(), theGroupName, isCompound); +} + +bool GHS3DPlugin_Hypothesis_i:: p_SetEnforcedVertex(CORBA::Double size, CORBA::Double x, CORBA::Double y, CORBA::Double z, + const char* theVertexName, const char* theVertexEntry, const char* theGroupName, + CORBA::Boolean isCompound) + throw (SALOME::SALOME_Exception) { + ASSERT(myBaseImpl); + MESSAGE("IDL : p_SetEnforcedVertex(" << size << ", " << x << ", " << y << ", " << z << ", \"" << theVertexName << "\", \"" << theVertexEntry << "\", \"" << theGroupName << "\", " << isCompound<< ")"); + bool newValue = false; + + ::GHS3DPlugin_Hypothesis::TCoordsGHS3DEnforcedVertexMap coordsList; + ::GHS3DPlugin_Hypothesis::TGeomEntryGHS3DEnforcedVertexMap enfVertexEntryList; + if (string(theVertexEntry).empty()) { + coordsList = this->GetImpl()->_GetEnforcedVerticesByCoords(); + std::vector coords; + coords.push_back(x); + coords.push_back(y); + coords.push_back(z); + if (coordsList.find(coords) == coordsList.end()) { + MESSAGE("Coords not found: add it in coordsList"); + newValue = true; + } + else { + MESSAGE("Coords already found, compare names"); + ::GHS3DPlugin_Hypothesis::TGHS3DEnforcedVertex *enfVertex = this->GetImpl()->GetEnforcedVertex(x, y, z); + if ((enfVertex->name != theVertexName) || (enfVertex->groupName != theGroupName) || (enfVertex->size != size)) { + MESSAGE("The names or size are different: update"); +// this->GetImpl()->ClearEnforcedVertex(theFaceEntry, x, y, z); + newValue = true; + } + else { + MESSAGE("The names and size are identical"); + } + } + + if (newValue) { + if (string(theVertexName).empty()) { + if (string(theGroupName).empty()) + SMESH::TPythonDump() << "isDone = " << _this() << ".SetEnforcedVertex(" << x << ", " << y << ", " << z << ", " << size << ")"; + else + SMESH::TPythonDump() << "isDone = " << _this() << ".SetEnforcedVertexWithGroup(" << x << ", " << y << ", " << z << ", " << size << ", \"" << theGroupName << "\")"; + } + else { + if (string(theGroupName).empty()) + SMESH::TPythonDump() << "isDone = " << _this() << ".SetEnforcedVertexNamed(" << x << ", " << y << ", " << z << ", " << size << ", \"" << theVertexName << "\")"; + else + SMESH::TPythonDump() << "isDone = " << _this() << ".SetEnforcedVertexNamedWithGroup(" << x << ", " << y << ", " << z << ", " << size << ", \"" << theVertexName << "\", \"" << theGroupName << "\")"; + } + } + } + else { +// if (isCompound || (!isCompound && !string(theVertexEntry).empty())) { + enfVertexEntryList = this->GetImpl()->_GetEnforcedVerticesByEntry(); +// ::BLSURFPlugin_Hypothesis::TGeomEntryGHS3DEnforcedVertexMap::const_iterator it = enfVertexEntryList.find(theVertexEntry); + if ( enfVertexEntryList.find(theVertexEntry) == enfVertexEntryList.end()) { + MESSAGE("Geom entry not found: add it in enfVertexEntryList"); + newValue = true; + } + else { + MESSAGE("Geom entry already found, compare names"); + ::GHS3DPlugin_Hypothesis::TGHS3DEnforcedVertex *enfVertex = this->GetImpl()->GetEnforcedVertex(theVertexEntry); + if ((enfVertex->name != theVertexName) || (enfVertex->groupName != theGroupName) || (enfVertex->size != size)) { + MESSAGE("The names or size are different: update"); +// this->GetImpl()->ClearEnforcedVertex(theFaceEntry, x, y, z); + newValue = true; + } + else { + MESSAGE("The names and size are identical"); + } + } + + if (newValue) { + if (string(theGroupName).empty()) + SMESH::TPythonDump() << "isDone = " << _this() << ".SetEnforcedVertexGeom(" << theVertexEntry << ", " << size << ")"; + else + SMESH::TPythonDump() << "isDone = " << _this() << ".SetEnforcedVertexGeomWithGroup(" << theVertexEntry << ", " << size << ", \"" << theGroupName << "\")"; + } + } + + if (newValue) + this->GetImpl()->SetEnforcedVertex(theVertexName, theVertexEntry, theGroupName, size, x, y, z, isCompound); + + MESSAGE("IDL : SetEnforcedVertexEntry END"); + return newValue; +} + +//======================================================================= +//function : GetEnforcedVertex +//======================================================================= + +CORBA::Double GHS3DPlugin_Hypothesis_i::GetEnforcedVertex(CORBA::Double x, CORBA::Double y, CORBA::Double z) + throw (SALOME::SALOME_Exception) +{ + ASSERT(myBaseImpl); + try { + bool isDone = this->GetImpl()->GetEnforcedVertex(x,y,z)->size; + SMESH::TPythonDump() << "aSize = " << _this() << ".GetEnforcedVertex(" << x << ", " << y << ", " << z << ")"; + return isDone; + } + catch (const std::invalid_argument& ex) { + SALOME::ExceptionStruct ExDescription; + ExDescription.text = ex.what(); + ExDescription.type = SALOME::BAD_PARAM; + ExDescription.sourceFile = "GHS3DPlugin_Hypothesis_i.cxx"; + ExDescription.lineNumber = 513; + throw SALOME::SALOME_Exception(ExDescription); + } + catch (SALOME_Exception& ex) { + THROW_SALOME_CORBA_EXCEPTION( ex.what() ,SALOME::BAD_PARAM ); + } +} + +//======================================================================= +//function : GetEnforcedVertex +//======================================================================= + +CORBA::Double GHS3DPlugin_Hypothesis_i::GetEnforcedVertexGeom(GEOM::GEOM_Object_ptr theVertex) + throw (SALOME::SALOME_Exception) +{ + ASSERT(myBaseImpl); + + if ((theVertex->GetShapeType() != GEOM::VERTEX) && (theVertex->GetShapeType() != GEOM::COMPOUND)) { + MESSAGE("theVertex shape type is not VERTEX or COMPOUND"); + THROW_SALOME_CORBA_EXCEPTION("theVertex shape type is not VERTEX or COMPOUND", SALOME::BAD_PARAM); + } + + string theVertexEntry = theVertex->GetStudyEntry(); + if (theVertexEntry.empty()) { + GEOM::GEOM_Gen_ptr geomGen = SMESH_Gen_i::GetGeomEngine(); + SMESH_Gen_i *smeshGen = SMESH_Gen_i::GetSMESHGen(); + string aName; + if (theVertex->GetShapeType() == GEOM::VERTEX) + aName = "Vertex_"; + if (theVertex->GetShapeType() == GEOM::COMPOUND) + aName = "Compound_"; + aName += theVertex->GetEntry(); + SALOMEDS::SObject_ptr theSVertex = geomGen->PublishInStudy(smeshGen->GetCurrentStudy(), NULL, theVertex, aName.c_str()); + if (!theSVertex->_is_nil()) + theVertexEntry = theSVertex->GetID(); + } + if (theVertexEntry.empty()) + THROW_SALOME_CORBA_EXCEPTION( "Geom object is not published in study" ,SALOME::BAD_PARAM ); + + string theVertexName = theVertex->GetName(); + + try { + bool isDone = this->GetImpl()->GetEnforcedVertex(theVertexName)->size; + SMESH::TPythonDump() << "aSize = " << _this() << ".GetEnforcedVertexGeom(" << theVertex << ")"; + return isDone; + } + catch (const std::invalid_argument& ex) { + SALOME::ExceptionStruct ExDescription; + ExDescription.text = ex.what(); + ExDescription.type = SALOME::BAD_PARAM; + ExDescription.sourceFile = "GHS3DPlugin_Hypothesis_i.cxx"; + ExDescription.lineNumber = 538; + throw SALOME::SALOME_Exception(ExDescription); + } + catch (SALOME_Exception& ex) { + THROW_SALOME_CORBA_EXCEPTION( ex.what() ,SALOME::BAD_PARAM ); + } +} + +//======================================================================= +//function : GetEnforcedVertices +//======================================================================= + +GHS3DPlugin::GHS3DEnforcedVertexList* GHS3DPlugin_Hypothesis_i::GetEnforcedVertices() +{ + ASSERT(myBaseImpl); + GHS3DPlugin::GHS3DEnforcedVertexList_var result = new GHS3DPlugin::GHS3DEnforcedVertexList(); + + const ::GHS3DPlugin_Hypothesis::TGHS3DEnforcedVertexList enfVertexList = this->GetImpl()->_GetEnforcedVertices(); + result->length( enfVertexList.size() ); + + ::GHS3DPlugin_Hypothesis::TGHS3DEnforcedVertexList::const_iterator it = enfVertexList.begin(); + + for (int i = 0 ; it != enfVertexList.end(); ++it, ++i ) { + ::GHS3DPlugin_Hypothesis::TGHS3DEnforcedVertex* currentVertex = (*it); + GHS3DPlugin::GHS3DEnforcedVertex_var enfVertex = new GHS3DPlugin::GHS3DEnforcedVertex(); + // Name + enfVertex->name = CORBA::string_dup(currentVertex->name.c_str()); + // Geom Vertex Entry + enfVertex->geomEntry = CORBA::string_dup(currentVertex->geomEntry.c_str()); + // Coords + GHS3DPlugin::TCoords_var coords = new GHS3DPlugin::TCoords(); + coords->length(currentVertex->coords.size()); + for (int ind = 0; ind < currentVertex->coords.size(); ind++) + coords[ind] = currentVertex->coords[ind]; + enfVertex->coords = coords; + // Group Name + enfVertex->groupName = CORBA::string_dup(currentVertex->groupName.c_str()); + // Size + enfVertex->size = currentVertex->size; + // isCompound + enfVertex->isCompound = currentVertex->isCompound; + + result[i]=enfVertex; + } + +// SMESH::TPythonDump() << "allEnforcedVertices = " << _this() << ".GetEnforcedVertices()"; + + return result._retn(); +} + +//======================================================================= +//function : RemoveEnforcedVertex +//======================================================================= + +bool GHS3DPlugin_Hypothesis_i::RemoveEnforcedVertex(CORBA::Double x, CORBA::Double y, CORBA::Double z) + throw (SALOME::SALOME_Exception) +{ + ASSERT(myBaseImpl); + try { + bool res = this->GetImpl()->RemoveEnforcedVertex(x,y,z); + SMESH::TPythonDump() << " isDone = " << _this() << ".RemoveEnforcedVertex( " << x << ", " << y << ", " << z << " )"; + return res; + } + catch (const std::invalid_argument& ex) { + SALOME::ExceptionStruct ExDescription; + ExDescription.text = ex.what(); + ExDescription.type = SALOME::BAD_PARAM; + ExDescription.sourceFile = "GHS3DPlugin_Hypothesis_i.cxx"; + ExDescription.lineNumber = 625; + throw SALOME::SALOME_Exception(ExDescription); + } + catch (SALOME_Exception& ex) { + THROW_SALOME_CORBA_EXCEPTION( ex.what() ,SALOME::BAD_PARAM ); + } +} + +bool GHS3DPlugin_Hypothesis_i::RemoveEnforcedVertexGeom(GEOM::GEOM_Object_ptr theVertex) + throw (SALOME::SALOME_Exception) +{ + ASSERT(myBaseImpl); + + if ((theVertex->GetShapeType() != GEOM::VERTEX) && (theVertex->GetShapeType() != GEOM::COMPOUND)) { + MESSAGE("theVertex shape type is not VERTEX or COMPOUND"); + THROW_SALOME_CORBA_EXCEPTION("theVertex shape type is not VERTEX or COMPOUND", SALOME::BAD_PARAM); + } + + string theVertexEntry = theVertex->GetStudyEntry(); + if (theVertexEntry.empty()) { + GEOM::GEOM_Gen_ptr geomGen = SMESH_Gen_i::GetGeomEngine(); + SMESH_Gen_i *smeshGen = SMESH_Gen_i::GetSMESHGen(); + string aName; + if (theVertex->GetShapeType() == GEOM::VERTEX) + aName = "Vertex_"; + if (theVertex->GetShapeType() == GEOM::COMPOUND) + aName = "Compound_"; + aName += theVertex->GetEntry(); + SALOMEDS::SObject_ptr theSVertex = geomGen->PublishInStudy(smeshGen->GetCurrentStudy(), NULL, theVertex, aName.c_str()); + if (!theSVertex->_is_nil()) + theVertexEntry = theSVertex->GetID(); + } + if (theVertexEntry.empty()) + THROW_SALOME_CORBA_EXCEPTION( "Geom object is not published in study" ,SALOME::BAD_PARAM ); + + try { + bool res = this->GetImpl()->RemoveEnforcedVertex(0,0,0, theVertexEntry.c_str()); + SMESH::TPythonDump() << "isDone = " << _this() << ".RemoveEnforcedVertexGeom( " << theVertexEntry.c_str() << " )"; + return res; + } + catch (const std::invalid_argument& ex) { + SALOME::ExceptionStruct ExDescription; + ExDescription.text = ex.what(); + ExDescription.type = SALOME::BAD_PARAM; + ExDescription.sourceFile = "GHS3DPlugin_Hypothesis_i.cxx"; + ExDescription.lineNumber = 648; + throw SALOME::SALOME_Exception(ExDescription); + } + catch (SALOME_Exception& ex) { + THROW_SALOME_CORBA_EXCEPTION( ex.what() ,SALOME::BAD_PARAM ); + } +} + +//======================================================================= +//function : ClearEnforcedVertices +//======================================================================= + +void GHS3DPlugin_Hypothesis_i::ClearEnforcedVertices() +{ + ASSERT(myBaseImpl); + this->GetImpl()->ClearEnforcedVertices(); + SMESH::TPythonDump () << _this() << ".ClearEnforcedVertices() "; +} + +//======================================================================= +//function : ClearEnforcedMeshes +//======================================================================= + +void GHS3DPlugin_Hypothesis_i::ClearEnforcedMeshes() +{ + ASSERT(myBaseImpl); + this->GetImpl()->ClearEnforcedMeshes(); + SMESH::TPythonDump () << _this() << ".ClearEnforcedMeshes() "; +} + +//======================================================================= +//function : GetEnforcedMeshes +//======================================================================= + +GHS3DPlugin::GHS3DEnforcedMeshList* GHS3DPlugin_Hypothesis_i::GetEnforcedMeshes() +{ + ASSERT(myBaseImpl); + GHS3DPlugin::GHS3DEnforcedMeshList_var result = new GHS3DPlugin::GHS3DEnforcedMeshList(); + + const ::GHS3DPlugin_Hypothesis::TGHS3DEnforcedMeshList enfMeshList = this->GetImpl()->_GetEnforcedMeshes(); + result->length( enfMeshList.size() ); + + ::GHS3DPlugin_Hypothesis::TGHS3DEnforcedMeshList::const_iterator it = enfMeshList.begin(); + + for (int i = 0 ; it != enfMeshList.end(); ++it, ++i ) { + ::GHS3DPlugin_Hypothesis::TGHS3DEnforcedMesh* currentMesh = (*it); + GHS3DPlugin::GHS3DEnforcedMesh_var enfMesh = new GHS3DPlugin::GHS3DEnforcedMesh(); + // Name + enfMesh->name = CORBA::string_dup(currentMesh->name.c_str()); + // Mesh Entry + enfMesh->entry = CORBA::string_dup(currentMesh->entry.c_str()); + // isCompound + enfMesh->elementType = currentMesh->elementType; + // Group Name + enfMesh->groupName = CORBA::string_dup(currentMesh->groupName.c_str()); + // Size + enfMesh->size = currentMesh->size; + + result[i]=enfMesh; + } + +// SMESH::TPythonDump() << "allEnforcedVertices = " << _this() << ".GetEnforcedVertices()"; + + return result._retn(); +} + +/*! + * \brief Adds enforced elements of type elementType using another mesh/sub-mesh/mesh group theSource. The elements will be grouped in theGroupName. + */ +bool GHS3DPlugin_Hypothesis_i::SetEnforcedMeshWithGroup(SMESH::SMESH_IDSource_ptr theSource, SMESH::ElementType theType, const char* theGroupName) + throw (SALOME::SALOME_Exception) +{ +#if GHS3D_VERSION >= 42 + return p_SetEnforcedMesh(theSource, theType, -1.0, theGroupName); +// bool res = p_SetEnforcedMesh(theSource, theType, -1.0, theGroupName); +// SMESH_Mesh_i* theMesh_i = SMESH::DownCast( theSource); +// SMESH_Group_i* theGroup_i = SMESH::DownCast( theSource); +// SMESH_GroupOnGeom_i* theGroupOnGeom_i = SMESH::DownCast( theSource); +// if (theGroup_i || theGroupOnGeom_i) +// { +// SMESH::TPythonDump () << "isDone = " << _this() << ".SetEnforcedMeshWithGroup( " +// << theSource << ", " << theType << ", \"" << theGroupName << "\" )"; +// } +// else if (theMesh_i) +// { +// SMESH::TPythonDump () << "isDone = " << _this() << ".SetEnforcedMeshWithGroup( " +// << theSource << ".GetMesh(), " << theType << ", \"" << theGroupName << "\" )"; +// } +// return res; +#else + SALOME::ExceptionStruct ExDescription; + ExDescription.text = "Bad version of GHS3D. It must >= 4.2."; + ExDescription.type = SALOME::BAD_PARAM; + ExDescription.sourceFile = "GHS3DPlugin_Hypothesis_i.cxx"; + ExDescription.lineNumber = 719; + throw SALOME::SALOME_Exception(ExDescription); +#endif +} + +/*! + * \brief Adds enforced elements of type elementType using another mesh/sub-mesh/mesh group theSource. + */ +bool GHS3DPlugin_Hypothesis_i::SetEnforcedMesh(SMESH::SMESH_IDSource_ptr theSource, SMESH::ElementType theType) + throw (SALOME::SALOME_Exception) +{ +// MESSAGE("GHS3DPlugin_Hypothesis_i::SetEnforcedMesh"); +#if GHS3D_VERSION >= 42 + return p_SetEnforcedMesh(theSource, theType); +// bool res = p_SetEnforcedMesh(theSource, theType); +// SMESH_Mesh_i* theMesh_i = SMESH::DownCast( theSource); +// SMESH_Group_i* theGroup_i = SMESH::DownCast( theSource); +// SMESH_GroupOnGeom_i* theGroupOnGeom_i = SMESH::DownCast( theSource); +// if (theGroup_i || theGroupOnGeom_i) +// { +// SMESH::TPythonDump () << "isDone = " << _this() << ".SetEnforcedMesh( " +// << theSource << ", " << theType << " )"; +// } +// else if (theMesh_i) +// { +// SMESH::TPythonDump () << "isDone = " << _this() << ".SetEnforcedMesh( " +// << theSource << ".GetMesh(), " << theType << " )"; +// } +// return res; +#else + SALOME::ExceptionStruct ExDescription; + ExDescription.text = "Bad version of GHS3D. It must >= 4.2."; + ExDescription.type = SALOME::BAD_PARAM; + ExDescription.sourceFile = "GHS3DPlugin_Hypothesis_i.cxx"; + ExDescription.lineNumber = 750; + throw SALOME::SALOME_Exception(ExDescription); +#endif +} + +/*! + * \brief Adds enforced elements of type elementType using another mesh/sub-mesh/mesh group theSource and a size. The elements will be grouped in theGroupName. + */ +bool GHS3DPlugin_Hypothesis_i::SetEnforcedMeshSizeWithGroup(SMESH::SMESH_IDSource_ptr theSource, SMESH::ElementType theType, double theSize, const char* theGroupName) + throw (SALOME::SALOME_Exception) +{ +#if GHS3D_VERSION >= 42 + if (theSize < 0) { + SALOME::ExceptionStruct ExDescription; + ExDescription.text = "Size cannot be negative"; + ExDescription.type = SALOME::BAD_PARAM; + ExDescription.sourceFile = "GHS3DPlugin_Hypothesis_i.cxx"; + ExDescription.lineNumber = 781; + throw SALOME::SALOME_Exception(ExDescription); + } + + return p_SetEnforcedMesh(theSource, theType, theSize, theGroupName); +// bool res = p_SetEnforcedMesh(theSource, theType, theSize, theGroupName); +// SMESH_Mesh_i* theMesh_i = SMESH::DownCast( theSource); +// SMESH_Group_i* theGroup_i = SMESH::DownCast( theSource); +// SMESH_GroupOnGeom_i* theGroupOnGeom_i = SMESH::DownCast( theSource); +// if (theGroup_i || theGroupOnGeom_i) +// { +// SMESH::TPythonDump () << "isDone = " << _this() << ".SetEnforcedMeshSizeWithGroup( " +// << theSource << ", " << theType << ", " << theSize << ", \"" << theGroupName << "\" )"; +// } +// else if (theMesh_i) +// { +// SMESH::TPythonDump () << "isDone = " << _this() << ".SetEnforcedMeshSizeWithGroup( " +// << theSource << ".GetMesh(), " << theType << ", " << theSize << ", \"" << theGroupName << "\" )"; +// } +// return res; +#else + SALOME::ExceptionStruct ExDescription; + ExDescription.text = "Bad version of GHS3D. It must >= 4.2."; + ExDescription.type = SALOME::BAD_PARAM; + ExDescription.sourceFile = "GHS3DPlugin_Hypothesis_i.cxx"; + ExDescription.lineNumber = 750; + throw SALOME::SALOME_Exception(ExDescription); +#endif +} + +/*! + * \brief Adds enforced elements of type elementType using another mesh/sub-mesh/mesh group theSource and a size. + */ +bool GHS3DPlugin_Hypothesis_i::SetEnforcedMeshSize(SMESH::SMESH_IDSource_ptr theSource, SMESH::ElementType theType, double theSize) + throw (SALOME::SALOME_Exception) +{ +#if GHS3D_VERSION >= 42 + if (theSize < 0) { + SALOME::ExceptionStruct ExDescription; + ExDescription.text = "Size cannot be negative"; + ExDescription.type = SALOME::BAD_PARAM; + ExDescription.sourceFile = "GHS3DPlugin_Hypothesis_i.cxx"; + ExDescription.lineNumber = 781; + throw SALOME::SALOME_Exception(ExDescription); + } + return p_SetEnforcedMesh(theSource, theType, theSize); +// bool res = p_SetEnforcedMesh(theSource, theType, theSize); +// SMESH_Mesh_i* theMesh_i = SMESH::DownCast( theSource); +// SMESH_Group_i* theGroup_i = SMESH::DownCast( theSource); +// SMESH_GroupOnGeom_i* theGroupOnGeom_i = SMESH::DownCast( theSource); +// if (theGroup_i || theGroupOnGeom_i) +// { +// SMESH::TPythonDump () << "isDone = " << _this() << ".SetEnforcedMeshSize( " +// << theSource << ", " << theType << ", " << theSize << " )"; +// } +// else if (theMesh_i) +// { +// SMESH::TPythonDump () << "isDone = " << _this() << ".SetEnforcedMeshSize( " +// << theSource << ".GetMesh(), " << theType << ", " << theSize << " )"; +// } +// return res; +#else + SALOME::ExceptionStruct ExDescription; + ExDescription.text = "Bad version of GHS3D. It must >= 4.2."; + ExDescription.type = SALOME::BAD_PARAM; + ExDescription.sourceFile = "GHS3DPlugin_Hypothesis_i.cxx"; + ExDescription.lineNumber = 750; + throw SALOME::SALOME_Exception(ExDescription); +#endif +} + +bool GHS3DPlugin_Hypothesis_i::p_SetEnforcedMesh(SMESH::SMESH_IDSource_ptr theSource, SMESH::ElementType theType, double theSize, const char* theGroupName) + throw (SALOME::SALOME_Exception) +{ + MESSAGE("GHS3DPlugin_Hypothesis_i::p_SetEnforcedMesh"); + ASSERT(myBaseImpl); + + if (CORBA::is_nil( theSource )) + { + SALOME::ExceptionStruct ExDescription; + ExDescription.text = "The source mesh CORBA object is NULL"; + ExDescription.type = SALOME::BAD_PARAM; + ExDescription.sourceFile = "GHS3DPlugin_Hypothesis_i.cxx"; + ExDescription.lineNumber = 840; + throw SALOME::SALOME_Exception(ExDescription); + } + + if ((theType != SMESH::NODE) && (theType != SMESH::EDGE) && (theType != SMESH::FACE)) + { + return false; +// SALOME::ExceptionStruct ExDescription; +// ExDescription.text = "Bad elementType"; +// ExDescription.type = SALOME::BAD_PARAM; +// ExDescription.sourceFile = "GHS3DPlugin_Hypothesis_i.cxx"; +// ExDescription.lineNumber = 840; +// throw SALOME::SALOME_Exception(ExDescription); + } + + SMESH::array_of_ElementType_var types = theSource->GetTypes(); + switch (theType) { + case SMESH::NODE: + MESSAGE("Required type is NODE"); + break; + case SMESH::EDGE: + MESSAGE("Required type is EDGE"); + break; + case SMESH::FACE: + MESSAGE("Required type is FACE"); + break; + default: + break; + } +// MESSAGE("Required type is "<length();i++){MESSAGE(types[i]);} + if ( types->length() >= 1 && types[types->length()-1] < theType) + { + return false; +// SALOME::ExceptionStruct ExDescription; +// ExDescription.text = "The source mesh has bad type"; +// ExDescription.type = SALOME::BAD_PARAM; +// ExDescription.sourceFile = "GHS3DPlugin_Hypothesis_i.cxx"; +// ExDescription.lineNumber = 840; +// throw SALOME::SALOME_Exception(ExDescription); + } + + SMESH_Mesh_i* theMesh_i = SMESH::DownCast( theSource); + SMESH_Group_i* theGroup_i = SMESH::DownCast( theSource); + SMESH_GroupOnGeom_i* theGroupOnGeom_i = SMESH::DownCast( theSource); + TIDSortedElemSet theElemSet; + SMESH_Gen_i *smeshGen = SMESH_Gen_i::GetSMESHGen(); + SALOMEDS::SObject_ptr SObj = smeshGen->ObjectToSObject(smeshGen->GetCurrentStudy(),theSource); + if (theMesh_i) + { + try { + bool res = this->GetImpl()->SetEnforcedMesh(theMesh_i->GetImpl(), theType, SObj->GetName() , SObj->GetID(), theSize, theGroupName); + if (theSize > 0) { + if (theGroupName != "") { + SMESH::TPythonDump () << "isDone = " << _this() << ".SetEnforcedMeshSizeWithGroup( " + << theSource << ".GetMesh(), " << theType << ", " << theSize << ", \"" << theGroupName << "\" )"; + } + else { + SMESH::TPythonDump () << "isDone = " << _this() << ".SetEnforcedMeshSize( " + << theSource << ".GetMesh(), " << theType << ", " << theSize << ", \"" << theGroupName << "\" )"; + } + } + else { + if (theGroupName != "") { + SMESH::TPythonDump () << "isDone = " << _this() << ".SetEnforcedMeshWithGroup( " + << theSource << ".GetMesh(), " << theType << ", \"" << theGroupName << "\" )"; + } + else { + SMESH::TPythonDump () << "isDone = " << _this() << ".SetEnforcedMesh( " + << theSource << ".GetMesh(), " << theType << " )"; + } + } + return res; + } + catch (const std::invalid_argument& ex) { + SALOME::ExceptionStruct ExDescription; + ExDescription.text = ex.what(); + ExDescription.type = SALOME::BAD_PARAM; + ExDescription.sourceFile = "GHS3DPlugin_Hypothesis_i.cxx"; + ExDescription.lineNumber = 840; + throw SALOME::SALOME_Exception(ExDescription); + } + catch (SALOME_Exception& ex) { + THROW_SALOME_CORBA_EXCEPTION( ex.what() ,SALOME::BAD_PARAM ); + } + } + else if (theGroup_i && types->length() == 1 && types[0] == theType) + { + MESSAGE("The source is a group") + try { + bool res = this->GetImpl()->SetEnforcedGroup(theGroup_i->GetGroupDS()->GetMesh(), theGroup_i->GetListOfID(), theType, SObj->GetName() , SObj->GetID(), theSize, theGroupName); + if (theSize > 0) { + if (theGroupName != "") { + SMESH::TPythonDump () << "isDone = " << _this() << ".SetEnforcedMeshSizeWithGroup( " + << theSource << ", " << theType << ", " << theSize << ", \"" << theGroupName << "\" )"; + } + else { + SMESH::TPythonDump () << "isDone = " << _this() << ".SetEnforcedMeshSize( " + << theSource << ", " << theType << ", " << theSize << ", \"" << theGroupName << "\" )"; + } + } + else { + if (theGroupName != "") { + SMESH::TPythonDump () << "isDone = " << _this() << ".SetEnforcedMeshWithGroup( " + << theSource << ", " << theType << ", \"" << theGroupName << "\" )"; + } + else { + SMESH::TPythonDump () << "isDone = " << _this() << ".SetEnforcedMesh( " + << theSource << ", " << theType << " )"; + } + } + return res; + } + catch (const std::invalid_argument& ex) { + SALOME::ExceptionStruct ExDescription; + ExDescription.text = ex.what(); + ExDescription.type = SALOME::BAD_PARAM; + ExDescription.sourceFile = "GHS3DPlugin_Hypothesis_i.cxx"; + ExDescription.lineNumber = 840; + throw SALOME::SALOME_Exception(ExDescription); + } + catch (SALOME_Exception& ex) { + THROW_SALOME_CORBA_EXCEPTION( ex.what() ,SALOME::BAD_PARAM ); + } + } + else if (theGroupOnGeom_i && types->length() == 1 && types[0] == theType) + { + MESSAGE("The source is a group on geom") + try { + bool res = this->GetImpl()->SetEnforcedGroup(theGroupOnGeom_i->GetGroupDS()->GetMesh(),theGroupOnGeom_i->GetListOfID(), theType, SObj->GetName() , SObj->GetID(), theSize, theGroupName); + if (theSize > 0) { + if (theGroupName != "") { + SMESH::TPythonDump () << "isDone = " << _this() << ".SetEnforcedMeshSizeWithGroup( " + << theSource << ", " << theType << ", " << theSize << ", \"" << theGroupName << "\" )"; + } + else { + SMESH::TPythonDump () << "isDone = " << _this() << ".SetEnforcedMeshSize( " + << theSource << ", " << theType << ", " << theSize << ", \"" << theGroupName << "\" )"; + } + } + else { + if (theGroupName != "") { + SMESH::TPythonDump () << "isDone = " << _this() << ".SetEnforcedMeshWithGroup( " + << theSource << ", " << theType << ", \"" << theGroupName << "\" )"; + } + else { + SMESH::TPythonDump () << "isDone = " << _this() << ".SetEnforcedMesh( " + << theSource << ", " << theType << " )"; + } + } + return res; + } + catch (const std::invalid_argument& ex) { + SALOME::ExceptionStruct ExDescription; + ExDescription.text = ex.what(); + ExDescription.type = SALOME::BAD_PARAM; + ExDescription.sourceFile = "GHS3DPlugin_Hypothesis_i.cxx"; + ExDescription.lineNumber = 840; + throw SALOME::SALOME_Exception(ExDescription); + } + catch (SALOME_Exception& ex) { + THROW_SALOME_CORBA_EXCEPTION( ex.what() ,SALOME::BAD_PARAM ); + } + } + return false; +} +//============================================================================= +/*! + * Get implementation + */ +//============================================================================= + +::GHS3DPlugin_Hypothesis* GHS3DPlugin_Hypothesis_i::GetImpl() +{ + return (::GHS3DPlugin_Hypothesis*)myBaseImpl; +} + +//================================================================================ +/*! + * \brief Verify whether hypothesis supports given entity type + */ +//================================================================================ + +CORBA::Boolean GHS3DPlugin_Hypothesis_i::IsDimSupported( SMESH::Dimension type ) +{ + return type == SMESH::DIM_3D; +} + diff --git a/src/GHS3DPlugin/GHS3DPlugin_Hypothesis_i.hxx b/src/GHS3DPlugin/GHS3DPlugin_Hypothesis_i.hxx new file mode 100644 index 0000000..7ca3cac --- /dev/null +++ b/src/GHS3DPlugin/GHS3DPlugin_Hypothesis_i.hxx @@ -0,0 +1,163 @@ +// Copyright (C) 2004-2012 CEA/DEN, EDF R&D +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// 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 +// + +// GHS3DPlugin : C++ implementation +// File : GHS3DPlugin_Hypothesis_i.hxx +// Date : 03/04/2006 +// Project : SALOME +// +#ifndef _GHS3DPlugin_Hypothesis_i_HXX_ +#define _GHS3DPlugin_Hypothesis_i_HXX_ + +#include "GHS3DPlugin_Defs.hxx" + +#include +#include CORBA_SERVER_HEADER(GHS3DPlugin_Algorithm) + +#include "SMESH_Hypothesis_i.hxx" +#include "SMESH_Mesh_i.hxx" +#include "GHS3DPlugin_Hypothesis.hxx" + +class SMESH_Gen; + +// GHS3DPlugin parameters hypothesis + +class GHS3DPLUGIN_EXPORT GHS3DPlugin_Hypothesis_i: + public virtual POA_GHS3DPlugin::GHS3DPlugin_Hypothesis, + public virtual SMESH_Hypothesis_i +{ + public: + // Constructor + GHS3DPlugin_Hypothesis_i (PortableServer::POA_ptr thePOA, + int theStudyId, + ::SMESH_Gen* theGenImpl); + // Destructor + virtual ~GHS3DPlugin_Hypothesis_i(); + + /*! + * To mesh "holes" in a solid or not. Default is to mesh. + */ + void SetToMeshHoles(CORBA::Boolean toMesh); + CORBA::Boolean GetToMeshHoles(); + /*! + * Maximal size of memory to be used by the algorithm (in Megabytes) + */ + void SetMaximumMemory(CORBA::Short MB) throw ( SALOME::SALOME_Exception ); + CORBA::Short GetMaximumMemory(); + /*! + * Initial size of memory to be used by the algorithm (in Megabytes) in + * automatic memory adjustment mode. Default is zero + */ + void SetInitialMemory(CORBA::Short MB) throw ( SALOME::SALOME_Exception ); + CORBA::Short GetInitialMemory(); + /*! + * Optimization level: 0-none, 1-light, 2-medium, 3-strong. Default is medium + */ + void SetOptimizationLevel(CORBA::Short level) throw ( SALOME::SALOME_Exception ); + CORBA::Short GetOptimizationLevel(); + /*! + * Path to working directory + */ + void SetWorkingDirectory(const char* path) throw ( SALOME::SALOME_Exception ); + char* GetWorkingDirectory(); + /*! + * To keep working files or remove them. Log file remains in case of errors anyway. + */ + void SetKeepFiles(CORBA::Boolean toKeep); + CORBA::Boolean GetKeepFiles(); + /*! + * Verbose level [0-10] + * 0 - no standard output, + * 2 - prints the data, quality statistics of the skin and final meshes and + * indicates when the final mesh is being saved. In addition the software + * gives indication regarding the CPU time. + * 10 - same as 2 plus the main steps in the computation, quality statistics + * histogram of the skin mesh, quality statistics histogram together with + * the characteristics of the final mesh. + */ + void SetVerboseLevel(CORBA::Short level) throw ( SALOME::SALOME_Exception ); + CORBA::Short GetVerboseLevel(); + /*! + * To create new nodes + */ + void SetToCreateNewNodes(CORBA::Boolean toCreate); + CORBA::Boolean GetToCreateNewNodes(); + /*! + * To use boundary recovery version which tries to create mesh on a very poor + * quality surface mesh + */ + void SetToUseBoundaryRecoveryVersion(CORBA::Boolean toUse); + CORBA::Boolean GetToUseBoundaryRecoveryVersion(); + /*! + * Applies finite-element correction by replacing overconstrained elements where + * it is possible. The process is cutting first the overconstrained edges and + * second the overconstrained facets. This insure that no edges have two boundary + * vertices and that no facets have three boundary vertices. + */ + void SetFEMCorrection(CORBA::Boolean toUseFem); + CORBA::Boolean GetFEMCorrection(); + /*! + * To removes initial central point. + */ + void SetToRemoveCentralPoint(CORBA::Boolean toRemove); + CORBA::Boolean GetToRemoveCentralPoint(); + /*! + * To set hiden/undocumented/advanced options + */ + void SetTextOption(const char* option); + char* GetTextOption(); + /*! + * To set an enforced vertex + */ + bool p_SetEnforcedVertex(CORBA::Double size, CORBA::Double x = 0, CORBA::Double y = 0, CORBA::Double z = 0, + const char* theVertexName = "", const char* theVertexEntry = "", const char* theGroupName = "", + CORBA::Boolean isCompound = false) + throw (SALOME::SALOME_Exception); + bool SetEnforcedVertex(CORBA::Double x, CORBA::Double y, CORBA::Double z, CORBA::Double size) throw (SALOME::SALOME_Exception); + bool SetEnforcedVertexNamed(CORBA::Double x, CORBA::Double y, CORBA::Double z, CORBA::Double size, const char* theVertexName) throw (SALOME::SALOME_Exception); + bool SetEnforcedVertexWithGroup(CORBA::Double x, CORBA::Double y, CORBA::Double z, CORBA::Double size, const char* theGroupName) throw (SALOME::SALOME_Exception); + bool SetEnforcedVertexNamedWithGroup(CORBA::Double x, CORBA::Double y, CORBA::Double z, CORBA::Double size, const char* theVertexName, const char* theGroupName) throw (SALOME::SALOME_Exception); + bool SetEnforcedVertexGeom(GEOM::GEOM_Object_ptr theVertex, CORBA::Double size) throw (SALOME::SALOME_Exception); + bool SetEnforcedVertexGeomWithGroup(GEOM::GEOM_Object_ptr theVertex, CORBA::Double size, const char* theGroupName) throw (SALOME::SALOME_Exception); + CORBA::Double GetEnforcedVertex(CORBA::Double x, CORBA::Double y, CORBA::Double z) throw (SALOME::SALOME_Exception); + CORBA::Double GetEnforcedVertexGeom(GEOM::GEOM_Object_ptr theVertex) throw (SALOME::SALOME_Exception); + bool RemoveEnforcedVertex(CORBA::Double x, CORBA::Double y, CORBA::Double z) throw (SALOME::SALOME_Exception); + bool RemoveEnforcedVertexGeom(GEOM::GEOM_Object_ptr theVertex) throw (SALOME::SALOME_Exception); + GHS3DPlugin::GHS3DEnforcedVertexList* GetEnforcedVertices(); + void ClearEnforcedVertices(); + /*! + * To set an enforced mesh + */ + bool p_SetEnforcedMesh(SMESH::SMESH_IDSource_ptr theSource, SMESH::ElementType elementType, double size = -1, const char* theGroupName="") throw (SALOME::SALOME_Exception); + bool SetEnforcedMesh(SMESH::SMESH_IDSource_ptr theSource, SMESH::ElementType elementType) throw (SALOME::SALOME_Exception); + bool SetEnforcedMeshWithGroup(SMESH::SMESH_IDSource_ptr theSource, SMESH::ElementType elementType, const char* theGroupName) throw (SALOME::SALOME_Exception); + bool SetEnforcedMeshSize(SMESH::SMESH_IDSource_ptr theSource, SMESH::ElementType elementType, double size) throw (SALOME::SALOME_Exception); + bool SetEnforcedMeshSizeWithGroup(SMESH::SMESH_IDSource_ptr theSource, SMESH::ElementType elementType, double size, const char* theGroupName) throw (SALOME::SALOME_Exception); + GHS3DPlugin::GHS3DEnforcedMeshList* GetEnforcedMeshes(); + void ClearEnforcedMeshes(); + + // Get implementation + ::GHS3DPlugin_Hypothesis* GetImpl(); + + // Verify whether hypothesis supports given entity type + CORBA::Boolean IsDimSupported( SMESH::Dimension type ); + +}; + +#endif diff --git a/src/GHS3DPlugin_i.cxx b/src/GHS3DPlugin/GHS3DPlugin_i.cxx similarity index 56% rename from src/GHS3DPlugin_i.cxx rename to src/GHS3DPlugin/GHS3DPlugin_i.cxx index 20188c2..7539de5 100644 --- a/src/GHS3DPlugin_i.cxx +++ b/src/GHS3DPlugin/GHS3DPlugin_i.cxx @@ -1,28 +1,28 @@ -// Copyright (C) 2004-2008 CEA/DEN, EDF R&D +// Copyright (C) 2004-2012 CEA/DEN, EDF R&D // -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License. +// 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. +// 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 +// 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 +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // + // SMESH GHS3DPlugin : implementaion of SMESH idl descriptions // File : GHS3DPlugin.cxx // Author : Julia DOROVSKIKH // Module : SMESH // $Header$ // -using namespace std; #include "SMESH_Hypothesis_i.hxx" #include "utilities.h" @@ -44,6 +44,9 @@ template class GHS3DPlugin_Creator_i:public HypothesisCreator_i extern "C" { + GHS3DPLUGIN_EXPORT GenericHypothesisCreator_i* GetHypothesisCreator (const char* aHypName); + + GHS3DPLUGIN_EXPORT GenericHypothesisCreator_i* GetHypothesisCreator (const char* aHypName) { MESSAGE("GetHypothesisCreator " << aHypName); diff --git a/src/GHS3DPlugin/Makefile.am b/src/GHS3DPlugin/Makefile.am new file mode 100644 index 0000000..a761826 --- /dev/null +++ b/src/GHS3DPlugin/Makefile.am @@ -0,0 +1,68 @@ +# Copyright (C) 2004-2012 CEA/DEN, EDF R&D +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License. +# +# 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 +# + +# -* Makefile *- +# Author : Edward AGAPOV (OCC) +# Modified by : Alexander BORODIN (OCN) - autotools usage +# Module : GHS3DPLUGIN +# Date : 10/01/2004 +# +include $(top_srcdir)/adm_local/unix/make_common_starter.am + +# header files +salomeinclude_HEADERS = \ + libmesh5.h \ + GHS3DPlugin_Defs.hxx \ + GHS3DPlugin_GHS3D.hxx \ + GHS3DPlugin_GHS3D_i.hxx \ + GHS3DPlugin_Hypothesis.hxx \ + GHS3DPlugin_Hypothesis_i.hxx + +# Libraries targets +lib_LTLIBRARIES = libGHS3DEngine.la + +dist_libGHS3DEngine_la_SOURCES = \ + libmesh5.c \ + GHS3DPlugin_GHS3D.cxx \ + GHS3DPlugin_GHS3D_i.cxx \ + GHS3DPlugin_i.cxx \ + GHS3DPlugin_Hypothesis.cxx \ + GHS3DPlugin_Hypothesis_i.cxx + +libGHS3DEngine_la_CPPFLAGS = \ + $(KERNEL_CXXFLAGS) \ + $(CAS_CPPFLAGS) \ + $(GEOM_CXXFLAGS) \ + $(MED_CXXFLAGS) \ + $(SMESH_CXXFLAGS) \ + $(VTK_INCLUDES) \ + $(BOOST_CPPFLAGS) \ + $(CORBA_CXXFLAGS) \ + $(CORBA_INCLUDES) \ + -I$(top_builddir)/idl + +libGHS3DEngine_la_LDFLAGS = \ + ../../idl/libSalomeIDLGHS3DPLUGIN.la \ + $(CAS_KERNEL) -lTKBRep -lTKG2d -lTKG3d -lTKTopAlgo -lTKGeomBase -lTKGeomAlgo -lTKCDF \ + $(MED_LDFLAGS) -lSalomeIDLMED \ + $(SMESH_LDFLAGS) -lSMESHimpl -lSMESHEngine -lSMESHDS -lSMDS -lStdMeshers \ + $(KERNEL_LDFLAGS) -lSalomeGenericObj -lSALOMELocalTrace -lSALOMEBasics -lSalomeNS -lOpUtil + +# Scripts to be installed. +dist_salomescript_DATA= GHS3DPluginDC.py diff --git a/src/GHS3DPlugin/libmesh5.c b/src/GHS3DPlugin/libmesh5.c new file mode 100644 index 0000000..4277b97 --- /dev/null +++ b/src/GHS3DPlugin/libmesh5.c @@ -0,0 +1,1192 @@ + + +/*----------------------------------------------------------*/ +/* */ +/* LIBMESH V 5.45 */ +/* */ +/*----------------------------------------------------------*/ +/* */ +/* Description: handle .meshb file format I/O */ +/* Author: Loic MARECHAL */ +/* Creation date: feb 16 2007 */ +/* Last modification: feb 08 2011 */ +/* */ +/*----------------------------------------------------------*/ + + +/*----------------------------------------------------------*/ +/* 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; + 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 */ +/*----------------------------------------------------------*/ + +int GmfIniFlg=0; +GmfMshSct *GmfMshTab[ MaxMsh + 1 ]; +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"}, + {"Reserved", "", "", ""}, + {"TetrahedraP2", "TetrahedronP2", "i", "iiiiiiiiiii"}, + {"Reserved", "", "", ""}, + {"Reserved", "", "", ""}, + {"HexahedraQ2", "HexahedronQ2", "i", "iiiiiiiiiiiiiiiiiiiiiiiiiiii"}, + {"Reserved", "", "", ""}, + {"Reserved", "", "", ""}, + {"Reserved", "", "", ""}, + {"Reserved", "", "", ""}, + {"Reserved", "", "", ""}, + {"Reserved", "", "", ""}, + {"Reserved", "", "", ""}, + {"Reserved", "", "", ""}, + {"Reserved", "", "", ""}, + {"Reserved", "", "", ""}, + {"Reserved", "", "", ""}, + {"Reserved", "", "", ""}, + {"Polyhedra", "Polyhedron", "i", "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii"}, + {"Polygons", "Polygon", "", "iiiiiiiii"}, + {"Reserved", "", "", ""}, + {"Pyramids", "Pyramid", "i", "iiiiii"}, + {"BoundingBox", "", "", "drdr"}, + {"Body","i", "drdrdrdr"}, + {"PrivateTable", "PrivateTable", "i", "i"}, + {"Reserved", "", "", ""}, + {"End", "", "", ""}, + {"Reserved", "", "", ""}, + {"Reserved", "", "", ""}, + {"Reserved", "", "", ""}, + {"Reserved", "", "", ""}, + {"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"}, + {"Reserved", "","",""} + }; + + +/*----------------------------------------------------------*/ +/* 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; + + 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) + 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 = (void *)msh->DblBuf; + msh->FltBuf = (void *)msh->DblBuf; + msh->IntBuf = (void *)msh->DblBuf; + + if(strstr(msh->FilNam, ".meshb")) + msh->typ |= (Bin | MshFil); + else if(strstr(msh->FilNam, ".mesh")) + msh->typ |= (Asc | MshFil); + else if(strstr(msh->FilNam, ".solb")) + msh->typ |= (Bin | SolFil); + else if(strstr(msh->FilNam, ".sol")) + msh->typ |= (Asc | SolFil); + else + 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"))) + 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) ) + return(0); + + ScaWrd(msh, (unsigned char *)&msh->ver); + + if( (msh->ver < 1) || (msh->ver > 3) ) + return(0); + + if( (msh->ver == 3) && (sizeof(long) == 4) ) + return(0); + + ScaWrd(msh, (unsigned char *)&KwdCod); + + if(KwdCod != GmfDimension) + 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) + return(0); + + fscanf(msh->hdl, "%d", &msh->ver); + + if( (msh->ver < 1) || (msh->ver > 3) ) + return(0); + + do + { + res = fscanf(msh->hdl, "%s", str); + }while( (res != EOF) && strcmp(str, "Dimension") ); + + if(res == EOF) + return(0); + + fscanf(msh->hdl, "%d", &msh->dim); + } + + if( (msh->dim != 2) && (msh->dim != 3) ) + return(0); + + (*PtrVer) = msh->ver; + (*PtrDim) = msh->dim; + + /*------------*/ + /* KW READING */ + /*------------*/ + + /* Read the list of kw present in the file */ + + if(!ScaKwdTab(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) ) + return(0); + + if( (msh->ver == 3) && (sizeof(long) == 4) ) + return(0); + + if( (msh->dim != 2) && (msh->dim != 3) ) + return(0); + + /* Create the mesh file */ + + if(!(msh->hdl = fopen(msh->FilNam, "wb"))) + 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 + 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]); + } + } + msh->pos = 0; + 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) + { + 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 + fscanf(msh->hdl, "%d", va_arg(VarArg, int *)); + } + else + { + ScaBlk(msh, msh->buf, kwd->SolSiz); + + for(i=0;iSolSiz;i++) + if(kwd->fmt[i] == 'r') + *(va_arg(VarArg, float *)) = msh->FltBuf[i]; + else + *(va_arg(VarArg, int *)) = msh->IntBuf[i]; + } + } + else + { + if(msh->typ & Asc) + { + for(i=0;iSolSiz;i++) + if(kwd->fmt[i] == 'r') + fscanf(msh->hdl, "%lf", va_arg(VarArg, double *)); + 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 + ScaWrd(msh, (unsigned char *)va_arg(VarArg, int *)); + } + } + else + { + if(msh->ver == 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) + { + 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 + fprintf(msh->hdl, "%d ", va_arg(VarArg, int)); + } + else + { + for(i=0;iSolSiz;i++) + if(kwd->fmt[i] == 'r') + msh->FltBuf[i] = va_arg(VarArg, double); + else + msh->IntBuf[i] = va_arg(VarArg, int); + + RecBlk(msh, msh->buf, kwd->SolSiz); + } + } + else + { + if(msh->typ & Asc) + { + for(i=0;iSolSiz;i++) + if(kwd->fmt[i] == 'r') + fprintf(msh->hdl, "%.15lg ", va_arg(VarArg, double)); + else + fprintf(msh->hdl, "%d ", va_arg(VarArg, int)); + } + else + { + pos = 0; + + for(i=0;iSolSiz;i++) + if(kwd->fmt[i] == 'r') + { + DblBuf = (void *)&msh->buf[ pos ]; + *DblBuf = va_arg(VarArg, double); + pos += 8; + } + else + { + IntBuf = (void *)&msh->buf[ pos ]; + *IntBuf = va_arg(VarArg, int); + pos += 4; + } + RecBlk(msh, msh->buf, kwd->NmbWrd); + } + } + } + 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(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, *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; + } +} + + +/*----------------------------------------------------------*/ +/* Read a 4 or 8 bytes position in 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/GHS3DPlugin/libmesh5.h b/src/GHS3DPlugin/libmesh5.h new file mode 100755 index 0000000..cfaf9fb --- /dev/null +++ b/src/GHS3DPlugin/libmesh5.h @@ -0,0 +1,152 @@ + + +/*----------------------------------------------------------*/ +/* */ +/* LIBMESH V 5.45 */ +/* */ +/*----------------------------------------------------------*/ +/* */ +/* Description: handle .meshb file format I/O */ +/* Author: Loic MARECHAL */ +/* Creation date: feb 16 2007 */ +/* Last modification: sep 27 2010 */ +/* */ +/*----------------------------------------------------------*/ + + +/*----------------------------------------------------------*/ +/* Defines */ +/*----------------------------------------------------------*/ + +#define GmfStrSiz 1024 +#define GmfMaxTyp 1000 +#define GmfMaxKwd 79 +#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, \ + GmfReserved6, \ + GmfTetrahedraP2, \ + GmfReserved7, \ + GmfReserved8, \ + GmfHexahedraQ2, \ + GmfReserved9, \ + GmfReserved10, \ + GmfReserved17, \ + GmfReserved18, \ + GmfReserved19, \ + GmfReserved20, \ + GmfReserved21, \ + GmfReserved22, \ + GmfReserved23, \ + GmfReserved24, \ + GmfReserved25, \ + GmfReserved26, \ + GmfPolyhedra, \ + GmfPolygons, \ + GmfReserved29, \ + GmfPyramids, \ + GmfBoundingBox, \ + GmfBody, \ + GmfPrivateTable, \ + GmfReserved33, \ + GmfEnd, \ + GmfReserved34, \ + GmfReserved35, \ + GmfReserved36, \ + GmfReserved37, \ + GmfTangents, \ + GmfNormals, \ + GmfTangentAtVertices, \ + GmfSolAtVertices, \ + GmfSolAtEdges, \ + GmfSolAtTriangles, \ + GmfSolAtQuadrilaterals, \ + GmfSolAtTetrahedra, \ + GmfSolAtPrisms, \ + GmfSolAtHexahedra, \ + GmfDSolAtVertices, \ + GmfISolAtVertices, \ + GmfISolAtEdges, \ + GmfISolAtTriangles, \ + GmfISolAtQuadrilaterals, \ + GmfISolAtTetrahedra, \ + GmfISolAtPrisms, \ + GmfISolAtHexahedra, \ + GmfIterations, \ + GmfTime, \ + GmfReserved38 +}; + + +/*----------------------------------------------------------*/ +/* External procedures */ +/*----------------------------------------------------------*/ + +extern int GmfOpenMesh(const char *, int, ...); +extern int GmfCloseMesh(int); +extern int GmfStatKwd(int, int, ...); +extern int GmfGotoKwd(int, int); +extern int GmfSetKwd(int, int, ...); +extern void GmfGetLin(int, int, ...); +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 + +extern char *GmfKwdFmt[ GmfMaxKwd + 1 ][4]; +extern int GmfCpyLin(int, int, int); + +#endif diff --git a/src/GHS3DPlugin_Defs.hxx b/src/GHS3DPlugin_Defs.hxx deleted file mode 100644 index 5476008..0000000 --- a/src/GHS3DPlugin_Defs.hxx +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (C) 2004-2008 CEA/DEN, EDF R&D -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License. -// -// 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 : GHS3DPlugin_Defs.hxx -// Author : Alexander A. BORODIN -// -#ifndef _GHS3DPlugin_DEFS_HXX_ -#define _GHS3DPlugin_DEFS_HXX_ - -#ifdef WIN32 - #ifdef GHS3DPLUGIN_EXPORTS - #define GHS3DPLUGIN_EXPORT __declspec( dllexport ) - #else - #define GHS3DPLUGIN_EXPORT __declspec( dllimport ) - #endif -#else - #define GHS3DPLUGIN_EXPORT -#endif - -#endif diff --git a/src/GHS3DPlugin_GHS3D.cxx b/src/GHS3DPlugin_GHS3D.cxx deleted file mode 100644 index 195de5c..0000000 --- a/src/GHS3DPlugin_GHS3D.cxx +++ /dev/null @@ -1,1698 +0,0 @@ -// Copyright (C) 2004-2008 CEA/DEN, EDF R&D -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License. -// -// 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 : GHS3DPlugin_GHS3D.cxx -// Created : -// Author : Edward AGAPOV, modified by Lioka RAZAFINDRAZAKA (CEA) 09/02/2007 -// Project : SALOME -// $Header$ -//============================================================================= -// -using namespace std; - -#include "GHS3DPlugin_GHS3D.hxx" -#include "GHS3DPlugin_Hypothesis.hxx" - -#include "SMESH_Gen.hxx" -#include "SMESH_Mesh.hxx" -#include "SMESH_Comment.hxx" -#include "SMESH_MesherHelper.hxx" -#include "SMESH_MeshEditor.hxx" - -#include "SMDS_MeshElement.hxx" -#include "SMDS_MeshNode.hxx" -#include "SMDS_FaceOfNodes.hxx" -#include "SMDS_VolumeOfNodes.hxx" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -//#include -//#include -//#include - -#include "utilities.h" - -#ifndef WIN32 -#include -#endif - -//#include - - -#define castToNode(n) static_cast( n ); - -#ifdef _DEBUG_ -#define DUMP(txt) \ -// cout << txt -#else -#define DUMP(txt) -#endif - -extern "C" -{ -#ifndef WNT -#include -#include -#endif -#include -#include -} - -#define HOLE_ID -1 - -//============================================================================= -/*! - * - */ -//============================================================================= - -GHS3DPlugin_GHS3D::GHS3DPlugin_GHS3D(int hypId, int studyId, SMESH_Gen* gen) - : SMESH_3D_Algo(hypId, studyId, gen) -{ - MESSAGE("GHS3DPlugin_GHS3D::GHS3DPlugin_GHS3D"); - _name = "GHS3D_3D"; - _shapeType = (1 << TopAbs_SHELL) | (1 << TopAbs_SOLID);// 1 bit /shape type - _onlyUnaryInput = false; // Compute() will be called on a compound of solids - _iShape=0; - _nbShape=0; - _compatibleHypothesis.push_back("GHS3D_Parameters"); - _requireShape = false; // can work without shape -} - -//============================================================================= -/*! - * - */ -//============================================================================= - -GHS3DPlugin_GHS3D::~GHS3DPlugin_GHS3D() -{ - MESSAGE("GHS3DPlugin_GHS3D::~GHS3DPlugin_GHS3D"); -} - -//============================================================================= -/*! - * - */ -//============================================================================= - -bool GHS3DPlugin_GHS3D::CheckHypothesis ( SMESH_Mesh& aMesh, - const TopoDS_Shape& aShape, - Hypothesis_Status& aStatus ) -{ - aStatus = SMESH_Hypothesis::HYP_OK; - - // there is only one compatible Hypothesis so far - _hyp = 0; - _keepFiles = false; - const list & hyps = GetUsedHypothesis(aMesh, aShape); - if ( !hyps.empty() ) - _hyp = static_cast ( hyps.front() ); - if ( _hyp ) - _keepFiles = _hyp->GetKeepFiles(); - - return true; -} - -//======================================================================= -//function : findShape -//purpose : -//======================================================================= - -static TopoDS_Shape findShape(const SMDS_MeshNode *aNode[], - TopoDS_Shape aShape, - const TopoDS_Shape shape[], - double** box, - const int nShape, - TopAbs_State * state = 0) -{ - gp_XYZ aPnt(0,0,0); - int j, iShape, nbNode = 4; - - for ( j=0; jX(), aNode[j]->Y(), aNode[j]->Z() ); - aPnt /= nbNode; - - BRepClass3d_SolidClassifier SC (aShape, aPnt, Precision::Confusion()); - if (state) *state = SC.State(); - if ( SC.State() != TopAbs_IN || aShape.IsNull() || aShape.ShapeType() != TopAbs_SOLID) { - for (iShape = 0; iShape < nShape; iShape++) { - aShape = shape[iShape]; - if ( !( aPnt.X() < box[iShape][0] || box[iShape][1] < aPnt.X() || - aPnt.Y() < box[iShape][2] || box[iShape][3] < aPnt.Y() || - aPnt.Z() < box[iShape][4] || box[iShape][5] < aPnt.Z()) ) { - BRepClass3d_SolidClassifier SC (aShape, aPnt, Precision::Confusion()); - if (state) *state = SC.State(); - if (SC.State() == TopAbs_IN) - break; - } - } - } - return aShape; -} - -//======================================================================= -//function : readMapIntLine -//purpose : -//======================================================================= - -static char* readMapIntLine(char* ptr, int tab[]) { - long int intVal; - cout << endl; - - for ( int i=0; i<17; i++ ) { - intVal = strtol(ptr, &ptr, 10); - if ( i < 3 ) - tab[i] = intVal; - } - return ptr; -} - -//======================================================================= -//function : countShape -//purpose : -//======================================================================= - -template < class Mesh, class Shape > -static int countShape( Mesh* mesh, Shape shape ) { - TopExp_Explorer expShape ( mesh->ShapeToMesh(), shape ); - int nbShape = 0; - for ( ; expShape.More(); expShape.Next() ) { - nbShape++; - } - return nbShape; -} - -//======================================================================= -//function : writeFaces -//purpose : -//======================================================================= - -static bool writeFaces (ofstream & theFile, - SMESHDS_Mesh * theMesh, - const map & theSmdsToGhs3dIdMap) -{ - // record structure: - // - // NB_ELEMS DUMMY_INT - // Loop from 1 to NB_ELEMS - // NB_NODES NODE_NB_1 NODE_NB_2 ... (NB_NODES + 1) times: DUMMY_INT - - int nbShape = countShape( theMesh, TopAbs_FACE ); - - int *tabID; tabID = new int[nbShape]; - TopoDS_Shape *tabShape; tabShape = new TopoDS_Shape[nbShape]; - TopoDS_Shape aShape; - SMESHDS_SubMesh* theSubMesh; - const SMDS_MeshElement* aFace; - const char* space = " "; - const int dummyint = 0; - map::const_iterator itOnMap; - SMDS_ElemIteratorPtr itOnSubMesh, itOnSubFace; - int shapeID, nbNodes, aSmdsID; - bool idFound; - - cout << " " << theMesh->NbFaces() << " shapes of 2D dimension" << endl; - cout << endl; - - theFile << space << theMesh->NbFaces() << space << dummyint << endl; - - TopExp_Explorer expface( theMesh->ShapeToMesh(), TopAbs_FACE ); - for ( int i = 0; expface.More(); expface.Next(), i++ ) { - tabID[i] = 0; - aShape = expface.Current(); - shapeID = theMesh->ShapeToIndex( aShape ); - idFound = false; - for ( int j=0; j<=i; j++) { - if ( shapeID == tabID[j] ) { - idFound = true; - break; - } - } - if ( ! idFound ) { - tabID[i] = shapeID; - tabShape[i] = aShape; - } - } - for ( int i =0; i < nbShape; i++ ) { - if ( tabID[i] != 0 ) { - aShape = tabShape[i]; - shapeID = tabID[i]; - theSubMesh = theMesh->MeshElements( aShape ); - if ( !theSubMesh ) continue; - itOnSubMesh = theSubMesh->GetElements(); - while ( itOnSubMesh->more() ) { - aFace = itOnSubMesh->next(); - nbNodes = aFace->NbNodes(); - - theFile << space << nbNodes; - - itOnSubFace = aFace->nodesIterator(); - while ( itOnSubFace->more() ) { - // find GHS3D ID - aSmdsID = itOnSubFace->next()->GetID(); - itOnMap = theSmdsToGhs3dIdMap.find( aSmdsID ); - ASSERT( itOnMap != theSmdsToGhs3dIdMap.end() ); - - theFile << space << (*itOnMap).second; - } - - // (NB_NODES + 1) times: DUMMY_INT - for ( int j=0; j<=nbNodes; j++) - theFile << space << dummyint; - - theFile << endl; - } - } - } - - delete [] tabID; - delete [] tabShape; - - return true; -} - -//======================================================================= -//function : writeFaces -//purpose : Write Faces in case if generate 3D mesh w/o geometry -//======================================================================= - -static bool writeFaces (ofstream & theFile, - SMESHDS_Mesh * theMesh, - vector & theNodeByGhs3dId) -{ - // record structure: - // - // NB_ELEMS DUMMY_INT - // Loop from 1 to NB_ELEMS - // NB_NODES NODE_NB_1 NODE_NB_2 ... (NB_NODES + 1) times: DUMMY_INT - - - int nbFaces = 0; - list< const SMDS_MeshElement* > faces; - list< const SMDS_MeshElement* >::iterator f; - map< const SMDS_MeshNode*,int >::iterator it; - SMDS_ElemIteratorPtr nodeIt; - const SMDS_MeshElement* elem; - int nbNodes; - - const char* space = " "; - const int dummyint = 0; - - //get all faces from mesh - SMDS_FaceIteratorPtr eIt = theMesh->facesIterator(); - while ( eIt->more() ) { - const SMDS_MeshElement* elem = eIt->next(); - if ( !elem ) - return false; - faces.push_back( elem ); - nbFaces++; - } - - if ( nbFaces == 0 ) - return false; - - cout << "The initial 2D mesh contains " << nbFaces << " faces and "; - - // NB_ELEMS DUMMY_INT - theFile << space << nbFaces << space << dummyint << endl; - - // Loop from 1 to NB_ELEMS - - map aNodeToGhs3dIdMap; - f = faces.begin(); - for ( ; f != faces.end(); ++f ) - { - // NB_NODES PER FACE - elem = *f; - nbNodes = elem->NbNodes(); - theFile << space << nbNodes; - - // NODE_NB_1 NODE_NB_2 ... - nodeIt = elem->nodesIterator(); - while ( nodeIt->more() ) - { - // find GHS3D ID - const SMDS_MeshNode* node = castToNode( nodeIt->next() ); - int newId = aNodeToGhs3dIdMap.size() + 1; // ghs3d ids count from 1 - it = aNodeToGhs3dIdMap.insert( make_pair( node, newId )).first; - theFile << space << it->second; - } - - // (NB_NODES + 1) times: DUMMY_INT - for ( int i=0; i<=nbNodes; i++) - theFile << space << dummyint; - - theFile << endl; - } - - // put nodes to theNodeByGhs3dId vector - theNodeByGhs3dId.resize( aNodeToGhs3dIdMap.size() ); - map::const_iterator n2id = aNodeToGhs3dIdMap.begin(); - for ( ; n2id != aNodeToGhs3dIdMap.end(); ++ n2id) - { - theNodeByGhs3dId[ n2id->second - 1 ] = n2id->first; // ghs3d ids count from 1 - } - - return true; -} - -//======================================================================= -//function : writePoints -//purpose : -//======================================================================= - -static bool writePoints (ofstream & theFile, - SMESHDS_Mesh * theMesh, - map & theSmdsToGhs3dIdMap, - map & theGhs3dIdToNodeMap) -{ - // record structure: - // - // NB_NODES - // Loop from 1 to NB_NODES - // X Y Z DUMMY_INT - - int nbNodes = theMesh->NbNodes(); - if ( nbNodes == 0 ) - return false; - - const char* space = " "; - const int dummyint = 0; - - int aGhs3dID = 1; - SMDS_NodeIteratorPtr it = theMesh->nodesIterator(); - const SMDS_MeshNode* node; - - // NB_NODES - theFile << space << nbNodes << endl; - cout << endl; - cout << "The initial 2D mesh contains :" << endl; - cout << " " << nbNodes << " vertices" << endl; - - // Loop from 1 to NB_NODES - - while ( it->more() ) - { - node = it->next(); - theSmdsToGhs3dIdMap.insert( make_pair( node->GetID(), aGhs3dID )); - theGhs3dIdToNodeMap.insert( make_pair( aGhs3dID, node )); - aGhs3dID++; - - // X Y Z DUMMY_INT - theFile - << space << node->X() - << space << node->Y() - << space << node->Z() - << space << dummyint; - - theFile << endl; - } - - return true; -} - -//======================================================================= -//function : writePoints -//purpose : -//======================================================================= - -static bool writePoints (ofstream & theFile, - SMESHDS_Mesh * theMesh, - const vector & theNodeByGhs3dId) -{ - // record structure: - // - // NB_NODES - // Loop from 1 to NB_NODES - // X Y Z DUMMY_INT - - //int nbNodes = theMesh->NbNodes(); - int nbNodes = theNodeByGhs3dId.size(); - if ( nbNodes == 0 ) - return false; - - const char* space = " "; - const int dummyint = 0; - - const SMDS_MeshNode* node; - - // NB_NODES - theFile << space << nbNodes << endl; - cout << nbNodes << " nodes" << endl; - - // Loop from 1 to NB_NODES - - vector::const_iterator nodeIt = theNodeByGhs3dId.begin(); - vector::const_iterator after = theNodeByGhs3dId.end(); - for ( ; nodeIt != after; ++nodeIt ) - { - node = *nodeIt; - - // X Y Z DUMMY_INT - theFile - << space << node->X() - << space << node->Y() - << space << node->Z() - << space << dummyint; - - theFile << endl; - } - - return true; -} - -//======================================================================= -//function : findShapeID -//purpose : find the solid corresponding to GHS3D sub-domain following -// the technique proposed in GHS3D manual in chapter -// "B.4 Subdomain (sub-region) assignment" -//======================================================================= - -static int findShapeID(SMESH_Mesh& mesh, - const SMDS_MeshNode* node1, - const SMDS_MeshNode* node2, - const SMDS_MeshNode* node3, - const bool toMeshHoles) -{ - const int invalidID = 0; - SMESHDS_Mesh* meshDS = mesh.GetMeshDS(); - - // face th enodes belong to - const SMDS_MeshElement * face = meshDS->FindFace(node1,node2,node3); - if ( !face ) - return invalidID; - - // geom face the face assigned to - SMESH_MeshEditor editor(&mesh); - int geomFaceID = editor.FindShape( face ); - if ( !geomFaceID ) - return invalidID; - TopoDS_Shape shape = meshDS->IndexToShape( geomFaceID ); - if ( shape.IsNull() || shape.ShapeType() != TopAbs_FACE ) - return invalidID; - TopoDS_Face geomFace = TopoDS::Face( shape ); - - // solids bounded by geom face - TopTools_IndexedMapOfShape solids, shells; - TopTools_ListIteratorOfListOfShape ansIt = mesh.GetAncestors(geomFace); - for ( ; ansIt.More(); ansIt.Next() ) { - switch ( ansIt.Value().ShapeType() ) { - case TopAbs_SOLID: - solids.Add( ansIt.Value() ); break; - case TopAbs_SHELL: - shells.Add( ansIt.Value() ); break; - default:; - } - } - // analyse found solids - if ( solids.Extent() == 0 || shells.Extent() == 0) - return invalidID; - - const TopoDS_Solid& solid1 = TopoDS::Solid( solids(1) ); - if ( solids.Extent() == 1 ) - { - if ( toMeshHoles ) - return meshDS->ShapeToIndex( solid1 ); - - // - are we at a hole boundary face? - if ( shells(1).IsSame( BRepTools::OuterShell( solid1 )) ) - return meshDS->ShapeToIndex( solid1 ); // - no - } - - // find orientation of geom face within the first solid - TopExp_Explorer fExp( solid1, TopAbs_FACE ); - for ( ; fExp.More(); fExp.Next() ) - if ( geomFace.IsSame( fExp.Current() )) { - geomFace = TopoDS::Face( fExp.Current() ); - break; - } - if ( !fExp.More() ) - return invalidID; // face not found - - // find UV of node1 on geomFace - SMESH_MesherHelper helper( mesh ); - gp_XY uv = helper.GetNodeUV( geomFace, node1 ); - - // check that uv is correct - gp_Pnt node1Pnt ( node1->X(), node1->Y(), node1->Z() ); - double tol = BRep_Tool::Tolerance( geomFace ); - BRepAdaptor_Surface surface( geomFace ); - if ( node1Pnt.Distance( surface.Value( uv.X(), uv.Y() )) > 2 * tol ) { - // project node1 onto geomFace to get right UV - GeomAPI_ProjectPointOnSurf projector( node1Pnt, surface.Surface().Surface() ); - if ( !projector.IsDone() || projector.NbPoints() < 1 ) - return invalidID; - Quantity_Parameter U,V; - projector.LowerDistanceParameters(U,V); - uv = gp_XY( U,V ); - } - // normale to face at node1 - gp_Pnt node2Pnt ( node2->X(), node2->Y(), node2->Z() ); - gp_Pnt node3Pnt ( node3->X(), node3->Y(), node3->Z() ); - gp_Vec vec12( node1Pnt, node2Pnt ); - gp_Vec vec13( node1Pnt, node3Pnt ); - gp_Vec meshNormal = vec12 ^ vec13; - if ( meshNormal.SquareMagnitude() < DBL_MIN ) - return invalidID; - - // normale to geomFace at UV - gp_Vec du, dv; - surface.D1( uv.X(), uv.Y(), node1Pnt, du, dv ); - gp_Vec geomNormal = du ^ dv; - if ( geomNormal.SquareMagnitude() < DBL_MIN ) - return findShapeID( mesh, node2, node3, node1, toMeshHoles ); - if ( geomFace.Orientation() == TopAbs_REVERSED ) - geomNormal.Reverse(); - - // compare normals - bool isReverse = ( meshNormal * geomNormal ) < 0; - if ( !isReverse ) - return meshDS->ShapeToIndex( solid1 ); - - if ( solids.Extent() == 1 ) - return HOLE_ID; // we are inside a hole - else - return meshDS->ShapeToIndex( solids(2) ); -} - -//======================================================================= -//function : readResultFile -//purpose : -//======================================================================= - -static bool readResultFile(const int fileOpen, - SMESH_Mesh& theMesh, - TopoDS_Shape tabShape[], - double** tabBox, - const int nbShape, - map & theGhs3dIdToNodeMap, - bool toMeshHoles) -{ - struct stat status; - size_t length; - - char *ptr, *mapPtr; - char *tetraPtr; - char *shapePtr; - - SMESHDS_Mesh* theMeshDS = theMesh.GetMeshDS(); - - int fileStat; - int nbElems, nbNodes, nbInputNodes; - int nodeId/*, triangleId*/; - int nbTriangle; - int ID, shapeID, ghs3dShapeID; - int IdShapeRef = 1; - int compoundID = - nbShape ? theMeshDS->ShapeToIndex( tabShape[0] ) : theMeshDS->ShapeToIndex( theMeshDS->ShapeToMesh() ); - - int *tab, *tabID, *nodeID, *nodeAssigne; - double *coord; - const SMDS_MeshNode **node; - - tab = new int[3]; - //tabID = new int[nbShape]; - nodeID = new int[4]; - coord = new double[3]; - node = new const SMDS_MeshNode*[4]; - - TopoDS_Shape aSolid; - SMDS_MeshNode * aNewNode; - map ::iterator itOnNode; - SMDS_MeshElement* aTet; -#ifdef _DEBUG_ - set shapeIDs; -#endif - - // Read the file state - fileStat = fstat(fileOpen, &status); - length = status.st_size; - - // Mapping the result file into memory - ptr = (char *) mmap(0,length,PROT_READ,MAP_PRIVATE,fileOpen,0); - mapPtr = ptr; - - ptr = readMapIntLine(ptr, tab); - tetraPtr = ptr; - - nbElems = tab[0]; - nbNodes = tab[1]; - nbInputNodes = tab[2]; - - nodeAssigne = new int[ nbNodes+1 ]; - - if (nbShape > 0) - aSolid = tabShape[0]; - - // Reading the nodeId - for (int i=0; i < 4*nbElems; i++) - nodeId = strtol(ptr, &ptr, 10); - - // Reading the nodeCoor and update the nodeMap - for (int iNode=1; iNode <= nbNodes; iNode++) { - for (int iCoor=0; iCoor < 3; iCoor++) - coord[ iCoor ] = strtod(ptr, &ptr); - nodeAssigne[ iNode ] = 1; - if ( iNode > nbInputNodes ) { - nodeAssigne[ iNode ] = 0; - aNewNode = theMeshDS->AddNode( coord[0],coord[1],coord[2] ); - theGhs3dIdToNodeMap.insert(theGhs3dIdToNodeMap.end(), make_pair( iNode, aNewNode )); - } - } - - // Reading the number of triangles which corresponds to the number of sub-domains - nbTriangle = strtol(ptr, &ptr, 10); - - tabID = new int[nbTriangle]; - for (int i=0; i < nbTriangle; i++) { - tabID[i] = 0; - // find the solid corresponding to GHS3D sub-domain following - // the technique proposed in GHS3D manual in chapter - // "B.4 Subdomain (sub-region) assignment" - int nodeId1 = strtol(ptr, &ptr, 10); - int nodeId2 = strtol(ptr, &ptr, 10); - int nodeId3 = strtol(ptr, &ptr, 10); - if ( nbTriangle > 1 ) { - const SMDS_MeshNode* n1 = theGhs3dIdToNodeMap[ nodeId1 ]; - const SMDS_MeshNode* n2 = theGhs3dIdToNodeMap[ nodeId2 ]; - const SMDS_MeshNode* n3 = theGhs3dIdToNodeMap[ nodeId3 ]; - try { - OCC_CATCH_SIGNALS; - tabID[i] = findShapeID( theMesh, n1, n2, n3, toMeshHoles ); -#ifdef _DEBUG_ - cout << i+1 << " subdomain: findShapeID() returns " << tabID[i] << endl; -#endif - } catch ( Standard_Failure ) { - } catch (...) {} - } - } - - shapePtr = ptr; - - if ( nbTriangle <= nbShape ) // no holes - toMeshHoles = true; // not avoid creating tetras in holes - - // Associating the tetrahedrons to the shapes - shapeID = compoundID; - for (int iElem = 0; iElem < nbElems; iElem++) { - for (int iNode = 0; iNode < 4; iNode++) { - ID = strtol(tetraPtr, &tetraPtr, 10); - itOnNode = theGhs3dIdToNodeMap.find(ID); - node[ iNode ] = itOnNode->second; - nodeID[ iNode ] = ID; - } - // We always run GHS3D with "to mesh holes'==TRUE but we must not create - // tetras within holes depending on hypo option, - // so we first check if aTet is inside a hole and then create it - //aTet = theMeshDS->AddVolume( node[1], node[0], node[2], node[3] ); - if ( nbTriangle > 1 ) { - shapeID = HOLE_ID; // negative shapeID means not to create tetras if !toMeshHoles - ghs3dShapeID = strtol(shapePtr, &shapePtr, 10) - IdShapeRef; - if ( tabID[ ghs3dShapeID ] == 0 ) { - TopAbs_State state; - aSolid = findShape(node, aSolid, tabShape, tabBox, nbShape, &state); - if ( toMeshHoles || state == TopAbs_IN ) - shapeID = theMeshDS->ShapeToIndex( aSolid ); - tabID[ ghs3dShapeID ] = shapeID; - } - else - shapeID = tabID[ ghs3dShapeID ]; - } - else if ( nbShape > 1 ) { - // Case where nbTriangle == 1 while nbShape == 2 encountered - // with compound of 2 boxes and "To mesh holes"==False, - // so there are no subdomains specified for each tetrahedron. - // Try to guess a solid by a node already bound to shape - shapeID = 0; - for ( int i=0; i<4 && shapeID==0; i++ ) { - if ( nodeAssigne[ nodeID[i] ] == 1 && - node[i]->GetPosition()->GetTypeOfPosition() == SMDS_TOP_3DSPACE && - node[i]->GetPosition()->GetShapeId() > 1 ) - { - shapeID = node[i]->GetPosition()->GetShapeId(); - } - } - if ( shapeID==0 ) { - aSolid = findShape(node, aSolid, tabShape, tabBox, nbShape); - shapeID = theMeshDS->ShapeToIndex( aSolid ); - } - } - // set new nodes and tetrahedron onto the shape - for ( int i=0; i<4; i++ ) { - if ( nodeAssigne[ nodeID[i] ] == 0 ) { - if ( shapeID != HOLE_ID ) - theMeshDS->SetNodeInVolume( node[i], shapeID ); - nodeAssigne[ nodeID[i] ] = shapeID; - } - } - if ( toMeshHoles || shapeID != HOLE_ID ) { - aTet = theMeshDS->AddVolume( node[1], node[0], node[2], node[3] ); - theMeshDS->SetMeshElementOnShape( aTet, shapeID ); - } -#ifdef _DEBUG_ - shapeIDs.insert( shapeID ); -#endif - } - // Remove nodes of tetras inside holes if !toMeshHoles - if ( !toMeshHoles ) { - itOnNode = theGhs3dIdToNodeMap.find( nbInputNodes ); - for ( ; itOnNode != theGhs3dIdToNodeMap.end(); ++itOnNode) { - ID = itOnNode->first; - if ( nodeAssigne[ ID ] == HOLE_ID ) - theMeshDS->RemoveFreeNode( itOnNode->second, 0 ); - } - } - - if ( nbElems ) - cout << nbElems << " tetrahedrons have been associated to " << nbShape << " shapes" << endl; - munmap(mapPtr, length); - close(fileOpen); - - delete [] tab; - delete [] tabID; - delete [] nodeID; - delete [] coord; - delete [] node; - delete [] nodeAssigne; - -#ifdef _DEBUG_ - if ( shapeIDs.size() != nbShape ) { - cout << "Only " << shapeIDs.size() << " solids of " << nbShape << " found" << endl; - for (int i=0; iShapeToIndex( tabShape[i] ); - if ( shapeIDs.find( shapeID ) == shapeIDs.end() ) - cout << " Solid #" << shapeID << " not found" << endl; - } - } -#endif - - return true; -} - -//======================================================================= -//function : readResultFile -//purpose : -//======================================================================= - -static bool readResultFile(const int fileOpen, - SMESHDS_Mesh* theMeshDS, - TopoDS_Shape aSolid, - vector & theNodeByGhs3dId) { - - struct stat status; - size_t length; - - char *ptr, *mapPtr; - char *tetraPtr; - char *shapePtr; - - int fileStat; - int nbElems, nbNodes, nbInputNodes; - int nodeId, triangleId; - int nbTriangle; - int ID, shapeID; - - int *tab; - double *coord; - const SMDS_MeshNode **node; - - tab = new int[3]; - coord = new double[3]; - node = new const SMDS_MeshNode*[4]; - - SMDS_MeshNode * aNewNode; - map ::iterator IdNode; - SMDS_MeshElement* aTet; - - // Read the file state - fileStat = fstat(fileOpen, &status); - length = status.st_size; - - // Mapping the result file into memory - ptr = (char *) mmap(0,length,PROT_READ,MAP_PRIVATE,fileOpen,0); - mapPtr = ptr; - - ptr = readMapIntLine(ptr, tab); - tetraPtr = ptr; - - nbElems = tab[0]; - nbNodes = tab[1]; - nbInputNodes = tab[2]; - - theNodeByGhs3dId.resize( nbNodes ); - - // Reading the nodeId - for (int i=0; i < 4*nbElems; i++) - nodeId = strtol(ptr, &ptr, 10); - - // Reading the nodeCoor and update the nodeMap - shapeID = theMeshDS->ShapeToIndex( aSolid ); - for (int iNode=0; iNode < nbNodes; iNode++) { - for (int iCoor=0; iCoor < 3; iCoor++) - coord[ iCoor ] = strtod(ptr, &ptr); - if ((iNode+1) > nbInputNodes) { - aNewNode = theMeshDS->AddNode( coord[0],coord[1],coord[2] ); - theMeshDS->SetNodeInVolume( aNewNode, shapeID ); - theNodeByGhs3dId[ iNode ] = aNewNode; - } - } - - // Reading the triangles - nbTriangle = strtol(ptr, &ptr, 10); - - for (int i=0; i < 3*nbTriangle; i++) - triangleId = strtol(ptr, &ptr, 10); - - shapePtr = ptr; - - // Associating the tetrahedrons to the shapes - for (int iElem = 0; iElem < nbElems; iElem++) { - for (int iNode = 0; iNode < 4; iNode++) { - ID = strtol(tetraPtr, &tetraPtr, 10); - node[ iNode ] = theNodeByGhs3dId[ ID-1 ]; - } - aTet = theMeshDS->AddVolume( node[1], node[0], node[2], node[3] ); - shapeID = theMeshDS->ShapeToIndex( aSolid ); - theMeshDS->SetMeshElementOnShape( aTet, shapeID ); - } - if ( nbElems ) - cout << nbElems << " tetrahedrons have been associated to " << nbTriangle << " shapes" << endl; - munmap(mapPtr, length); - close(fileOpen); - - delete [] tab; - delete [] coord; - delete [] node; - - return true; -} - -//============================================================================= -/*! - *Here we are going to use the GHS3D mesher - */ -//============================================================================= - -bool GHS3DPlugin_GHS3D::Compute(SMESH_Mesh& theMesh, - const TopoDS_Shape& theShape) -{ - bool Ok(false); - SMESHDS_Mesh* meshDS = theMesh.GetMeshDS(); - - _nbShape = countShape( meshDS, TopAbs_SOLID ); // we count the number of shapes - - // create bounding box for every shape inside the compound - - int iShape = 0; - TopoDS_Shape* tabShape; - double** tabBox; - tabShape = new TopoDS_Shape[_nbShape]; - tabBox = new double*[_nbShape]; - for (int i=0; i<_nbShape; i++) - tabBox[i] = new double[6]; - Standard_Real Xmin, Ymin, Zmin, Xmax, Ymax, Zmax; - - TopExp_Explorer expBox (meshDS->ShapeToMesh(), TopAbs_SOLID); - for (; expBox.More(); expBox.Next()) { - tabShape[iShape] = expBox.Current(); - Bnd_Box BoundingBox; - BRepBndLib::Add(expBox.Current(), BoundingBox); - BoundingBox.Get(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax); - tabBox[iShape][0] = Xmin; tabBox[iShape][1] = Xmax; - tabBox[iShape][2] = Ymin; tabBox[iShape][3] = Ymax; - tabBox[iShape][4] = Zmin; tabBox[iShape][5] = Zmax; - iShape++; - } - - // a unique working file name - // to avoid access to the same files by eg different users - TCollection_AsciiString aGenericName - = (char*) GHS3DPlugin_Hypothesis::GetFileName(_hyp).c_str(); - - TCollection_AsciiString aFacesFileName, aPointsFileName, aResultFileName; - TCollection_AsciiString aBadResFileName, aBbResFileName, aLogFileName; - aFacesFileName = aGenericName + ".faces"; // in faces - aPointsFileName = aGenericName + ".points"; // in points - aResultFileName = aGenericName + ".noboite";// out points and volumes - aBadResFileName = aGenericName + ".boite"; // out bad result - aBbResFileName = aGenericName + ".bb"; // out vertex stepsize - aLogFileName = aGenericName + ".log"; // log - - // ----------------- - // make input files - // ----------------- - - ofstream aFacesFile ( aFacesFileName.ToCString() , ios::out); - ofstream aPointsFile ( aPointsFileName.ToCString() , ios::out); - - Ok = -#ifdef WIN32 - aFacesFile->is_open() && aPointsFile->is_open(); -#else - aFacesFile.rdbuf()->is_open() && aPointsFile.rdbuf()->is_open(); -#endif - if (!Ok) { - INFOS( "Can't write into " << aFacesFileName); - return error(SMESH_Comment("Can't write into ") << aFacesFileName); - } - map aSmdsToGhs3dIdMap; - map aGhs3dIdToNodeMap; - - Ok = writePoints( aPointsFile, meshDS, aSmdsToGhs3dIdMap, aGhs3dIdToNodeMap ) && - writeFaces ( aFacesFile, meshDS, aSmdsToGhs3dIdMap ); - - aFacesFile.close(); - aPointsFile.close(); - - if ( ! Ok ) { - if ( !_keepFiles ) { - OSD_File( aFacesFileName ).Remove(); - OSD_File( aPointsFileName ).Remove(); - } - return error(COMPERR_BAD_INPUT_MESH); - } - OSD_File( aResultFileName ).Remove(); // needed for boundary recovery module usage - - // ----------------- - // run ghs3d mesher - // ----------------- - - TCollection_AsciiString cmd( (char*)GHS3DPlugin_Hypothesis::CommandToRun( _hyp ).c_str() ); - cmd += TCollection_AsciiString(" -f ") + aGenericName; // file to read - cmd += TCollection_AsciiString(" 1>" ) + aLogFileName; // dump into file - - cout << endl; - cout << "Ghs3d execution..." << endl; - cout << cmd << endl; - - system( cmd.ToCString() ); // run - - cout << endl; - cout << "End of Ghs3d execution !" << endl; - - // -------------- - // read a result - // -------------- - - // Mapping the result file - - int fileOpen; - fileOpen = open( aResultFileName.ToCString(), O_RDONLY); - if ( fileOpen < 0 ) { - cout << endl; - cout << "Can't open the " << aResultFileName.ToCString() << " GHS3D output file" << endl; - cout << "Log: " << aLogFileName << endl; - Ok = false; - } - else { - bool toMeshHoles = - _hyp ? _hyp->GetToMeshHoles(true) : GHS3DPlugin_Hypothesis::DefaultMeshHoles(); - Ok = readResultFile( fileOpen, theMesh, tabShape, tabBox, _nbShape, aGhs3dIdToNodeMap, - toMeshHoles ); - } - - // --------------------- - // remove working files - // --------------------- - - if ( Ok ) - { - if ( !_keepFiles ) - OSD_File( aLogFileName ).Remove(); - } - else if ( OSD_File( aLogFileName ).Size() > 0 ) - { - // get problem description from the log file - _Ghs2smdsConvertor conv( aGhs3dIdToNodeMap ); - storeErrorDescription( aLogFileName, conv ); - } - else - { - // the log file is empty - OSD_File( aLogFileName ).Remove(); - INFOS( "GHS3D Error, command '" << cmd.ToCString() << "' failed" ); - error(COMPERR_ALGO_FAILED, "ghs3d: command not found" ); - } - - if ( !_keepFiles ) { - OSD_File( aFacesFileName ).Remove(); - OSD_File( aPointsFileName ).Remove(); - OSD_File( aResultFileName ).Remove(); - OSD_File( aBadResFileName ).Remove(); - OSD_File( aBbResFileName ).Remove(); - } - cout << "<" << aResultFileName.ToCString() << "> GHS3D output file "; - if ( !Ok ) - cout << "not "; - cout << "treated !" << endl; - cout << endl; - - _nbShape = 0; // re-initializing _nbShape for the next Compute() method call - delete [] tabShape; - delete [] tabBox; - - return Ok; -} - -//============================================================================= -/*! - *Here we are going to use the GHS3D mesher w/o geometry - */ -//============================================================================= -bool GHS3DPlugin_GHS3D::Compute(SMESH_Mesh& theMesh, - SMESH_MesherHelper* aHelper) -{ - MESSAGE("GHS3DPlugin_GHS3D::Compute()"); - - SMESHDS_Mesh* meshDS = theMesh.GetMeshDS(); - TopoDS_Shape theShape = aHelper->GetSubShape(); - - // a unique working file name - // to avoid access to the same files by eg different users - TCollection_AsciiString aGenericName - = (char*) GHS3DPlugin_Hypothesis::GetFileName(_hyp).c_str(); - - TCollection_AsciiString aFacesFileName, aPointsFileName, aResultFileName; - TCollection_AsciiString aBadResFileName, aBbResFileName, aLogFileName; - aFacesFileName = aGenericName + ".faces"; // in faces - aPointsFileName = aGenericName + ".points"; // in points - aResultFileName = aGenericName + ".noboite";// out points and volumes - aBadResFileName = aGenericName + ".boite"; // out bad result - aBbResFileName = aGenericName + ".bb"; // out vertex stepsize - aLogFileName = aGenericName + ".log"; // log - - // ----------------- - // make input files - // ----------------- - - ofstream aFacesFile ( aFacesFileName.ToCString() , ios::out); - ofstream aPointsFile ( aPointsFileName.ToCString() , ios::out); - bool Ok = -#ifdef WIN32 - aFacesFile->is_open() && aPointsFile->is_open(); -#else - aFacesFile.rdbuf()->is_open() && aPointsFile.rdbuf()->is_open(); -#endif - - if (!Ok) - return error( SMESH_Comment("Can't write into ") << aPointsFileName); - - vector aNodeByGhs3dId; - - Ok = (writeFaces ( aFacesFile, meshDS, aNodeByGhs3dId ) && - writePoints( aPointsFile, meshDS, aNodeByGhs3dId)); - - aFacesFile.close(); - aPointsFile.close(); - - if ( ! Ok ) { - if ( !_keepFiles ) { - OSD_File( aFacesFileName ).Remove(); - OSD_File( aPointsFileName ).Remove(); - } - return error(COMPERR_BAD_INPUT_MESH); - } - OSD_File( aResultFileName ).Remove(); // needed for boundary recovery module usage - - // ----------------- - // run ghs3d mesher - // ----------------- - - TCollection_AsciiString cmd = - (char*)GHS3DPlugin_Hypothesis::CommandToRun( _hyp, false ).c_str(); - cmd += TCollection_AsciiString(" -f ") + aGenericName; // file to read - cmd += TCollection_AsciiString(" 1>" ) + aLogFileName; // dump into file - - system( cmd.ToCString() ); // run - - // -------------- - // read a result - // -------------- - int fileOpen; - fileOpen = open( aResultFileName.ToCString(), O_RDONLY); - if ( fileOpen < 0 ) { - cout << endl; - cout << "Error when opening the " << aResultFileName.ToCString() << " file" << endl; - cout << "Log: " << aLogFileName << endl; - cout << endl; - Ok = false; - } - else { - Ok = readResultFile( fileOpen, meshDS, theShape ,aNodeByGhs3dId ); - } - - // --------------------- - // remove working files - // --------------------- - - if ( Ok ) - { - if ( !_keepFiles ) - OSD_File( aLogFileName ).Remove(); - } - else if ( OSD_File( aLogFileName ).Size() > 0 ) - { - // get problem description from the log file - _Ghs2smdsConvertor conv( aNodeByGhs3dId ); - storeErrorDescription( aLogFileName, conv ); - } - else { - // the log file is empty - OSD_File( aLogFileName ).Remove(); - INFOS( "GHS3D Error, command '" << cmd.ToCString() << "' failed" ); - error(COMPERR_ALGO_FAILED, "ghs3d: command not found" ); - } - - if ( !_keepFiles ) - { - OSD_File( aFacesFileName ).Remove(); - OSD_File( aPointsFileName ).Remove(); - OSD_File( aResultFileName ).Remove(); - OSD_File( aBadResFileName ).Remove(); - OSD_File( aBbResFileName ).Remove(); - } - - return Ok; -} - -//================================================================================ -/*! - * \brief Provide human readable text by error code reported by ghs3d - */ -//================================================================================ - -static string translateError(const int errNum) -{ - switch ( errNum ) { - case 0: - return "The surface mesh includes a face of type other than edge, " - "triangle or quadrilateral. This face type is not supported."; - case 1: - return "Not enough memory for the face table."; - case 2: - return "Not enough memory."; - case 3: - return "Not enough memory."; - case 4: - return "Face is ignored."; - case 5: - return "End of file. Some data are missing in the file."; - case 6: - return "Read error on the file. There are wrong data in the file."; - case 7: - return "the metric file is inadequate (dimension other than 3)."; - case 8: - return "the metric file is inadequate (values not per vertices)."; - case 9: - return "the metric file contains more than one field."; - case 10: - return "the number of values in the \".bb\" (metric file) is incompatible with the expected" - "value of number of mesh vertices in the \".noboite\" file."; - case 12: - return "Too many sub-domains."; - case 13: - return "the number of vertices is negative or null."; - case 14: - return "the number of faces is negative or null."; - case 15: - return "A face has a null vertex."; - case 22: - return "incompatible data."; - case 131: - return "the number of vertices is negative or null."; - case 132: - return "the number of vertices is negative or null (in the \".mesh\" file)."; - case 133: - return "the number of faces is negative or null."; - case 1000: - return "A face appears more than once in the input surface mesh."; - case 1001: - return "An edge appears more than once in the input surface mesh."; - case 1002: - return "A face has a vertex negative or null."; - case 1003: - return "NOT ENOUGH MEMORY."; - case 2000: - return "Not enough available memory."; - case 2002: - return "Some initial points cannot be inserted. The surface mesh is probably very bad " - "in terms of quality or the input list of points is wrong."; - case 2003: - return "Some vertices are too close to one another or coincident."; - case 2004: - return "Some vertices are too close to one another or coincident."; - case 2012: - return "A vertex cannot be inserted."; - case 2014: - return "There are at least two points considered as coincident."; - case 2103: - return "Some vertices are too close to one another or coincident."; - case 3000: - return "The surface mesh regeneration step has failed."; - case 3009: - return "Constrained edge cannot be enforced."; - case 3019: - return "Constrained face cannot be enforced."; - case 3029: - return "Missing faces."; - case 3100: - return "No guess to start the definition of the connected component(s)."; - case 3101: - return "The surface mesh includes at least one hole. The domain is not well defined."; - case 3102: - return "Impossible to define a component."; - case 3103: - return "The surface edge intersects another surface edge."; - case 3104: - return "The surface edge intersects the surface face."; - case 3105: - return "One boundary point lies within a surface face."; - case 3106: - return "One surface edge intersects a surface face."; - case 3107: - return "One boundary point lies within a surface edge."; - case 3108: - return "Insufficient memory ressources detected due to a bad quality surface mesh leading " - "to too many swaps."; - case 3109: - return "Edge is unique (i.e., bounds a hole in the surface)."; - case 3122: - return "Presumably, the surface mesh is not compatible with the domain being processed."; - case 3123: - return "Too many components, too many sub-domain."; - case 3209: - return "The surface mesh includes at least one hole. " - "Therefore there is no domain properly defined."; - case 3300: - return "Statistics."; - case 3400: - return "Statistics."; - case 3500: - return "Warning, it is dramatically tedious to enforce the boundary items."; - case 4000: - return "Not enough memory at this time, nevertheless, the program continues. " - "The expected mesh will be correct but not really as large as required."; - case 4002: - return "see above error code, resulting quality may be poor."; - case 4003: - return "Not enough memory at this time, nevertheless, the program continues (warning)."; - case 8000: - return "Unknown face type."; - case 8005: - case 8006: - return "End of file. Some data are missing in the file."; - case 9000: - return "A too small volume element is detected."; - case 9001: - return "There exists at least a null or negative volume element."; - case 9002: - return "There exist null or negative volume elements."; - case 9003: - return "A too small volume element is detected. A face is considered being degenerated."; - case 9100: - return "Some element is suspected to be very bad shaped or wrong."; - case 9102: - return "A too bad quality face is detected. This face is considered degenerated."; - case 9112: - return "A too bad quality face is detected. This face is degenerated."; - case 9122: - return "Presumably, the surface mesh is not compatible with the domain being processed."; - case 9999: - return "Abnormal error occured, contact hotline."; - case 23600: - return "Not enough memory for the face table."; - case 23601: - return "The algorithm cannot run further. " - "The surface mesh is probably very bad in terms of quality."; - case 23602: - return "Bad vertex number."; - } - return ""; -} - -//================================================================================ -/*! - * \brief Retrieve from a string given number of integers - */ -//================================================================================ - -static char* getIds( char* ptr, int nbIds, vector& ids ) -{ - ids.clear(); - ids.reserve( nbIds ); - while ( nbIds ) - { - while ( !isdigit( *ptr )) ++ptr; - if ( ptr[-1] == '-' ) --ptr; - ids.push_back( strtol( ptr, &ptr, 10 )); - --nbIds; - } - return ptr; -} - -//================================================================================ -/*! - * \brief Retrieve problem description form a log file - * \retval bool - always false - */ -//================================================================================ - -bool GHS3DPlugin_GHS3D::storeErrorDescription(const TCollection_AsciiString& logFile, - const _Ghs2smdsConvertor & toSmdsConvertor ) -{ - // open file -#ifdef WNT - int file = ::_open (logFile.ToCString(), _O_RDONLY|_O_BINARY); -#else - int file = ::open (logFile.ToCString(), O_RDONLY); -#endif - if ( file < 0 ) - return error( SMESH_Comment("See ") << logFile << " for problem description"); - - // get file size -// struct stat status; -// fstat(file, &status); -// size_t length = status.st_size; - off_t length = lseek( file, 0, SEEK_END); - lseek( file, 0, SEEK_SET); - - // read file - vector< char > buf( length ); - int nBytesRead = ::read (file, & buf[0], length); - ::close (file); - char* ptr = & buf[0]; - char* bufEnd = ptr + nBytesRead; - - SMESH_Comment errDescription; - - enum { NODE = 1, EDGE, TRIA, VOL, ID = 1 }; - - // look for errors "ERR #" - - set foundErrorStr; // to avoid reporting same error several times - set elemErrorNums; // not to report different types of errors with bad elements - while ( ++ptr < bufEnd ) - { - if ( strncmp( ptr, "ERR ", 4 ) != 0 ) - continue; - - list badElems; - vector nodeIds; - - ptr += 4; - char* errBeg = ptr; - int errNum = strtol(ptr, &ptr, 10); - switch ( errNum ) { // we treat errors enumerated in [SALOME platform 0019316] issue - case 0015: - // The face number (numfac) with vertices (f 1, f 2, f 3) has a null vertex. - ptr = getIds(ptr, NODE, nodeIds); - ptr = getIds(ptr, TRIA, nodeIds); - badElems.push_back( toSmdsConvertor.getElement(nodeIds)); - break; - case 1000: // ERR 1000 : 1 3 2 - // Face (f 1, f 2, f 3) appears more than once in the input surface mesh. - ptr = getIds(ptr, TRIA, nodeIds); - badElems.push_back( toSmdsConvertor.getElement(nodeIds)); - break; - case 1001: - // Edge (e1, e2) appears more than once in the input surface mesh - ptr = getIds(ptr, EDGE, nodeIds); - badElems.push_back( toSmdsConvertor.getElement(nodeIds)); - break; - case 1002: - // Face (f 1, f 2, f 3) has a vertex negative or null - ptr = getIds(ptr, TRIA, nodeIds); - badElems.push_back( toSmdsConvertor.getElement(nodeIds)); - break; - case 2004: - // Vertex v1 and vertex v2 are too close to one another or coincident (warning). - ptr = getIds(ptr, NODE, nodeIds); - badElems.push_back( toSmdsConvertor.getElement(nodeIds)); - ptr = getIds(ptr, NODE, nodeIds); - badElems.push_back( toSmdsConvertor.getElement(nodeIds)); - break; - case 2012: - // Vertex v1 cannot be inserted (warning). - ptr = getIds(ptr, NODE, nodeIds); - badElems.push_back( toSmdsConvertor.getElement(nodeIds)); - break; - case 2014: - // There are at least two points whose distance is dist, i.e., considered as coincident - case 2103: // ERR 2103 : 16 WITH 3 - // Vertex v1 and vertex v2 are too close to one another or coincident (warning). - ptr = getIds(ptr, NODE, nodeIds); - badElems.push_back( toSmdsConvertor.getElement(nodeIds)); - ptr = getIds(ptr, NODE, nodeIds); - badElems.push_back( toSmdsConvertor.getElement(nodeIds)); - break; - case 3009: - // Constrained edge (e1, e2) cannot be enforced (warning). - ptr = getIds(ptr, EDGE, nodeIds); - badElems.push_back( toSmdsConvertor.getElement(nodeIds)); - break; - case 3019: - // Constrained face (f 1, f 2, f 3) cannot be enforced - ptr = getIds(ptr, TRIA, nodeIds); - badElems.push_back( toSmdsConvertor.getElement(nodeIds)); - break; - case 3103: // ERR 3103 : 1 2 WITH 7 3 - // The surface edge (e1, e2) intersects another surface edge (e3, e4) - ptr = getIds(ptr, EDGE, nodeIds); - badElems.push_back( toSmdsConvertor.getElement(nodeIds)); - ptr = getIds(ptr, EDGE, nodeIds); - badElems.push_back( toSmdsConvertor.getElement(nodeIds)); - break; - case 3104: // ERR 3104 : 9 10 WITH 1 2 3 - // The surface edge (e1, e2) intersects the surface face (f 1, f 2, f 3) - ptr = getIds(ptr, EDGE, nodeIds); - badElems.push_back( toSmdsConvertor.getElement(nodeIds)); - ptr = getIds(ptr, TRIA, nodeIds); - badElems.push_back( toSmdsConvertor.getElement(nodeIds)); - break; - case 3105: // ERR 3105 : 8 IN 2 3 5 - // One boundary point (say p1) lies within a surface face (f 1, f 2, f 3) - ptr = getIds(ptr, NODE, nodeIds); - badElems.push_back( toSmdsConvertor.getElement(nodeIds)); - ptr = getIds(ptr, TRIA, nodeIds); - badElems.push_back( toSmdsConvertor.getElement(nodeIds)); - break; - case 3106: - // One surface edge (say e1, e2) intersects a surface face (f 1, f 2, f 3) - ptr = getIds(ptr, EDGE, nodeIds); - badElems.push_back( toSmdsConvertor.getElement(nodeIds)); - ptr = getIds(ptr, TRIA, nodeIds); - badElems.push_back( toSmdsConvertor.getElement(nodeIds)); - break; - case 3107: // ERR 3107 : 2 IN 4 1 - // One boundary point (say p1) lies within a surface edge (e1, e2) (stop). - ptr = getIds(ptr, NODE, nodeIds); - badElems.push_back( toSmdsConvertor.getElement(nodeIds)); - ptr = getIds(ptr, EDGE, nodeIds); - badElems.push_back( toSmdsConvertor.getElement(nodeIds)); - break; - case 3109: // ERR 3109 : EDGE 5 6 UNIQUE - // Edge (e1, e2) is unique (i.e., bounds a hole in the surface) - ptr = getIds(ptr, EDGE, nodeIds); - badElems.push_back( toSmdsConvertor.getElement(nodeIds)); - break; - case 9000: // ERR 9000 - // ELEMENT 261 WITH VERTICES : 7 396 -8 242 - // VOLUME : -1.11325045E+11 W.R.T. EPSILON 0. - // A too small volume element is detected. Are reported the index of the element, - // its four vertex indices, its volume and the tolerance threshold value - ptr = getIds(ptr, ID, nodeIds); - ptr = getIds(ptr, VOL, nodeIds); - badElems.push_back( toSmdsConvertor.getElement(nodeIds)); - // even if all nodes found, volume it most probably invisible, - // add its faces to demenstrate it anyhow - { - vector faceNodes( nodeIds.begin(), --nodeIds.end() ); // 012 - badElems.push_back( toSmdsConvertor.getElement(faceNodes)); - faceNodes[2] = nodeIds[3]; // 013 - badElems.push_back( toSmdsConvertor.getElement(faceNodes)); - faceNodes[1] = nodeIds[2]; // 023 - badElems.push_back( toSmdsConvertor.getElement(faceNodes)); - faceNodes[0] = nodeIds[1]; // 123 - badElems.push_back( toSmdsConvertor.getElement(faceNodes)); - } - break; - case 9001: // ERR 9001 - // %% NUMBER OF NEGATIVE VOLUME TETS : 1 - // %% THE LARGEST NEGATIVE TET : 1.75376581E+11 - // %% NUMBER OF NULL VOLUME TETS : 0 - // There exists at least a null or negative volume element - break; - case 9002: - // There exist n null or negative volume elements - break; - case 9003: - // A too small volume element is detected - break; - case 9102: - // A too bad quality face is detected. This face is considered degenerated, - // its index, its three vertex indices together with its quality value are reported - break; // same as next - case 9112: // ERR 9112 - // FACE 2 WITH VERTICES : 4 2 5 - // SMALL INRADIUS : 0. - // A too bad quality face is detected. This face is degenerated, - // its index, its three vertex indices together with its inradius are reported - ptr = getIds(ptr, ID, nodeIds); - ptr = getIds(ptr, TRIA, nodeIds); - badElems.push_back( toSmdsConvertor.getElement(nodeIds)); - // add triangle edges as it most probably has zero area and hence invisible - { - vector edgeNodes(2); - edgeNodes[0] = nodeIds[0]; edgeNodes[1] = nodeIds[1]; // 0-1 - badElems.push_back( toSmdsConvertor.getElement(edgeNodes)); - edgeNodes[1] = nodeIds[2]; // 0-2 - badElems.push_back( toSmdsConvertor.getElement(edgeNodes)); - edgeNodes[0] = nodeIds[1]; // 1-2 - badElems.push_back( toSmdsConvertor.getElement(edgeNodes)); - } - break; - } - - bool isNewError = foundErrorStr.insert( string( errBeg, ptr )).second; - if ( !isNewError ) - continue; // not to report same error several times - -// const SMDS_MeshElement* nullElem = 0; -// bool allElemsOk = ( find( badElems.begin(), badElems.end(), nullElem) == badElems.end()); - -// if ( allElemsOk && !badElems.empty() && !elemErrorNums.empty() ) { -// bool oneMoreErrorType = elemErrorNums.insert( errNum ).second; -// if ( oneMoreErrorType ) -// continue; // not to report different types of errors with bad elements -// } - - // store bad elements - //if ( allElemsOk ) { - list::iterator elem = badElems.begin(); - for ( ; elem != badElems.end(); ++elem ) - addBadInputElement( *elem ); - //} - - // make error text - string text = translateError( errNum ); - if ( errDescription.find( text ) == text.npos ) { - if ( !errDescription.empty() ) - errDescription << "\n"; - errDescription << text; - } - - } // end while - - if ( errDescription.empty() ) { // no errors found - char msg[] = "connection to server failed"; - if ( search( &buf[0], bufEnd, msg, msg + strlen(msg)) != bufEnd ) - errDescription << "Licence problems."; - } - - if ( errDescription.empty() ) - errDescription << "See " << logFile << " for problem description"; - else - errDescription << "\nSee " << logFile << " for more information"; - - return error( errDescription ); -} - -//================================================================================ -/*! - * \brief Creates _Ghs2smdsConvertor - */ -//================================================================================ - -_Ghs2smdsConvertor::_Ghs2smdsConvertor( const map & ghs2NodeMap) - :_ghs2NodeMap( & ghs2NodeMap ), _nodeByGhsId( 0 ) -{ -} - -//================================================================================ -/*! - * \brief Creates _Ghs2smdsConvertor - */ -//================================================================================ - -_Ghs2smdsConvertor::_Ghs2smdsConvertor( const vector & nodeByGhsId) - : _ghs2NodeMap( 0 ), _nodeByGhsId( &nodeByGhsId ) -{ -} - -//================================================================================ -/*! - * \brief Return SMDS element by ids of GHS3D nodes - */ -//================================================================================ - -const SMDS_MeshElement* _Ghs2smdsConvertor::getElement(const vector& ghsNodes) const -{ - size_t nbNodes = ghsNodes.size(); - vector nodes( nbNodes, 0 ); - for ( size_t i = 0; i < nbNodes; ++i ) { - int ghsNode = ghsNodes[ i ]; - if ( _ghs2NodeMap ) { - map ::const_iterator in = _ghs2NodeMap->find( ghsNode); - if ( in == _ghs2NodeMap->end() ) - return 0; - nodes[ i ] = in->second; - } - else { - if ( ghsNode < 1 || ghsNode > _nodeByGhsId->size() ) - return 0; - nodes[ i ] = (*_nodeByGhsId)[ ghsNode-1 ]; - } - } - if ( nbNodes == 1 ) - return nodes[0]; - - if ( nbNodes == 2 ) { - const SMDS_MeshElement* edge= SMDS_Mesh::FindEdge( nodes[0], nodes[1] ); - if ( !edge ) - edge = new SMDS_MeshEdge( nodes[0], nodes[1] ); - return edge; - } - if ( nbNodes == 3 ) { - const SMDS_MeshElement* face = SMDS_Mesh::FindFace( nodes ); - if ( !face ) - face = new SMDS_FaceOfNodes( nodes[0], nodes[1], nodes[2] ); - return face; - } - if ( nbNodes == 4 ) - return new SMDS_VolumeOfNodes( nodes[0], nodes[1], nodes[2], nodes[3] ); - - return 0; -} - diff --git a/src/GHS3DPlugin_GHS3D_i.cxx b/src/GHS3DPlugin_GHS3D_i.cxx deleted file mode 100644 index 21469d3..0000000 --- a/src/GHS3DPlugin_GHS3D_i.cxx +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright (C) 2004-2008 CEA/DEN, EDF R&D -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License. -// -// 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_I : idl implementation based on 'SMESH' unit's calsses -// File : GHS3DPlugin_GHS3D_i.cxx -// Author : Edward AGAPOV -// Module : GHS3DPlugin -// $Header$ -// -using namespace std; -#include "GHS3DPlugin_GHS3D_i.hxx" -#include "SMESH_Gen.hxx" -#include "GHS3DPlugin_GHS3D.hxx" - -#include "utilities.h" - -//============================================================================= -/*! - * GHS3DPlugin_GHS3D_i::GHS3DPlugin_GHS3D_i - * - * Constructor - */ -//============================================================================= - -GHS3DPlugin_GHS3D_i::GHS3DPlugin_GHS3D_i (PortableServer::POA_ptr thePOA, - int theStudyId, - ::SMESH_Gen* theGenImpl ) - : SALOME::GenericObj_i( thePOA ), - SMESH_Hypothesis_i( thePOA ), - SMESH_Algo_i( thePOA ), - SMESH_3D_Algo_i( thePOA ) -{ - MESSAGE( "GHS3DPlugin_GHS3D_i::GHS3DPlugin_GHS3D_i" ); - myBaseImpl = new ::GHS3DPlugin_GHS3D (theGenImpl->GetANewId(), - theStudyId, - theGenImpl ); -} - -//============================================================================= -/*! - * GHS3DPlugin_GHS3D_i::~GHS3DPlugin_GHS3D_i - * - * Destructor - */ -//============================================================================= - -GHS3DPlugin_GHS3D_i::~GHS3DPlugin_GHS3D_i() -{ - MESSAGE( "GHS3DPlugin_GHS3D_i::~GHS3DPlugin_GHS3D_i" ); -} - -//============================================================================= -/*! - * GHS3DPlugin_GHS3D_i::GetImpl - * - * Get implementation - */ -//============================================================================= - -::GHS3DPlugin_GHS3D* GHS3DPlugin_GHS3D_i::GetImpl() -{ - MESSAGE( "GHS3DPlugin_GHS3D_i::GetImpl" ); - return ( ::GHS3DPlugin_GHS3D* )myBaseImpl; -} - diff --git a/src/GHS3DPlugin_Hypothesis.cxx b/src/GHS3DPlugin_Hypothesis.cxx deleted file mode 100644 index 3a29541..0000000 --- a/src/GHS3DPlugin_Hypothesis.cxx +++ /dev/null @@ -1,628 +0,0 @@ -// Copyright (C) 2004-2008 CEA/DEN, EDF R&D -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License. -// -// 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 : GHS3DPlugin_Hypothesis.cxx -// Created : Wed Apr 2 12:36:29 2008 -// Author : Edward AGAPOV (eap) -//============================================================================= -// -#include "GHS3DPlugin_Hypothesis.hxx" - -#include - -//======================================================================= -//function : GHS3DPlugin_Hypothesis -//======================================================================= - -GHS3DPlugin_Hypothesis::GHS3DPlugin_Hypothesis(int hypId, int studyId, SMESH_Gen * gen) - : SMESH_Hypothesis(hypId, studyId, gen) -{ - _name = "GHS3D_Parameters"; - _param_algo_dim = 3; - - myToMeshHoles = DefaultMeshHoles(); - myMaximumMemory = -1;//DefaultMaximumMemory(); - myInitialMemory = -1;//DefaultInitialMemory(); - myOptimizationLevel = DefaultOptimizationLevel(); - myWorkingDirectory = DefaultWorkingDirectory(); - myKeepFiles = DefaultKeepFiles(); - myVerboseLevel = DefaultVerboseLevel(); - myToCreateNewNodes = DefaultToCreateNewNodes(); - myToUseBoundaryRecoveryVersion = DefaultToUseBoundaryRecoveryVersion(); -} - -//======================================================================= -//function : SetToMeshHoles -//======================================================================= - -void GHS3DPlugin_Hypothesis::SetToMeshHoles(bool toMesh) -{ - if ( myToMeshHoles != toMesh ) { - myToMeshHoles = toMesh; - NotifySubMeshesHypothesisModification(); - } -} - -//======================================================================= -//function : GetToMeshHoles -//======================================================================= - -bool GHS3DPlugin_Hypothesis::GetToMeshHoles(bool checkFreeOption) const -{ - if (checkFreeOption && !myTextOption.empty()) { - if ( myTextOption.find("-c 0")) - return true; - if ( myTextOption.find("-c 1")) - return false; - } - return myToMeshHoles; -} - -//======================================================================= -//function : SetMaximumMemory -//======================================================================= - -void GHS3DPlugin_Hypothesis::SetMaximumMemory(short MB) -{ - if ( myMaximumMemory != MB ) { - myMaximumMemory = MB; - NotifySubMeshesHypothesisModification(); - } -} - -//======================================================================= -//function : GetMaximumMemory -// * automatic memory adjustment mode. Default is zero -//======================================================================= - -short GHS3DPlugin_Hypothesis::GetMaximumMemory() const -{ - return myMaximumMemory; -} - -//======================================================================= -//function : SetInitialMemory -//======================================================================= - -void GHS3DPlugin_Hypothesis::SetInitialMemory(short MB) -{ - if ( myInitialMemory != MB ) { - myInitialMemory = MB; - NotifySubMeshesHypothesisModification(); - } -} - -//======================================================================= -//function : GetInitialMemory -//======================================================================= - -short GHS3DPlugin_Hypothesis::GetInitialMemory() const -{ - return myInitialMemory; -} - -//======================================================================= -//function : SetOptimizationLevel -//======================================================================= - -void GHS3DPlugin_Hypothesis::SetOptimizationLevel(OptimizationLevel level) -{ - if ( myOptimizationLevel != level ) { - myOptimizationLevel = level; - NotifySubMeshesHypothesisModification(); - } -} - -//======================================================================= -//function : GetOptimizationLevel -//======================================================================= - -GHS3DPlugin_Hypothesis::OptimizationLevel GHS3DPlugin_Hypothesis::GetOptimizationLevel() const -{ - return (OptimizationLevel) myOptimizationLevel; -} - -//======================================================================= -//function : SetWorkingDirectory -//======================================================================= - -void GHS3DPlugin_Hypothesis::SetWorkingDirectory(const string& path) -{ - if ( myWorkingDirectory != path ) { - myWorkingDirectory = path; - NotifySubMeshesHypothesisModification(); - } -} - -//======================================================================= -//function : GetWorkingDirectory -//======================================================================= - -string GHS3DPlugin_Hypothesis::GetWorkingDirectory() const -{ - return myWorkingDirectory; -} - -//======================================================================= -//function : SetKeepFiles -//======================================================================= - -void GHS3DPlugin_Hypothesis::SetKeepFiles(bool toKeep) -{ - if ( myKeepFiles != toKeep ) { - myKeepFiles = toKeep; - NotifySubMeshesHypothesisModification(); - } -} - -//======================================================================= -//function : GetKeepFiles -//======================================================================= - -bool GHS3DPlugin_Hypothesis::GetKeepFiles() const -{ - return myKeepFiles; -} - -//======================================================================= -//function : SetVerboseLevel -//======================================================================= - -void GHS3DPlugin_Hypothesis::SetVerboseLevel(short level) -{ - if ( myVerboseLevel != level ) { - myVerboseLevel = level; - NotifySubMeshesHypothesisModification(); - } -} - -//======================================================================= -//function : GetVerboseLevel -//======================================================================= - -short GHS3DPlugin_Hypothesis::GetVerboseLevel() const -{ - return myVerboseLevel; -} - -//======================================================================= -//function : SetToCreateNewNodes -//======================================================================= - -void GHS3DPlugin_Hypothesis::SetToCreateNewNodes(bool toCreate) -{ - if ( myToCreateNewNodes != toCreate ) { - myToCreateNewNodes = toCreate; - NotifySubMeshesHypothesisModification(); - } -} - -//======================================================================= -//function : GetToCreateNewNodes -//======================================================================= - -bool GHS3DPlugin_Hypothesis::GetToCreateNewNodes() const -{ - return myToCreateNewNodes; -} - -//======================================================================= -//function : SetToUseBoundaryRecoveryVersion -//======================================================================= - -void GHS3DPlugin_Hypothesis::SetToUseBoundaryRecoveryVersion(bool toUse) -{ - if ( myToUseBoundaryRecoveryVersion != toUse ) { - myToUseBoundaryRecoveryVersion = toUse; - NotifySubMeshesHypothesisModification(); - } -} - -//======================================================================= -//function : GetToUseBoundaryRecoveryVersion -//======================================================================= - -bool GHS3DPlugin_Hypothesis::GetToUseBoundaryRecoveryVersion() const -{ - return myToUseBoundaryRecoveryVersion; -} - -//======================================================================= -//function : SetTextOption -//======================================================================= - -void GHS3DPlugin_Hypothesis::SetTextOption(const string& option) -{ - if ( myTextOption != option ) { - myTextOption = option; - NotifySubMeshesHypothesisModification(); - } -} - -//======================================================================= -//function : GetTextOption -//======================================================================= - -string GHS3DPlugin_Hypothesis::GetTextOption() const -{ - return myTextOption; -} - - -//======================================================================= -//function : DefaultMeshHoles -//======================================================================= - -bool GHS3DPlugin_Hypothesis::DefaultMeshHoles() -{ - return false; // PAL19680 -} - -//======================================================================= -//function : DefaultMaximumMemory -//======================================================================= - -#ifndef WIN32 -#include -#endif - -short GHS3DPlugin_Hypothesis::DefaultMaximumMemory() -{ -#ifndef WIN32 - struct sysinfo si; - int err = sysinfo( &si ); - if ( err == 0 ) { - int ramMB = si.totalram * si.mem_unit / 1024 / 1024; - return (short) ( 0.7 * ramMB ); - } -#endif - return -1; -} - -//======================================================================= -//function : DefaultInitialMemory -//======================================================================= - -short GHS3DPlugin_Hypothesis::DefaultInitialMemory() -{ - return DefaultMaximumMemory(); -} - -//======================================================================= -//function : DefaultOptimizationLevel -//======================================================================= - -short GHS3DPlugin_Hypothesis::DefaultOptimizationLevel() -{ - return Medium; -} - -//======================================================================= -//function : DefaultWorkingDirectory -//======================================================================= - -string GHS3DPlugin_Hypothesis::DefaultWorkingDirectory() -{ - TCollection_AsciiString aTmpDir; - - char *Tmp_dir = getenv("SALOME_TMP_DIR"); - if(Tmp_dir != NULL) { - aTmpDir = Tmp_dir; - } - else { -#ifdef WIN32 - aTmpDir = TCollection_AsciiString("C:\\"); -#else - aTmpDir = TCollection_AsciiString("/tmp/"); -#endif - } - return aTmpDir.ToCString(); -} - -//======================================================================= -//function : DefaultKeepFiles -//======================================================================= - -bool GHS3DPlugin_Hypothesis::DefaultKeepFiles() -{ - return false; -} - -//======================================================================= -//function : DefaultVerboseLevel -//======================================================================= - -short GHS3DPlugin_Hypothesis::DefaultVerboseLevel() -{ - return 10; -} - -//======================================================================= -//function : DefaultToCreateNewNodes -//======================================================================= - -bool GHS3DPlugin_Hypothesis::DefaultToCreateNewNodes() -{ - return true; -} - -//======================================================================= -//function : DefaultToUseBoundaryRecoveryVersion -//======================================================================= - -bool GHS3DPlugin_Hypothesis::DefaultToUseBoundaryRecoveryVersion() -{ - return false; -} - -//======================================================================= -//function : SaveTo -//======================================================================= - -ostream & GHS3DPlugin_Hypothesis::SaveTo(ostream & save) -{ - save << (int) myToMeshHoles << " "; - save << myMaximumMemory << " "; - save << myInitialMemory << " "; - save << myOptimizationLevel << " "; - save << myWorkingDirectory << " "; - save << (int)myKeepFiles << " "; - save << myVerboseLevel << " "; - save << (int)myToCreateNewNodes << " "; - save << (int)myToUseBoundaryRecoveryVersion << " "; - save << myTextOption << " "; - return save; -} - -//======================================================================= -//function : LoadFrom -//======================================================================= - -istream & GHS3DPlugin_Hypothesis::LoadFrom(istream & load) -{ - bool isOK = true; - int i; - - isOK = (load >> i); - if (isOK) - myToMeshHoles = i; - else - load.clear(ios::badbit | load.rdstate()); - - isOK = (load >> i); - if (isOK) - myMaximumMemory = i; - else - load.clear(ios::badbit | load.rdstate()); - - isOK = (load >> i); - if (isOK) - myInitialMemory = i; - else - load.clear(ios::badbit | load.rdstate()); - - isOK = (load >> i); - if (isOK) - myOptimizationLevel = i; - else - load.clear(ios::badbit | load.rdstate()); - - isOK = (load >> myWorkingDirectory); - if (isOK) { - if ( myWorkingDirectory == "0") { // myWorkingDirectory was empty - myKeepFiles = false; - myWorkingDirectory.clear(); - } - else if ( myWorkingDirectory == "1" ) { - myKeepFiles = true; - myWorkingDirectory.clear(); - } - } - else - load.clear(ios::badbit | load.rdstate()); - - if ( !myWorkingDirectory.empty() ) { - isOK = (load >> i); - if (isOK) - myKeepFiles = i; - else - load.clear(ios::badbit | load.rdstate()); - } - - isOK = (load >> i); - if (isOK) - myVerboseLevel = (short) i; - else - load.clear(ios::badbit | load.rdstate()); - - isOK = (load >> i); - if (isOK) - myToCreateNewNodes = (bool) i; - else - load.clear(ios::badbit | load.rdstate()); - - isOK = (load >> i); - if (isOK) - myToUseBoundaryRecoveryVersion = (bool) i; - else - load.clear(ios::badbit | load.rdstate()); - - isOK = (load >> myTextOption); - while (isOK) { - string txt; - if (load >> txt) { - myTextOption += " "; - myTextOption += txt; - } - else - isOK = false; - } -// else -// load.clear(ios::badbit | load.rdstate()); - - return load; -} - -//======================================================================= -//function : SetParametersByMesh -//======================================================================= - -bool GHS3DPlugin_Hypothesis::SetParametersByMesh(const SMESH_Mesh* ,const TopoDS_Shape&) -{ - return false; -} - - -//================================================================================ -/*! - * \brief Return false - */ -//================================================================================ - -bool GHS3DPlugin_Hypothesis::SetParametersByDefaults(const TDefaults& /*dflts*/, - const SMESH_Mesh* /*theMesh*/) -{ - return false; -} - -//================================================================================ -/*! - * \brief Return command to run ghs3d mesher excluding file prefix (-f) - */ -//================================================================================ - -string GHS3DPlugin_Hypothesis::CommandToRun(const GHS3DPlugin_Hypothesis* hyp, - const bool hasShapeToMesh) -{ -#ifndef WIN32 - TCollection_AsciiString cmd( "ghs3d" ); -#else - TCollection_AsciiString cmd( "ghs3d.exe" ); -#endif - // check if any option is overridden by hyp->myTextOption - bool m = hyp ? ( hyp->myTextOption.find("-m") == string::npos ) : true; - bool M = hyp ? ( hyp->myTextOption.find("-M") == string::npos ) : true; - bool c = hyp ? ( hyp->myTextOption.find("-c") == string::npos ) : true; - bool o = hyp ? ( hyp->myTextOption.find("-o") == string::npos ) : true; - bool p0= hyp ? ( hyp->myTextOption.find("-p0")== string::npos ) : true; - bool C = hyp ? ( hyp->myTextOption.find("-C") == string::npos ) : true; - bool v = hyp ? ( hyp->myTextOption.find("-v") == string::npos ) : true; - - // if use boundary recovery version, few options are allowed - bool useBndRecovery = !C; - if ( !useBndRecovery && hyp ) - useBndRecovery = hyp->myToUseBoundaryRecoveryVersion; - - // ghs3d needs to know amount of memory it may use (MB). - // Default memory is defined at ghs3d installation but it may be not enough, - // so allow to use about all available memory - if ( m ) { - short aMaximumMemory = hyp ? hyp->myMaximumMemory : -1; - cmd += " -m "; - if ( aMaximumMemory < 0 ) - cmd += DefaultMaximumMemory(); - else - cmd += aMaximumMemory; - } - if ( M && !useBndRecovery ) { - short aInitialMemory = hyp ? hyp->myInitialMemory : -1; - cmd += " -M "; - if ( aInitialMemory > 0 ) - cmd += aInitialMemory; - else - cmd += "100"; - } - // component to mesh - // 0 , all components to be meshed - // 1 , only the main ( outermost ) component to be meshed - if ( c && !useBndRecovery ) { - // We always run GHS3D with "to mesh holes'==TRUE (see PAL19680) - if ( hasShapeToMesh ) - cmd += " -c 0"; - else { - bool aToMeshHoles = hyp ? hyp->myToMeshHoles : DefaultMeshHoles(); - if ( aToMeshHoles ) - cmd += " -c 0"; - else - cmd += " -c 1"; - } - } - - // optimization level - if ( o && hyp && !useBndRecovery ) { - if ( hyp->myOptimizationLevel >= 0 && hyp->myOptimizationLevel < 4 ) { - char* level[] = { "none" , "light" , "standard" , "strong" }; - cmd += " -o "; - cmd += level[ hyp->myOptimizationLevel ]; - } - } - - // to create internal nodes - if ( p0 && hyp && !hyp->myToCreateNewNodes ) { - cmd += " -p0"; - } - - // verbose mode - if ( v && hyp ) { - cmd += " -v "; - cmd += hyp->myVerboseLevel; - } - - // boundary recovery version - if ( useBndRecovery ) { - cmd += " -C"; - } - - // options as text - if ( hyp && !hyp->myTextOption.empty() ) { - cmd += " "; - cmd += (char*) hyp->myTextOption.c_str(); - } - - return cmd.ToCString(); -} - -//================================================================================ -/*! - * \brief Return a unique file name - */ -//================================================================================ - -string GHS3DPlugin_Hypothesis::GetFileName(const GHS3DPlugin_Hypothesis* hyp) -{ - string aTmpDir = hyp ? hyp->GetWorkingDirectory() : DefaultWorkingDirectory(); - const char lastChar = *aTmpDir.rbegin(); -#ifdef WIN32 - if(lastChar != '\\') aTmpDir+='\\'; -#else - if(lastChar != '/') aTmpDir+='/'; -#endif - - TCollection_AsciiString aGenericName = (char*)aTmpDir.c_str(); - aGenericName += "GHS3D_"; -#ifdef WIN32 - aGenericName += GetCurrentProcessId(); -#else - aGenericName += getpid(); -#endif - aGenericName += "_"; - aGenericName += Abs((Standard_Integer)(long) aGenericName.ToCString()); - - return aGenericName.ToCString(); -} diff --git a/src/GHS3DPlugin_Hypothesis.hxx b/src/GHS3DPlugin_Hypothesis.hxx deleted file mode 100644 index 1c59739..0000000 --- a/src/GHS3DPlugin_Hypothesis.hxx +++ /dev/null @@ -1,152 +0,0 @@ -// Copyright (C) 2004-2008 CEA/DEN, EDF R&D -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License. -// -// 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 -// -// GHS3DPlugin : C++ implementation -// File : GHS3DPlugin_Hypothesis.hxx -// Created : Wed Apr 2 12:21:17 2008 -// Author : Edward AGAPOV (eap) -// -#ifndef GHS3DPlugin_Hypothesis_HeaderFile -#define GHS3DPlugin_Hypothesis_HeaderFile - -#include "GHS3DPlugin_Defs.hxx" - -#include - -using namespace std; - -class GHS3DPLUGIN_EXPORT GHS3DPlugin_Hypothesis: public SMESH_Hypothesis -{ -public: - - GHS3DPlugin_Hypothesis(int hypId, int studyId, SMESH_Gen * gen); - - /*! - * To mesh "holes" in a solid or not. Default is to mesh. - */ - void SetToMeshHoles(bool toMesh); - bool GetToMeshHoles(bool checkFreeOption = false) const; - /*! - * Maximal size of memory to be used by the algorithm (in Megabytes) - */ - void SetMaximumMemory(short MB); - short GetMaximumMemory() const; - /*! - * Initial size of memory to be used by the algorithm (in Megabytes) in - * automatic memory adjustment mode. Default is zero - */ - void SetInitialMemory(short MB); - short GetInitialMemory() const; - /*! - * Optimization level: 0-none, 1-light, 2-medium, 3-strong. Default is medium - */ - enum OptimizationLevel { None = 0, Light, Medium, Strong }; - void SetOptimizationLevel(OptimizationLevel level); - OptimizationLevel GetOptimizationLevel() const; - /*! - * Path to working directory - */ - void SetWorkingDirectory(const string& path); - string GetWorkingDirectory() const; - /*! - * To keep working files or remove them. Log file remains in case of errors anyway. - */ - void SetKeepFiles(bool toKeep); - bool GetKeepFiles() const; - /*! - * Verbose level [0-10] - * 0 - no standard output, - * 2 - prints the data, quality statistics of the skin and final meshes and - * indicates when the final mesh is being saved. In addition the software - * gives indication regarding the CPU time. - * 10 - same as 2 plus the main steps in the computation, quality statistics - * histogram of the skin mesh, quality statistics histogram together with - * the characteristics of the final mesh. - */ - void SetVerboseLevel(short level); - short GetVerboseLevel() const; - /*! - * To create new nodes - */ - void SetToCreateNewNodes(bool toCreate); - bool GetToCreateNewNodes() const; - /*! - * To use boundary recovery version which tries to create mesh on a very poor - * quality surface mesh - */ - void SetToUseBoundaryRecoveryVersion(bool toUse); - bool GetToUseBoundaryRecoveryVersion() const; - /*! - * To set hiden/undocumented/advanced options - */ - void SetTextOption(const string& option); - string GetTextOption() const; - - static bool DefaultMeshHoles(); - static short DefaultMaximumMemory(); - static short DefaultInitialMemory(); - static short DefaultOptimizationLevel(); - static string DefaultWorkingDirectory(); - static bool DefaultKeepFiles(); - static short DefaultVerboseLevel(); - static bool DefaultToCreateNewNodes(); - static bool DefaultToUseBoundaryRecoveryVersion(); - - /*! - * \brief Return command to run ghs3d mesher excluding file prefix (-f) - */ - static std::string CommandToRun(const GHS3DPlugin_Hypothesis* hyp, - const bool hasShapeToMesh=true); - /*! - * \brief Return a unique file name - */ - static std::string GetFileName(const GHS3DPlugin_Hypothesis* hyp); - - // Persistence - virtual ostream & SaveTo(ostream & save); - virtual istream & LoadFrom(istream & load); - friend GHS3DPLUGIN_EXPORT ostream & operator <<(ostream & save, GHS3DPlugin_Hypothesis & hyp); - friend GHS3DPLUGIN_EXPORT istream & operator >>(istream & load, GHS3DPlugin_Hypothesis & hyp); - - /*! - * \brief Does nothing - */ - virtual bool SetParametersByMesh(const SMESH_Mesh* theMesh, const TopoDS_Shape& theShape); - - /*! - * \brief Does nothing - */ - virtual bool SetParametersByDefaults(const TDefaults& dflts, const SMESH_Mesh* theMesh=0); - -private: - - bool myToMeshHoles; - short myMaximumMemory; - short myInitialMemory; - short myOptimizationLevel; - bool myKeepFiles; - string myWorkingDirectory; - short myVerboseLevel; - bool myToCreateNewNodes; - bool myToUseBoundaryRecoveryVersion; - string myTextOption; - -}; - - -#endif diff --git a/src/GHS3DPlugin_Hypothesis_i.cxx b/src/GHS3DPlugin_Hypothesis_i.cxx deleted file mode 100644 index 3cec323..0000000 --- a/src/GHS3DPlugin_Hypothesis_i.cxx +++ /dev/null @@ -1,318 +0,0 @@ -// Copyright (C) 2004-2008 CEA/DEN, EDF R&D -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License. -// -// 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 : GHS3DPlugin_Hypothesis_i.cxx -// Created : Wed Apr 2 13:53:01 2008 -// Author : Edward AGAPOV (eap) -// -#include "GHS3DPlugin_Hypothesis_i.hxx" - -#include -#include - -#include -#include -#include - -//======================================================================= -//function : GHS3DPlugin_Hypothesis_i -//======================================================================= - -GHS3DPlugin_Hypothesis_i::GHS3DPlugin_Hypothesis_i (PortableServer::POA_ptr thePOA, - int theStudyId, - ::SMESH_Gen* theGenImpl) - : SALOME::GenericObj_i( thePOA ), - SMESH_Hypothesis_i( thePOA ) -{ - MESSAGE( "GHS3DPlugin_Hypothesis_i::GHS3DPlugin_Hypothesis_i" ); - myBaseImpl = new ::GHS3DPlugin_Hypothesis (theGenImpl->GetANewId(), - theStudyId, - theGenImpl); -} - -//======================================================================= -//function : ~GHS3DPlugin_Hypothesis_i -//======================================================================= - -GHS3DPlugin_Hypothesis_i::~GHS3DPlugin_Hypothesis_i() -{ - MESSAGE( "GHS3DPlugin_Hypothesis_i::~GHS3DPlugin_Hypothesis_i" ); -} - -//======================================================================= -//function : SetToMeshHoles -//======================================================================= - -void GHS3DPlugin_Hypothesis_i::SetToMeshHoles(CORBA::Boolean toMesh) -{ - ASSERT(myBaseImpl); - this->GetImpl()->SetToMeshHoles(toMesh); - SMESH::TPythonDump() << _this() << ".SetToMeshHoles( " << toMesh << " )"; -} - -//======================================================================= -//function : GetToMeshHoles -//======================================================================= - -CORBA::Boolean GHS3DPlugin_Hypothesis_i::GetToMeshHoles() -{ - ASSERT(myBaseImpl); - return this->GetImpl()->GetToMeshHoles(); -} - -//======================================================================= -//function : SetMaximumMemory -//======================================================================= - -void GHS3DPlugin_Hypothesis_i::SetMaximumMemory(CORBA::Short MB) - throw ( SALOME::SALOME_Exception ) -{ - if ( MB == 0 ) - THROW_SALOME_CORBA_EXCEPTION( "Invalid memory size",SALOME::BAD_PARAM ); - ASSERT(myBaseImpl); - this->GetImpl()->SetMaximumMemory(MB); - SMESH::TPythonDump() << _this() << ".SetMaximumMemory( " << MB << " )"; -} - -//======================================================================= -//function : GetMaximumMemory -//======================================================================= - -CORBA::Short GHS3DPlugin_Hypothesis_i::GetMaximumMemory() -{ - ASSERT(myBaseImpl); - return this->GetImpl()->GetMaximumMemory(); -} - -//======================================================================= -//function : SetInitialMemory -//======================================================================= - -void GHS3DPlugin_Hypothesis_i::SetInitialMemory(CORBA::Short MB) - throw ( SALOME::SALOME_Exception ) -{ - if ( MB == 0 ) - THROW_SALOME_CORBA_EXCEPTION( "Invalid memory size",SALOME::BAD_PARAM ); - ASSERT(myBaseImpl); - this->GetImpl()->SetInitialMemory(MB); - SMESH::TPythonDump() << _this() << ".SetInitialMemory( " << MB << " )"; -} - -//======================================================================= -//function : GetInitialMemory -//======================================================================= - -CORBA::Short GHS3DPlugin_Hypothesis_i::GetInitialMemory() -{ - ASSERT(myBaseImpl); - return this->GetImpl()->GetInitialMemory(); -} - -//======================================================================= -//function : SetOptimizationLevel -//======================================================================= - -void GHS3DPlugin_Hypothesis_i::SetOptimizationLevel(CORBA::Short level) - throw ( SALOME::SALOME_Exception ) -{ - ::GHS3DPlugin_Hypothesis::OptimizationLevel l = - (::GHS3DPlugin_Hypothesis::OptimizationLevel) level; - if ( l < ::GHS3DPlugin_Hypothesis::None || - l > ::GHS3DPlugin_Hypothesis::Strong ) - THROW_SALOME_CORBA_EXCEPTION( "Invalid optimization level",SALOME::BAD_PARAM ); - - ASSERT(myBaseImpl); - this->GetImpl()->SetOptimizationLevel(l); - SMESH::TPythonDump() << _this() << ".SetOptimizationLevel( " << level << " )"; -} - -//======================================================================= -//function : GetOptimizationLevel -//======================================================================= - -CORBA::Short GHS3DPlugin_Hypothesis_i::GetOptimizationLevel() -{ - ASSERT(myBaseImpl); - return this->GetImpl()->GetOptimizationLevel(); -} - -//======================================================================= -//function : SetWorkingDirectory -//======================================================================= - -void GHS3DPlugin_Hypothesis_i::SetWorkingDirectory(const char* path) throw ( SALOME::SALOME_Exception ) -{ - if (!path ) - THROW_SALOME_CORBA_EXCEPTION( "Null working directory",SALOME::BAD_PARAM ); - - string file(path); - const char lastChar = *file.rbegin(); -#ifdef WIN32 - if ( lastChar != '\\' ) file += '\\'; -#else - if ( lastChar != '/' ) file += '/'; -#endif - file += "GHS3D.log"; - SMESH_Mesh_i::PrepareForWriting (file.c_str()); - - ASSERT(myBaseImpl); - this->GetImpl()->SetWorkingDirectory(path); - SMESH::TPythonDump() << _this() << ".SetWorkingDirectory( '" << path << "' )"; -} - -//======================================================================= -//function : GetWorkingDirectory -//======================================================================= - -char* GHS3DPlugin_Hypothesis_i::GetWorkingDirectory() -{ - ASSERT(myBaseImpl); - return CORBA::string_dup( this->GetImpl()->GetWorkingDirectory().c_str() ); -} - -//======================================================================= -//function : SetKeepFiles -//======================================================================= - -void GHS3DPlugin_Hypothesis_i::SetKeepFiles(CORBA::Boolean toKeep) -{ - ASSERT(myBaseImpl); - this->GetImpl()->SetKeepFiles(toKeep); - SMESH::TPythonDump() << _this() << ".SetKeepFiles( " << toKeep << " )"; -} - -//======================================================================= -//function : GetKeepFiles -//======================================================================= - -CORBA::Boolean GHS3DPlugin_Hypothesis_i::GetKeepFiles() -{ - ASSERT(myBaseImpl); - return this->GetImpl()->GetKeepFiles(); -} - -//======================================================================= -//function : SetVerboseLevel -//======================================================================= - -void GHS3DPlugin_Hypothesis_i::SetVerboseLevel(CORBA::Short level) - throw ( SALOME::SALOME_Exception ) -{ - if (level < 0 || level > 10 ) - THROW_SALOME_CORBA_EXCEPTION( "Invalid verbose level, valid range is [0-10]", - SALOME::BAD_PARAM ); - ASSERT(myBaseImpl); - this->GetImpl()->SetVerboseLevel(level); - SMESH::TPythonDump() << _this() << ".SetVerboseLevel( " << level << " )"; -} - -//======================================================================= -//function : GetVerboseLevel -//======================================================================= - -CORBA::Short GHS3DPlugin_Hypothesis_i::GetVerboseLevel() -{ - ASSERT(myBaseImpl); - return this->GetImpl()->GetVerboseLevel(); -} - -//======================================================================= -//function : SetToCreateNewNodes -//======================================================================= - -void GHS3DPlugin_Hypothesis_i::SetToCreateNewNodes(CORBA::Boolean toCreate) -{ - ASSERT(myBaseImpl); - this->GetImpl()->SetToCreateNewNodes(toCreate); - SMESH::TPythonDump() << _this() << ".SetToCreateNewNodes( " << toCreate << " )"; -} - -//======================================================================= -//function : GetToCreateNewNodes -//======================================================================= - -CORBA::Boolean GHS3DPlugin_Hypothesis_i::GetToCreateNewNodes() -{ - ASSERT(myBaseImpl); - return this->GetImpl()->GetToCreateNewNodes(); -} - -//======================================================================= -//function : SetToUseBoundaryRecoveryVersion -//======================================================================= - -void GHS3DPlugin_Hypothesis_i::SetToUseBoundaryRecoveryVersion(CORBA::Boolean toUse) -{ - ASSERT(myBaseImpl); - this->GetImpl()->SetToUseBoundaryRecoveryVersion(toUse); - SMESH::TPythonDump() << _this() << ".SetToUseBoundaryRecoveryVersion( " << toUse << " )"; -} - -//======================================================================= -//function : GetToUseBoundaryRecoveryVersion -//======================================================================= - -CORBA::Boolean GHS3DPlugin_Hypothesis_i::GetToUseBoundaryRecoveryVersion() -{ - ASSERT(myBaseImpl); - return this->GetImpl()->GetToUseBoundaryRecoveryVersion(); -} - -//======================================================================= -//function : SetTextOption -//======================================================================= - -void GHS3DPlugin_Hypothesis_i::SetTextOption(const char* option) -{ - ASSERT(myBaseImpl); - this->GetImpl()->SetTextOption(option); - SMESH::TPythonDump() << _this() << ".SetTextOption( '" << option << "' )"; -} - -//======================================================================= -//function : GetTextOption -//======================================================================= - -char* GHS3DPlugin_Hypothesis_i::GetTextOption() -{ - ASSERT(myBaseImpl); - return CORBA::string_dup( this->GetImpl()->GetTextOption().c_str() ); -} - -//============================================================================= -/*! - * Get implementation - */ -//============================================================================= - -::GHS3DPlugin_Hypothesis* GHS3DPlugin_Hypothesis_i::GetImpl() -{ - return (::GHS3DPlugin_Hypothesis*)myBaseImpl; -} - -//================================================================================ -/*! - * \brief Verify whether hypothesis supports given entity type - */ -//================================================================================ - -CORBA::Boolean GHS3DPlugin_Hypothesis_i::IsDimSupported( SMESH::Dimension type ) -{ - return type == SMESH::DIM_3D; -} - diff --git a/src/GHS3DPlugin_Hypothesis_i.hxx b/src/GHS3DPlugin_Hypothesis_i.hxx deleted file mode 100644 index 60704e4..0000000 --- a/src/GHS3DPlugin_Hypothesis_i.hxx +++ /dev/null @@ -1,118 +0,0 @@ -// Copyright (C) 2004-2008 CEA/DEN, EDF R&D -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License. -// -// 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 -// -// GHS3DPlugin : C++ implementation -// File : GHS3DPlugin_Hypothesis_i.hxx -// Date : 03/04/2006 -// Project : SALOME -// -#ifndef _GHS3DPlugin_Hypothesis_i_HXX_ -#define _GHS3DPlugin_Hypothesis_i_HXX_ - -#include "GHS3DPlugin_Defs.hxx" - -#include -#include CORBA_SERVER_HEADER(GHS3DPlugin_Algorithm) - -#include "SMESH_Hypothesis_i.hxx" -#include "GHS3DPlugin_Hypothesis.hxx" - -class SMESH_Gen; - -// GHS3DPlugin parameters hypothesis - -class GHS3DPLUGIN_EXPORT GHS3DPlugin_Hypothesis_i: - public virtual POA_GHS3DPlugin::GHS3DPlugin_Hypothesis, - public virtual SMESH_Hypothesis_i -{ - public: - // Constructor - GHS3DPlugin_Hypothesis_i (PortableServer::POA_ptr thePOA, - int theStudyId, - ::SMESH_Gen* theGenImpl); - // Destructor - virtual ~GHS3DPlugin_Hypothesis_i(); - - /*! - * To mesh "holes" in a solid or not. Default is to mesh. - */ - void SetToMeshHoles(CORBA::Boolean toMesh); - CORBA::Boolean GetToMeshHoles(); - /*! - * Maximal size of memory to be used by the algorithm (in Megabytes) - */ - void SetMaximumMemory(CORBA::Short MB) throw ( SALOME::SALOME_Exception ); - CORBA::Short GetMaximumMemory(); - /*! - * Initial size of memory to be used by the algorithm (in Megabytes) in - * automatic memory adjustment mode. Default is zero - */ - void SetInitialMemory(CORBA::Short MB) throw ( SALOME::SALOME_Exception ); - CORBA::Short GetInitialMemory(); - /*! - * Optimization level: 0-none, 1-light, 2-medium, 3-strong. Default is medium - */ - void SetOptimizationLevel(CORBA::Short level) throw ( SALOME::SALOME_Exception ); - CORBA::Short GetOptimizationLevel(); - /*! - * Path to working directory - */ - void SetWorkingDirectory(const char* path) throw ( SALOME::SALOME_Exception ); - char* GetWorkingDirectory(); - /*! - * To keep working files or remove them. Log file remains in case of errors anyway. - */ - void SetKeepFiles(CORBA::Boolean toKeep); - CORBA::Boolean GetKeepFiles(); - /*! - * Verbose level [0-10] - * 0 - no standard output, - * 2 - prints the data, quality statistics of the skin and final meshes and - * indicates when the final mesh is being saved. In addition the software - * gives indication regarding the CPU time. - * 10 - same as 2 plus the main steps in the computation, quality statistics - * histogram of the skin mesh, quality statistics histogram together with - * the characteristics of the final mesh. - */ - void SetVerboseLevel(CORBA::Short level) throw ( SALOME::SALOME_Exception ); - CORBA::Short GetVerboseLevel(); - /*! - * To create new nodes - */ - void SetToCreateNewNodes(CORBA::Boolean toCreate); - CORBA::Boolean GetToCreateNewNodes(); - /*! - * To use boundary recovery version which tries to create mesh on a very poor - * quality surface mesh - */ - void SetToUseBoundaryRecoveryVersion(CORBA::Boolean toUse); - CORBA::Boolean GetToUseBoundaryRecoveryVersion(); - /*! - * To set hiden/undocumented/advanced options - */ - void SetTextOption(const char* option); - char* GetTextOption(); - - // Get implementation - ::GHS3DPlugin_Hypothesis* GetImpl(); - - // Verify whether hypothesis supports given entity type - CORBA::Boolean IsDimSupported( SMESH::Dimension type ); -}; - -#endif diff --git a/src/GUI/GHS3DPluginGUI.cxx b/src/GUI/GHS3DPluginGUI.cxx new file mode 100644 index 0000000..905c9b3 --- /dev/null +++ b/src/GUI/GHS3DPluginGUI.cxx @@ -0,0 +1,42 @@ +// Copyright (C) 2007-2012 CEA/DEN, EDF R&D +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// 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 : GHS3DPluginGUI.cxx +// Authors : Gilles DAVID (Euriware) +// --- +// +#include "GHS3DPluginGUI_HypothesisCreator.h" + +//============================================================================= +/*! GetHypothesisCreator + * + */ +//============================================================================= +extern "C" +{ + GHS3DPLUGINGUI_EXPORT + SMESHGUI_GenericHypothesisCreator* GetHypothesisCreator( const QString& aHypType ) + { + SMESHGUI_GenericHypothesisCreator* aCreator = NULL; + if ( aHypType == "GHS3D_Parameters" ) + aCreator = new GHS3DPluginGUI_HypothesisCreator( aHypType ); + return aCreator; + } +} diff --git a/src/GUI/GHS3DPluginGUI_Enums.h b/src/GUI/GHS3DPluginGUI_Enums.h new file mode 100644 index 0000000..8516565 --- /dev/null +++ b/src/GUI/GHS3DPluginGUI_Enums.h @@ -0,0 +1,84 @@ +// Copyright (C) 2004-2012 CEA/DEN, EDF R&D +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// 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 +// + +// GHS3DPlugin GUI: GUI for plugged-in mesher GHS3DPlugin +// File : GHS3DPluginGUI_Enums.h +// Author : Gilles DAVID (Euriware) +// Module : GHS3DPlugin +// +#ifndef GHS3DPLUGINGUI_Enums_HeaderFile +#define GHS3DPLUGINGUI_Enums_HeaderFile + +// tabs +enum { + STD_TAB = 0, + ADV_TAB, + ENF_VER_TAB, + ENF_MESH_TAB +}; + +// Enforced vertices array columns +enum { + ENF_VER_NAME_COLUMN = 0, + ENF_VER_X_COLUMN, + ENF_VER_Y_COLUMN, + ENF_VER_Z_COLUMN, + ENF_VER_SIZE_COLUMN, + ENF_VER_ENTRY_COLUMN, + ENF_VER_COMPOUND_COLUMN, + ENF_VER_GROUP_COLUMN, + ENF_VER_NB_COLUMNS +}; + +// Enforced meshes array columns +enum { + ENF_MESH_NAME_COLUMN = 0, + ENF_MESH_ENTRY_COLUMN, + ENF_MESH_CONSTRAINT_COLUMN, + ENF_MESH_SIZE_COLUMN, + ENF_MESH_GROUP_COLUMN, + ENF_MESH_NB_COLUMNS +}; + +// Enforced vertices widget inputs +enum { + ENF_VER_WARNING = 0, + ENF_VER_VERTEX /*= 0*/, + ENF_VER_X_COORD, + ENF_VER_Y_COORD, + ENF_VER_Z_COORD, + ENF_VER_SIZE, + ENF_VER_GROUP, + ENF_VER_BTN, + ENF_VER_NB_LINES +}; + +// Enforced meshes widget inputs +enum { + ENF_MESH_WARNING = 0, + ENF_MESH_MESH /*= 0*/, + ENF_MESH_CONSTRAINT, + ENF_MESH_SIZE, + ENF_MESH_GROUP, + ENF_MESH_BTN, + ENF_MESH_NB_LINES +}; + + +#endif diff --git a/src/GUI/GHS3DPluginGUI_HypothesisCreator.cxx b/src/GUI/GHS3DPluginGUI_HypothesisCreator.cxx index 411036e..6c097cc 100644 --- a/src/GUI/GHS3DPluginGUI_HypothesisCreator.cxx +++ b/src/GUI/GHS3DPluginGUI_HypothesisCreator.cxx @@ -1,21 +1,22 @@ -// Copyright (C) 2004-2008 CEA/DEN, EDF R&D +// Copyright (C) 2004-2012 CEA/DEN, EDF R&D // -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License. +// 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. +// 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 +// 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 +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // + // GHS3DPlugin GUI: GUI for plugged-in mesher GHS3DPlugin // File : GHS3DPluginGUI_HypothesisCreator.cxx // Author : Michael Zorin @@ -23,44 +24,74 @@ // $Header: // #include "GHS3DPluginGUI_HypothesisCreator.h" +// #include "GHS3DPluginGUI_EnforcedDelegates.h" +#include "GHS3DPluginGUI_Enums.h" + +#include "GeometryGUI.h" #include +#include #include +#include +#include +#include -#include CORBA_SERVER_HEADER(GHS3DPlugin_Algorithm) - -#include +#include #include -#include +#include #include +#include #include +#include + +#include -#include #include +#include +#include #include -#include #include +#include #include #include #include #include #include #include +#include + +#include +#include +#include -enum { - STD_TAB = 0, - ADV_TAB -}; +#include +#include + +#include namespace { -#ifndef WIN32 +#ifdef WIN32 +#include +#else #include #endif int maxAvailableMemory() { -#ifndef WIN32 +#ifdef WIN32 + // See http://msdn.microsoft.com/en-us/library/aa366589.aspx + MEMORYSTATUSEX statex; + statex.dwLength = sizeof (statex); + int err = GlobalMemoryStatusEx (&statex); + if (err != 0) { + int totMB = + statex.ullTotalPhys / 1024 / 1024 + + statex.ullTotalPageFile / 1024 / 1024 + + statex.ullTotalVirtual / 1024 / 1024; + return (int) ( 0.7 * totMB ); + } +#else struct sysinfo si; int err = sysinfo( &si ); if ( err == 0 ) { @@ -70,17 +101,284 @@ namespace { return (int) ( 0.7 * totMB ); } #endif - return 100000; + return 0; } } +// +// BEGIN EnforcedVertexTableWidgetDelegate +// + +EnforcedVertexTableWidgetDelegate::EnforcedVertexTableWidgetDelegate(QObject *parent) + : QItemDelegate(parent) +{ +} + +QWidget *EnforcedVertexTableWidgetDelegate::createEditor(QWidget *parent, + const QStyleOptionViewItem & option , + const QModelIndex & index ) const +{ + QModelIndex father = index.parent(); + QString entry = father.child(index.row(), ENF_VER_ENTRY_COLUMN).data().toString(); + + if (index.column() == ENF_VER_X_COLUMN || + index.column() == ENF_VER_Y_COLUMN || + index.column() == ENF_VER_Z_COLUMN || + index.column() == ENF_VER_SIZE_COLUMN) { + SMESHGUI_SpinBox *editor = new SMESHGUI_SpinBox(parent); + if (index.column() == ENF_VER_SIZE_COLUMN) + editor->RangeStepAndValidator(0, COORD_MAX, 10.0, "length_precision"); + else + editor->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, "length_precision"); + editor->setReadOnly(!entry.isEmpty()); + editor->setDisabled(!entry.isEmpty()); + return editor; + } +// else if (index.column() == ENF_VER_COMPOUND_COLUMN) { +// QCheckBox *editor = new QCheckBox(parent); +// editor->setDisabled(!entry.isEmpty()); +// return editor; +// } + else if (index.column() == ENF_VER_GROUP_COLUMN || + index.column() == ENF_VER_NAME_COLUMN) { +// else { + QLineEdit *editor = new QLineEdit(parent); + if (index.column() != ENF_VER_GROUP_COLUMN) { + editor->setReadOnly(!entry.isEmpty()); + editor->setDisabled(!entry.isEmpty()); + } + return editor; + } + return QItemDelegate::createEditor(parent, option, index); +} + +void EnforcedVertexTableWidgetDelegate::setEditorData(QWidget *editor, + const QModelIndex &index) const +{ + if (index.column() == ENF_VER_X_COLUMN || + index.column() == ENF_VER_Y_COLUMN || + index.column() == ENF_VER_Z_COLUMN || + index.column() == ENF_VER_SIZE_COLUMN) + { + SMESHGUI_SpinBox *lineEdit = qobject_cast(editor); + lineEdit->SetValue(index.data().toDouble()); + } + else if (index.column() == ENF_VER_COMPOUND_COLUMN) { + QCheckBox *checkBox = qobject_cast(editor); + checkBox->setChecked(index.data().toBool()); + } + else { + QItemDelegate::setEditorData(editor, index); + } +} + +void EnforcedVertexTableWidgetDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, + const QModelIndex &index) const +{ + QModelIndex parent = index.parent(); + + QString entry = parent.child(index.row(), ENF_VER_ENTRY_COLUMN).data().toString(); + bool isCompound = parent.child(index.row(), ENF_VER_COMPOUND_COLUMN).data(Qt::CheckStateRole).toBool(); + + if (index.column() == ENF_VER_X_COLUMN || + index.column() == ENF_VER_Y_COLUMN || + index.column() == ENF_VER_Z_COLUMN) { + SMESHGUI_SpinBox *lineEdit = qobject_cast(editor); + if (!isCompound && !vertexExists(model, index, lineEdit->GetString())) + model->setData(index, lineEdit->GetValue(), Qt::EditRole); + } + else if (index.column() == ENF_VER_SIZE_COLUMN) + { + SMESHGUI_SpinBox *lineEdit = qobject_cast(editor); + const double newsize = lineEdit->GetValue(); + if (newsize > 0) + model->setData(index, newsize, Qt::EditRole); + } + else if (index.column() == ENF_VER_NAME_COLUMN) { + QLineEdit *lineEdit = qobject_cast(editor); + QString value = lineEdit->text(); + if (entry.isEmpty() && !vertexExists(model, index, value)) + model->setData(index, value, Qt::EditRole); + } + else if (index.column() == ENF_VER_ENTRY_COLUMN) { + QLineEdit *lineEdit = qobject_cast(editor); + QString value = lineEdit->text(); + if (! vertexExists(model, index, value)) + model->setData(index, value, Qt::EditRole); + } + else if (index.column() == ENF_VER_COMPOUND_COLUMN) { + QCheckBox *checkBox = qobject_cast(editor); + model->setData(index, checkBox->isChecked(), Qt::CheckStateRole); + } + else { + QItemDelegate::setModelData(editor, model, index); + } +} + +void EnforcedVertexTableWidgetDelegate::updateEditorGeometry(QWidget *editor, + const QStyleOptionViewItem &option, const QModelIndex &/* index */) const +{ + editor->setGeometry(option.rect); +} + +bool EnforcedVertexTableWidgetDelegate::vertexExists(QAbstractItemModel *model, + const QModelIndex &index, + QString value) const +{ + bool exists = false; + QModelIndex parent = index.parent(); + int row = index.row(); + int col = index.column(); + + if (parent.isValid() && !value.isEmpty()) { + if (col == ENF_VER_X_COLUMN || col == ENF_VER_Y_COLUMN || col == ENF_VER_Z_COLUMN) { + double x, y, z; + if (col == ENF_VER_X_COLUMN) { + x = value.toDouble(); + y = parent.child(row, ENF_VER_Y_COLUMN).data().toDouble(); + z = parent.child(row, ENF_VER_Z_COLUMN).data().toDouble(); + } + if (col == ENF_VER_Y_COLUMN) { + y = value.toDouble(); + x = parent.child(row, ENF_VER_X_COLUMN).data().toDouble(); + z = parent.child(row, ENF_VER_Z_COLUMN).data().toDouble(); + } + if (col == ENF_VER_Z_COLUMN) { + z = value.toDouble(); + x = parent.child(row, ENF_VER_X_COLUMN).data().toDouble(); + y = parent.child(row, ENF_VER_Y_COLUMN).data().toDouble(); + } + int nbChildren = model->rowCount(parent); + for (int i = 0 ; i < nbChildren ; i++) { + if (i != row) { + double childX = parent.child(i, ENF_VER_X_COLUMN).data().toDouble(); + double childY = parent.child(i, ENF_VER_Y_COLUMN).data().toDouble(); + double childZ = parent.child(i, ENF_VER_Z_COLUMN).data().toDouble(); + if ((childX == x) && (childY == y) && (childZ == z)) { + exists = true; + break; + } + } + } + } + else if (col == ENF_VER_NAME_COLUMN) { + QString name = parent.child(row, ENF_VER_NAME_COLUMN).data().toString(); + if (name == value) + exists = true; + } + } + + return exists; +} + +// +// END EnforcedVertexTableWidgetDelegate +// + +// +// BEGIN EnforcedMeshTableWidgetDelegate +// + +EnforcedMeshTableWidgetDelegate::EnforcedMeshTableWidgetDelegate(QObject *parent) + : QItemDelegate(parent) +{ +} + +QWidget *EnforcedMeshTableWidgetDelegate::createEditor(QWidget *parent, + const QStyleOptionViewItem & option , + const QModelIndex & index ) const +{ + if (index.column() == ENF_MESH_SIZE_COLUMN) { + SMESHGUI_SpinBox *editor = new SMESHGUI_SpinBox(parent); + editor->RangeStepAndValidator(0, COORD_MAX, 10.0, "length_precision"); + return editor; + } + return QItemDelegate::createEditor(parent, option, index); +} + +void EnforcedMeshTableWidgetDelegate::setEditorData(QWidget *editor, + const QModelIndex &index) const +{ + if (index.column() == ENF_MESH_SIZE_COLUMN) { + SMESHGUI_SpinBox *spinBox = qobject_cast(editor); + spinBox->SetValue(index.data().toDouble()); + } + else + QItemDelegate::setEditorData(editor, index); +} + +void EnforcedMeshTableWidgetDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, + const QModelIndex &index) const +{ + if (index.column() == ENF_MESH_SIZE_COLUMN) + { + SMESHGUI_SpinBox *spinBox = qobject_cast(editor); + const double newsize = spinBox->GetValue(); + if (newsize > 0) + model->setData(index, newsize, Qt::EditRole); + } + else + QItemDelegate::setModelData(editor, model, index); + +} + +void EnforcedMeshTableWidgetDelegate::updateEditorGeometry(QWidget *editor, + const QStyleOptionViewItem &option, const QModelIndex &/* index */) const +{ + editor->setGeometry(option.rect); +} + +// bool EnforcedMeshTableWidgetDelegate::enfMeshExists(QAbstractItemModel *model, +// const QModelIndex &index, +// QString value) const +// { +// bool exists = false; +// QModelIndex parent = index.parent(); +// int row = index.row(); +// int col = index.column(); +// return exists; +// } + +// +// END EnforcedMeshTableWidgetDelegate +// + + GHS3DPluginGUI_HypothesisCreator::GHS3DPluginGUI_HypothesisCreator( const QString& theHypType ) : SMESHGUI_GenericHypothesisCreator( theHypType ) { + GeomToolSelected = NULL; + GeomToolSelected = getGeomSelectionTool(); + + iconVertex = QPixmap(SUIT_Session::session()->resourceMgr()->loadPixmap("GEOM", tr("ICON_OBJBROWSER_VERTEX"))); + iconCompound = QPixmap(SUIT_Session::session()->resourceMgr()->loadPixmap("GEOM", tr("ICON_OBJBROWSER_COMPOUND"))); +// mySelectionMgr = SMESH::GetSelectionMgr(SMESHGUI::GetSMESHGUI()); + myEnfMeshConstraintLabels << tr( "GHS3D_ENF_MESH_CONSTRAINT_NODE" ) << tr( "GHS3D_ENF_MESH_CONSTRAINT_EDGE" ) << tr("GHS3D_ENF_MESH_CONSTRAINT_FACE"); } GHS3DPluginGUI_HypothesisCreator::~GHS3DPluginGUI_HypothesisCreator() { + GHS3DPluginGUI_HypothesisCreator* that = (GHS3DPluginGUI_HypothesisCreator*)this; + that->getGeomSelectionTool()->selectionMgr()->clearFilters(); + myEnfMeshWdg->deactivateSelection(); +} + +/** + * \brief {Get or create the geom selection tool for active study} + * */ +GeomSelectionTools* GHS3DPluginGUI_HypothesisCreator::getGeomSelectionTool() +{ + GHS3DPluginGUI_HypothesisCreator* that = (GHS3DPluginGUI_HypothesisCreator*)this; + _PTR(Study) aStudy = SMESH::GetActiveStudyDocument(); + if (that->GeomToolSelected == NULL || that->GeomToolSelected->getMyStudy() != aStudy) { + that->GeomToolSelected = new GeomSelectionTools(aStudy); + } + return that->GeomToolSelected; +} + +GEOM::GEOM_Gen_var GHS3DPluginGUI_HypothesisCreator::getGeomEngine() +{ + return GeometryGUI::GetGeomGen(); } QFrame* GHS3DPluginGUI_HypothesisCreator::buildFrame() @@ -114,15 +412,15 @@ QFrame* GHS3DPluginGUI_HypothesisCreator::buildFrame() myToMeshHolesCheck = new QCheckBox( tr( "GHS3D_TO_MESH_HOLES" ), myStdGroup ); aStdLayout->addWidget( myToMeshHolesCheck, row++, 0, 1, 2 ); - aStdLayout->addWidget( new QLabel( tr( "GHS3D_OPTIMIZATIOL_LEVEL" ), myStdGroup ), row, 0 ); + aStdLayout->addWidget( new QLabel( tr( "GHS3D_OPTIMIZATIOL_LEVEL" ), myStdGroup ), row, 0, 1, 1 ); myOptimizationLevelCombo = new QComboBox( myStdGroup ); aStdLayout->addWidget( myOptimizationLevelCombo, row++, 1, 1, 1 ); QStringList types; - types << tr( "LEVEL_NONE" ) << tr( "LEVEL_LIGHT" ) << tr( "LEVEL_MEDIUM" ) << tr( "LEVEL_STRONG" ); + types << tr( "LEVEL_NONE" ) << tr( "LEVEL_LIGHT" ) << tr( "LEVEL_MEDIUM" ) << tr( "LEVEL_STANDARDPLUS" ) << tr( "LEVEL_STRONG" ); myOptimizationLevelCombo->addItems( types ); - aStdLayout->setRowStretch( row, 5 ); + aStdLayout->setRowStretch( row, 10 ); // advanced parameters myAdvGroup = new QWidget(); @@ -160,31 +458,208 @@ QFrame* GHS3DPluginGUI_HypothesisCreator::buildFrame() myToCreateNewNodesCheck = new QCheckBox( tr( "TO_ADD_NODES" ), myAdvGroup ); + myRemoveInitialCentralPointCheck = new QCheckBox( tr( "NO_INITIAL_CENTRAL_POINT" ), myAdvGroup ); + myBoundaryRecoveryCheck = new QCheckBox( tr( "RECOVERY_VERSION" ), myAdvGroup ); + + myFEMCorrectionCheck = new QCheckBox( tr( "FEM_CORRECTION" ), myAdvGroup ); QLabel* aTextOptionLabel = new QLabel( tr( "TEXT_OPTION" ), myAdvGroup ); myTextOption = new QLineEdit( myAdvGroup ); - anAdvLayout->addWidget( myMaximumMemoryCheck, 0, 0, 1, 1 ); - anAdvLayout->addWidget( myMaximumMemorySpin, 0, 1, 1, 1 ); - anAdvLayout->addWidget( aMegabyteLabel, 0, 2, 1, 1 ); - anAdvLayout->addWidget( myInitialMemoryCheck, 1, 0, 1, 1 ); - anAdvLayout->addWidget( myInitialMemorySpin, 1, 1, 1, 1 ); - anAdvLayout->addWidget( aMegabyteLabel2, 1, 2, 1, 1 ); - anAdvLayout->addWidget( aWorkinDirLabel, 2, 0, 1, 1 ); - anAdvLayout->addWidget( myWorkingDir, 2, 1, 1, 2 ); - anAdvLayout->addWidget( dirBtn, 2, 3, 1, 1 ); - anAdvLayout->addWidget( myKeepFiles, 3, 0, 1, 4 ); - anAdvLayout->addWidget( aVerboseLevelLabel, 4, 0, 1, 1 ); - anAdvLayout->addWidget( myVerboseLevelSpin, 4, 1, 1, 1 ); - anAdvLayout->addWidget( myToCreateNewNodesCheck, 5, 0, 1, 4 ); - anAdvLayout->addWidget( myBoundaryRecoveryCheck, 6, 0, 1, 4 ); - anAdvLayout->addWidget( aTextOptionLabel, 7, 0, 1, 1 ); - anAdvLayout->addWidget( myTextOption, 7, 1, 1, 2 ); + anAdvLayout->addWidget( myMaximumMemoryCheck, 0, 0, 1, 1 ); + anAdvLayout->addWidget( myMaximumMemorySpin, 0, 1, 1, 1 ); + anAdvLayout->addWidget( aMegabyteLabel, 0, 2, 1, 1 ); + anAdvLayout->addWidget( myInitialMemoryCheck, 1, 0, 1, 1 ); + anAdvLayout->addWidget( myInitialMemorySpin, 1, 1, 1, 1 ); + anAdvLayout->addWidget( aMegabyteLabel2, 1, 2, 1, 1 ); + anAdvLayout->addWidget( aWorkinDirLabel, 2, 0, 1, 1 ); + anAdvLayout->addWidget( myWorkingDir, 2, 1, 1, 2 ); + anAdvLayout->addWidget( dirBtn, 2, 3, 1, 1 ); + anAdvLayout->addWidget( myKeepFiles, 3, 0, 1, 4 ); + anAdvLayout->addWidget( aVerboseLevelLabel, 4, 0, 1, 1 ); + anAdvLayout->addWidget( myVerboseLevelSpin, 4, 1, 1, 1 ); + anAdvLayout->addWidget( myToCreateNewNodesCheck, 5, 0, 1, 4 ); + anAdvLayout->addWidget( myRemoveInitialCentralPointCheck, 6, 0, 1, 4 ); + anAdvLayout->addWidget( myBoundaryRecoveryCheck, 7, 0, 1, 4 ); + anAdvLayout->addWidget( myFEMCorrectionCheck, 8, 0, 1, 4 ); + anAdvLayout->addWidget( aTextOptionLabel, 9, 0, 1, 1 ); + anAdvLayout->addWidget( myTextOption, 9, 1, 1, 2 ); + + // Enforced vertices parameters + myEnfGroup = new QWidget(); + QGridLayout* anEnfLayout = new QGridLayout(myEnfGroup); + + myEnforcedTableWidget = new QTableWidget(myEnfGroup); + myEnforcedTableWidget ->setMinimumWidth(300); + myEnforcedTableWidget->setRowCount( 0 ); + myEnforcedTableWidget->setColumnCount( ENF_VER_NB_COLUMNS ); + myEnforcedTableWidget->setSortingEnabled(true); + QStringList enforcedHeaders; + enforcedHeaders << tr( "GHS3D_ENF_NAME_COLUMN" ) + << tr( "GHS3D_ENF_VER_X_COLUMN" )<< tr( "GHS3D_ENF_VER_Y_COLUMN" ) << tr( "GHS3D_ENF_VER_Z_COLUMN" ) + << tr( "GHS3D_ENF_SIZE_COLUMN" ) << tr("GHS3D_ENF_ENTRY_COLUMN") << tr("GHS3D_ENF_VER_COMPOUND_COLUMN") << tr( "GHS3D_ENF_GROUP_COLUMN" ); + + myEnforcedTableWidget->setHorizontalHeaderLabels(enforcedHeaders); + myEnforcedTableWidget->verticalHeader()->hide(); + myEnforcedTableWidget->horizontalHeader()->setStretchLastSection(true); + myEnforcedTableWidget->setAlternatingRowColors(true); + myEnforcedTableWidget->setSelectionMode(QAbstractItemView::ExtendedSelection); + myEnforcedTableWidget->setSelectionBehavior(QAbstractItemView::SelectItems); + myEnforcedTableWidget->horizontalHeader()->setResizeMode(QHeaderView::Interactive); + myEnforcedTableWidget->resizeColumnsToContents(); + myEnforcedTableWidget->hideColumn(ENF_VER_ENTRY_COLUMN); + myEnforcedTableWidget->hideColumn(ENF_VER_COMPOUND_COLUMN); + + myEnforcedTableWidget->setItemDelegate(new EnforcedVertexTableWidgetDelegate()); + +// VERTEX SELECTION + TColStd_MapOfInteger shapeTypes; + shapeTypes.Add( TopAbs_VERTEX ); + shapeTypes.Add( TopAbs_COMPOUND ); + + SMESH_NumberFilter* vertexFilter = new SMESH_NumberFilter("GEOM", TopAbs_SHAPE, 1, shapeTypes); + myEnfVertexWdg = new StdMeshersGUI_ObjectReferenceParamWdg( vertexFilter, 0, /*multiSel=*/true, /*stretch=*/false); + myEnfVertexWdg->SetDefaultText(tr("GHS3D_ENF_SELECT_VERTEX"), "QLineEdit { color: grey }"); + + QLabel* myXCoordLabel = new QLabel( tr( "GHS3D_ENF_VER_X_LABEL" ), myEnfGroup ); + myXCoord = new SMESHGUI_SpinBox(myEnfGroup); + myXCoord->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, "length_precision"); + QLabel* myYCoordLabel = new QLabel( tr( "GHS3D_ENF_VER_Y_LABEL" ), myEnfGroup ); + myYCoord = new SMESHGUI_SpinBox(myEnfGroup); + myYCoord->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, "length_precision"); + QLabel* myZCoordLabel = new QLabel( tr( "GHS3D_ENF_VER_Z_LABEL" ), myEnfGroup ); + myZCoord = new SMESHGUI_SpinBox(myEnfGroup); + myZCoord->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, "length_precision"); + QLabel* mySizeLabel = new QLabel( tr( "GHS3D_ENF_SIZE_LABEL" ), myEnfGroup ); + mySizeValue = new SMESHGUI_SpinBox(myEnfGroup); + mySizeValue->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, "length_precision"); + + QLabel* myGroupNameLabel = new QLabel( tr( "GHS3D_ENF_GROUP_LABEL" ), myEnfGroup ); + myGroupName = new QLineEdit(myEnfGroup); + + addVertexButton = new QPushButton(tr("GHS3D_ENF_ADD"),myEnfGroup); + addVertexButton->setEnabled(false); + removeVertexButton = new QPushButton(tr("GHS3D_ENF_REMOVE"),myEnfGroup); +// myGlobalGroupName = new QCheckBox(tr("GHS3D_ENF_VER_GROUPS"), myEnfGroup); +// myGlobalGroupName->setChecked(false); + + QGroupBox* GroupBox = new QGroupBox( myEnfGroup ); + QLabel* info = new QLabel( GroupBox ); + info->setText( tr( "GHS3D_ENF_VER_INFO" ) ); + info->setWordWrap( true ); + QVBoxLayout* GroupBoxVLayout = new QVBoxLayout( GroupBox ); + GroupBoxVLayout->setSpacing( 6 ); + GroupBoxVLayout->setMargin( 11 ); + GroupBoxVLayout->addWidget( info ); + + + anEnfLayout->addWidget(GroupBox, ENF_VER_WARNING, 0, 1, 2 ); + anEnfLayout->addWidget(myEnforcedTableWidget, ENF_VER_VERTEX, 0, ENF_VER_NB_LINES, 1); + + QGridLayout* anEnfLayout2 = new QGridLayout(myEnfGroup); + anEnfLayout2->addWidget(myEnfVertexWdg, ENF_VER_VERTEX, 0, 1, 2); + anEnfLayout2->addWidget(myXCoordLabel, ENF_VER_X_COORD, 0, 1, 1); + anEnfLayout2->addWidget(myXCoord, ENF_VER_X_COORD, 1, 1, 1); + anEnfLayout2->addWidget(myYCoordLabel, ENF_VER_Y_COORD, 0, 1, 1); + anEnfLayout2->addWidget(myYCoord, ENF_VER_Y_COORD, 1, 1, 1); + anEnfLayout2->addWidget(myZCoordLabel, ENF_VER_Z_COORD, 0, 1, 1); + anEnfLayout2->addWidget(myZCoord, ENF_VER_Z_COORD, 1, 1, 1); + anEnfLayout2->addWidget(mySizeLabel, ENF_VER_SIZE, 0, 1, 1); + anEnfLayout2->addWidget(mySizeValue, ENF_VER_SIZE, 1, 1, 1); + anEnfLayout2->addWidget(myGroupNameLabel, ENF_VER_GROUP, 0, 1, 1); + anEnfLayout2->addWidget(myGroupName, ENF_VER_GROUP, 1, 1, 1); + anEnfLayout2->addWidget(addVertexButton, ENF_VER_BTN, 0, 1, 1); + anEnfLayout2->addWidget(removeVertexButton, ENF_VER_BTN, 1, 1, 1); + anEnfLayout2->setRowStretch(ENF_VER_NB_LINES, 1); + + anEnfLayout->addLayout(anEnfLayout2, ENF_VER_VERTEX, 1,ENF_VER_NB_LINES, 1); + anEnfLayout->setRowStretch(ENF_VER_VERTEX, 10); + + + // Enforced meshes parameters + myEnfMeshGroup = new QWidget(); + QGridLayout* anEnfMeshLayout = new QGridLayout(myEnfMeshGroup); + + myEnforcedMeshTableWidget = new QTableWidget(myEnfGroup); + myEnforcedMeshTableWidget->setRowCount( 0 ); + myEnforcedMeshTableWidget->setColumnCount( ENF_MESH_NB_COLUMNS ); + myEnforcedMeshTableWidget->setSortingEnabled(true); + myEnforcedMeshTableWidget->verticalHeader()->hide(); + QStringList enforcedMeshHeaders; + enforcedMeshHeaders << tr( "GHS3D_ENF_NAME_COLUMN" ) + << tr( "GHS3D_ENF_ENTRY_COLUMN" ) + << tr( "GHS3D_ENF_MESH_CONSTRAINT_COLUMN" ) + << tr( "GHS3D_ENF_SIZE_COLUMN" ) + << tr( "GHS3D_ENF_GROUP_COLUMN" ); + myEnforcedMeshTableWidget->setHorizontalHeaderLabels(enforcedMeshHeaders); + myEnforcedMeshTableWidget->horizontalHeader()->setStretchLastSection(true); + myEnforcedMeshTableWidget->horizontalHeader()->setResizeMode(QHeaderView::Interactive); + myEnforcedMeshTableWidget->setAlternatingRowColors(true); + myEnforcedMeshTableWidget->setSelectionMode(QAbstractItemView::ExtendedSelection); + myEnforcedMeshTableWidget->setSelectionBehavior(QAbstractItemView::SelectItems); + myEnforcedMeshTableWidget->resizeColumnsToContents(); + myEnforcedMeshTableWidget->hideColumn(ENF_MESH_ENTRY_COLUMN); + + myEnforcedMeshTableWidget->setItemDelegate(new EnforcedMeshTableWidgetDelegate()); + +// myEnfMesh = SMESH::SMESH_Mesh::_nil(); +// myEnfMeshArray = new SMESH::mesh_array(); + + myEnfMeshWdg = new StdMeshersGUI_ObjectReferenceParamWdg( IDSOURCE, myEnfMeshGroup, /*multiSel=*/true); + myEnfMeshWdg->SetDefaultText(tr("GHS3D_ENF_SELECT_MESH"), "QLineEdit { color: grey }"); + + myEnfMeshWdg->AvoidSimultaneousSelection(myEnfVertexWdg); + + QLabel* myMeshConstraintLabel = new QLabel( tr( "GHS3D_ENF_MESH_CONSTRAINT_LABEL" ), myEnfMeshGroup ); + myEnfMeshConstraint = new QComboBox(myEnfMeshGroup); + myEnfMeshConstraint->insertItems(0,myEnfMeshConstraintLabels); + myEnfMeshConstraint->setEditable(false); + myEnfMeshConstraint->setCurrentIndex(0); + + QLabel* myMeshSizeLabel = new QLabel( tr( "GHS3D_ENF_SIZE_LABEL" ), myEnfMeshGroup ); + myMeshSizeValue = new SMESHGUI_SpinBox(myEnfMeshGroup); + myMeshSizeValue->RangeStepAndValidator(0, COORD_MAX, 10.0, "length_precision"); + QLabel* myMeshGroupNameLabel = new QLabel( tr( "GHS3D_ENF_GROUP_LABEL" ), myEnfMeshGroup ); + myMeshGroupName = new QLineEdit(myEnfMeshGroup); + + addEnfMeshButton = new QPushButton(tr("GHS3D_ENF_ADD"),myEnfMeshGroup); +// addEnfMeshButton->setEnabled(false); + removeEnfMeshButton = new QPushButton(tr("GHS3D_ENF_REMOVE"),myEnfMeshGroup); + + QGroupBox* GroupBox2 = new QGroupBox( myEnfMeshGroup ); + QLabel* info2 = new QLabel( GroupBox2 ); + info2->setText( tr( "GHS3D_ENF_MESH_INFO" ) ); + info2->setWordWrap( true ); + QVBoxLayout* GroupBox2VLayout = new QVBoxLayout( GroupBox2 ); + GroupBox2VLayout->setSpacing( 6 ); + GroupBox2VLayout->setMargin( 11 ); + GroupBox2VLayout->addWidget( info2 ); + + anEnfMeshLayout->addWidget( GroupBox2, ENF_MESH_WARNING, 0, 1, 2 ); + anEnfMeshLayout->addWidget(myEnforcedMeshTableWidget, ENF_MESH_MESH, 0, ENF_MESH_NB_LINES , 1); + + QGridLayout* anEnfMeshLayout2 = new QGridLayout(myEnfMeshGroup); + anEnfMeshLayout2->addWidget(myEnfMeshWdg, ENF_MESH_MESH, 0, 1, 2); + anEnfMeshLayout2->addWidget(myMeshConstraintLabel, ENF_MESH_CONSTRAINT, 0, 1, 1); + anEnfMeshLayout2->addWidget(myEnfMeshConstraint, ENF_MESH_CONSTRAINT, 1, 1, 1); + anEnfMeshLayout2->addWidget(myMeshSizeLabel, ENF_MESH_SIZE, 0, 1, 1); + anEnfMeshLayout2->addWidget(myMeshSizeValue, ENF_MESH_SIZE, 1, 1, 1); + anEnfMeshLayout2->addWidget(myMeshGroupNameLabel, ENF_MESH_GROUP, 0, 1, 1); + anEnfMeshLayout2->addWidget(myMeshGroupName, ENF_MESH_GROUP, 1, 1, 1); + anEnfMeshLayout2->addWidget(addEnfMeshButton, ENF_MESH_BTN, 0, 1, 1); + anEnfMeshLayout2->addWidget(removeEnfMeshButton, ENF_MESH_BTN, 1, 1, 1); + anEnfMeshLayout2->setRowStretch(ENF_MESH_NB_LINES, 1); + + anEnfMeshLayout->addLayout(anEnfMeshLayout2, ENF_MESH_MESH, 1, ENF_MESH_NB_LINES, 1); + anEnfMeshLayout->setRowStretch(ENF_MESH_MESH, 10); + // add tabs tab->insertTab( STD_TAB, myStdGroup, tr( "SMESH_ARGUMENTS" ) ); tab->insertTab( ADV_TAB, myAdvGroup, tr( "GHS3D_ADV_ARGS" ) ); + tab->insertTab( ENF_VER_TAB, myEnfGroup, tr( "GHS3D_ENFORCED_VERTICES" ) ); + tab->insertTab( ENF_MESH_TAB, myEnfMeshGroup, tr( "GHS3D_ENFORCED_MESHES" ) ); tab->setCurrentIndex( STD_TAB ); // connections @@ -192,10 +667,758 @@ QFrame* GHS3DPluginGUI_HypothesisCreator::buildFrame() connect( myInitialMemoryCheck, SIGNAL( toggled( bool ) ), this, SLOT( updateWidgets() ) ); connect( myBoundaryRecoveryCheck, SIGNAL( toggled( bool ) ), this, SLOT( updateWidgets() ) ); connect( dirBtn, SIGNAL( clicked() ), this, SLOT( onDirBtnClicked() ) ); + connect( myEnforcedTableWidget, SIGNAL( itemClicked(QTableWidgetItem *)), this, SLOT( synchronizeCoords() ) ); + connect( myEnforcedTableWidget, SIGNAL( itemChanged(QTableWidgetItem *)), this, SLOT( updateEnforcedVertexValues(QTableWidgetItem *) ) ); + connect( myEnforcedTableWidget, SIGNAL( itemSelectionChanged() ), this, SLOT( synchronizeCoords() ) ); + connect( addVertexButton, SIGNAL( clicked()), this, SLOT( onAddEnforcedVertex() ) ); + connect( removeVertexButton, SIGNAL( clicked()), this, SLOT( onRemoveEnforcedVertex() ) ); + connect( myEnfVertexWdg, SIGNAL( contentModified()), this, SLOT( onSelectEnforcedVertex() ) ); + connect( myEnfVertexWdg, SIGNAL( contentModified()), this, SLOT( checkVertexIsDefined() ) ); + connect( myXCoord, SIGNAL( textChanged(const QString&) ), this, SLOT( clearEnfVertexSelection() ) ); + connect( myYCoord, SIGNAL( textChanged(const QString&) ), this, SLOT( clearEnfVertexSelection() ) ); + connect( myZCoord, SIGNAL( textChanged(const QString&) ), this, SLOT( clearEnfVertexSelection() ) ); + connect( mySizeValue, SIGNAL( textChanged(const QString&) ), this, SLOT( checkVertexIsDefined() ) ); + connect( myXCoord, SIGNAL( valueChanged(const QString&) ), this, SLOT( clearEnfVertexSelection() ) ); + connect( myYCoord, SIGNAL( valueChanged(const QString&) ), this, SLOT( clearEnfVertexSelection() ) ); + connect( myZCoord, SIGNAL( valueChanged(const QString&) ), this, SLOT( clearEnfVertexSelection() ) ); + connect( mySizeValue, SIGNAL( valueChanged(const QString&) ), this, SLOT( checkVertexIsDefined() ) ); + connect( this, SIGNAL( vertexDefined(bool) ), addVertexButton, SLOT( setEnabled(bool) ) ); + + connect( addEnfMeshButton, SIGNAL( clicked()), this, SLOT( onAddEnforcedMesh() ) ); + connect( removeEnfMeshButton, SIGNAL( clicked()), this, SLOT( onRemoveEnforcedMesh() ) ); +// connect( myEnfMeshWdg, SIGNAL( contentModified()), this, SLOT( checkEnfMeshIsDefined() ) ); +// connect( myEnfMeshConstraint, SIGNAL( currentIndexChanged(int) ), this, SLOT( checkEnfMeshIsDefined() ) ); +// connect( myMeshSizeValue, SIGNAL( textChanged(const QString&) ), this, SLOT( checkEnfMeshIsDefined() ) ); +// connect( this, SIGNAL( enfMeshDefined(bool) ), addEnfMeshButton, SLOT( setEnabled(bool) ) ); return fr; } +/** + * This method checks if an enforced vertex is defined; +**/ +void GHS3DPluginGUI_HypothesisCreator::clearEnfVertexSelection() +{ + if (myEnfVertexWdg->NbObjects() != 0) { + disconnect( myEnfVertexWdg, SIGNAL( contentModified()), this, SLOT( onSelectEnforcedVertex() ) ); + disconnect( myEnfVertexWdg, SIGNAL( contentModified()), this, SLOT( checkVertexIsDefined() ) ); + myEnfVertexWdg->SetObject(GEOM::GEOM_Object::_nil()); + connect( myEnfVertexWdg, SIGNAL( contentModified()), this, SLOT( onSelectEnforcedVertex() ) ); + connect( myEnfVertexWdg, SIGNAL( contentModified()), this, SLOT( checkVertexIsDefined() ) ); + } + GHS3DPluginGUI_HypothesisCreator* that = (GHS3DPluginGUI_HypothesisCreator*)this; + that->checkVertexIsDefined(); +} + +/** + * This method checks if an enforced vertex is defined; +**/ +void GHS3DPluginGUI_HypothesisCreator::checkVertexIsDefined() +{ + bool enfVertexIsDefined = false; + enfVertexIsDefined = (!mySizeValue->GetString().isEmpty() && + (!myEnfVertexWdg->NbObjects() == 0 || + (myEnfVertexWdg->NbObjects() == 0 && !myXCoord->GetString().isEmpty() + && !myYCoord->GetString().isEmpty() + && !myZCoord->GetString().isEmpty()))); + emit vertexDefined(enfVertexIsDefined); +} + +/** + * This method checks if an enforced mesh is defined; +**/ +void GHS3DPluginGUI_HypothesisCreator::checkEnfMeshIsDefined() +{ + emit enfMeshDefined((!myMeshSizeValue->GetString().isEmpty() && !myEnfVertexWdg->NbObjects() == 0)); +} + +/** + * This method resets the content of the X, Y, Z, size and GroupName widgets; +**/ +void GHS3DPluginGUI_HypothesisCreator::clearEnforcedVertexWidgets() +{ + myXCoord->setCleared(true); + myYCoord->setCleared(true); + myZCoord->setCleared(true); +// mySizeValue->setCleared(true); + myXCoord->setText(""); + myYCoord->setText(""); + myZCoord->setText(""); +// mySizeValue->setText(""); +// myGroupName->setText(""); + addVertexButton->setEnabled(false); +} + +/** GHS3DPluginGUI_HypothesisCreator::updateEnforcedVertexValues(item) +This method updates the tooltip of a modified item. The QLineEdit widgets content +is synchronized with the coordinates of the enforced vertex clicked in the tree widget. +*/ +void GHS3DPluginGUI_HypothesisCreator::updateEnforcedVertexValues(QTableWidgetItem* item) { +// MESSAGE("GHS3DPluginGUI_HypothesisCreator::updateEnforcedVertexValues"); + int row = myEnforcedTableWidget->row(item); + + QVariant vertexName = myEnforcedTableWidget->item(row,ENF_VER_NAME_COLUMN)->data(Qt::EditRole); + QVariant x = myEnforcedTableWidget->item(row,ENF_VER_X_COLUMN)->data( Qt::EditRole); + QVariant y = myEnforcedTableWidget->item(row,ENF_VER_Y_COLUMN)->data( Qt::EditRole); + QVariant z = myEnforcedTableWidget->item(row,ENF_VER_Z_COLUMN)->data( Qt::EditRole); + QVariant size = myEnforcedTableWidget->item(row,ENF_VER_SIZE_COLUMN)->data( Qt::EditRole); + QVariant entry = myEnforcedTableWidget->item(row,ENF_VER_ENTRY_COLUMN)->data( Qt::EditRole); + QString groupName = myEnforcedTableWidget->item(row,ENF_VER_GROUP_COLUMN)->data( Qt::EditRole).toString(); + + clearEnforcedVertexWidgets(); + + if ( !x.isNull() || !entry.isNull()) { + QString toolTip = vertexName.toString(); + toolTip += QString("("); + if (entry.isNull() || (!entry.isNull() && entry.toString() == "")) { + toolTip += x.toString(); + toolTip += QString(", ") + y.toString(); + toolTip += QString(", ") + z.toString(); + } + else + toolTip += entry.toString(); + toolTip += QString(")"); + + if (!size.isNull()) + toolTip += QString("=") + size.toString(); + + if (!groupName.isEmpty()) + toolTip += QString(" [") + groupName + QString("]"); + +// MESSAGE("Tooltip: " << toolTip.toStdString()); + for (int col=0;colitem(row,col)->setToolTip(toolTip); + + if (!x.isNull()) { + disconnect( myXCoord, SIGNAL( textChanged(const QString&) ), this, SLOT( clearEnfVertexSelection() ) ); + disconnect( myYCoord, SIGNAL( textChanged(const QString&) ), this, SLOT( clearEnfVertexSelection() ) ); + disconnect( myZCoord, SIGNAL( textChanged(const QString&) ), this, SLOT( clearEnfVertexSelection() ) ); + myXCoord->SetValue(x.toDouble()); + myYCoord->SetValue(y.toDouble()); + myZCoord->SetValue(z.toDouble()); + connect( myXCoord, SIGNAL( textChanged(const QString&) ), this, SLOT( clearEnfVertexSelection() ) ); + connect( myYCoord, SIGNAL( textChanged(const QString&) ), this, SLOT( clearEnfVertexSelection() ) ); + connect( myZCoord, SIGNAL( textChanged(const QString&) ), this, SLOT( clearEnfVertexSelection() ) ); + } + if (!size.isNull()) + mySizeValue->SetValue(size.toDouble()); + + if (!groupName.isEmpty()) + myGroupName->setText(groupName); + } +} + +void GHS3DPluginGUI_HypothesisCreator::onSelectEnforcedVertex() { + int nbSelEnfVertex = myEnfVertexWdg->NbObjects(); + clearEnforcedVertexWidgets(); + if (nbSelEnfVertex == 1) + { + if ( CORBA::is_nil( getGeomEngine() ) && !GeometryGUI::InitGeomGen() ) + return ; + + myEnfVertex = myEnfVertexWdg->GetObject< GEOM::GEOM_Object >(nbSelEnfVertex-1); + if (myEnfVertex == GEOM::GEOM_Object::_nil()) + return; + if (myEnfVertex->GetShapeType() == GEOM::VERTEX) { + GHS3DPluginGUI_HypothesisCreator* that = (GHS3DPluginGUI_HypothesisCreator*)this; + GEOM::GEOM_IMeasureOperations_var measureOp = getGeomEngine()->GetIMeasureOperations( that->getGeomSelectionTool()->getMyStudy()->StudyId() ); + if (CORBA::is_nil(measureOp)) + return; + + CORBA::Double x,y,z; + measureOp->PointCoordinates (myEnfVertex, x, y, z); + if ( measureOp->IsDone() ) + { + disconnect( myXCoord, SIGNAL( textChanged(const QString&) ), this, SLOT( clearEnfVertexSelection() ) ); + disconnect( myYCoord, SIGNAL( textChanged(const QString&) ), this, SLOT( clearEnfVertexSelection() ) ); + disconnect( myZCoord, SIGNAL( textChanged(const QString&) ), this, SLOT( clearEnfVertexSelection() ) ); + myXCoord->SetValue(x); + myYCoord->SetValue(y); + myZCoord->SetValue(z); + connect( myXCoord, SIGNAL( textChanged(const QString&) ), this, SLOT( clearEnfVertexSelection() ) ); + connect( myYCoord, SIGNAL( textChanged(const QString&) ), this, SLOT( clearEnfVertexSelection() ) ); + connect( myZCoord, SIGNAL( textChanged(const QString&) ), this, SLOT( clearEnfVertexSelection() ) ); + } + } + } +} + +/** GHS3DPluginGUI_HypothesisCreator::synchronizeCoords() +This method synchronizes the QLineEdit/SMESHGUI_SpinBox widgets content with the coordinates +of the enforced vertex clicked in the tree widget. +*/ +void GHS3DPluginGUI_HypothesisCreator::synchronizeCoords() { + clearEnforcedVertexWidgets(); + QList items = myEnforcedTableWidget->selectedItems(); +// myEnfVertexWdg->disconnect(SIGNAL(contentModified())); + disconnect( myEnfVertexWdg, SIGNAL( contentModified()), this, SLOT( onSelectEnforcedVertex() ) ); + if (! items.isEmpty()) { + QTableWidgetItem *item; + int row; + QVariant entry; + if (items.size() == 1) { + item = items[0]; + row = myEnforcedTableWidget->row(item); + QVariant x = myEnforcedTableWidget->item(row,ENF_VER_X_COLUMN)->data( Qt::EditRole); + QVariant y = myEnforcedTableWidget->item(row,ENF_VER_Y_COLUMN)->data( Qt::EditRole); + QVariant z = myEnforcedTableWidget->item(row,ENF_VER_Z_COLUMN)->data( Qt::EditRole); + QVariant size = myEnforcedTableWidget->item(row,ENF_VER_SIZE_COLUMN)->data( Qt::EditRole); + entry = myEnforcedTableWidget->item(row,ENF_VER_ENTRY_COLUMN)->data( Qt::EditRole); + if (!entry.isNull()) { + SMESH::string_array_var objIds = new SMESH::string_array; + objIds->length(1); + objIds[0] = entry.toString().toStdString().c_str(); + myEnfVertexWdg->SetObjects(objIds); + } + else { + myEnfVertexWdg->SetObject(GEOM::GEOM_Object::_nil()); + } + QVariant group = myEnforcedTableWidget->item(row,ENF_VER_GROUP_COLUMN)->data( Qt::EditRole); + if (!x.isNull()/* && entry.isNull()*/) { +// disconnect( myXCoord, SIGNAL( textChanged(const QString &)), this, SLOT( onSelectEnforcedVertex() ) ); + disconnect( myXCoord, SIGNAL( textChanged(const QString&) ), this, SLOT( clearEnfVertexSelection() ) ); + disconnect( myYCoord, SIGNAL( textChanged(const QString&) ), this, SLOT( clearEnfVertexSelection() ) ); + disconnect( myZCoord, SIGNAL( textChanged(const QString&) ), this, SLOT( clearEnfVertexSelection() ) ); + myXCoord->SetValue(x.toDouble()); + myYCoord->SetValue(y.toDouble()); + myZCoord->SetValue(z.toDouble()); + connect( myXCoord, SIGNAL( textChanged(const QString&) ), this, SLOT( clearEnfVertexSelection() ) ); + connect( myYCoord, SIGNAL( textChanged(const QString&) ), this, SLOT( clearEnfVertexSelection() ) ); + connect( myZCoord, SIGNAL( textChanged(const QString&) ), this, SLOT( clearEnfVertexSelection() ) ); + } + if (!size.isNull()) + mySizeValue->SetValue(size.toDouble()); + + if (!group.isNull() && (!x.isNull() || !entry.isNull())) + myGroupName->setText(group.toString()); + } + else { + QList entryList; + for (int i = 0; i < items.size(); ++i) { + item = items[i]; + row = myEnforcedTableWidget->row(item); + entry = myEnforcedTableWidget->item(row,ENF_VER_ENTRY_COLUMN)->data( Qt::EditRole); + if (!entry.isNull()) + entryList << entry.toString(); + } + if (entryList.size() > 0) { + SMESH::string_array_var objIds = new SMESH::string_array; + objIds->length(entryList.size()); + for (int i = 0; i < entryList.size() ; i++) + objIds[i] = entryList.at(i).toStdString().c_str(); + myEnfVertexWdg->SetObjects(objIds); + } + else { + myEnfVertexWdg->SetObject(GEOM::GEOM_Object::_nil()); + } + } + } + else { + myEnfVertexWdg->SetObject(GEOM::GEOM_Object::_nil()); + } + connect( myEnfVertexWdg, SIGNAL( contentModified()), this, SLOT( onSelectEnforcedVertex() ) ); + GHS3DPluginGUI_HypothesisCreator* that = (GHS3DPluginGUI_HypothesisCreator*)this; + that->checkVertexIsDefined(); +} + +/** GHS3DPluginGUI_HypothesisCreator::addEnforcedMesh( meshName, geomEntry, elemType, size, groupName) +This method adds in the tree widget an enforced mesh from mesh, submesh or group with optionally size and and groupName. +*/ +void GHS3DPluginGUI_HypothesisCreator::addEnforcedMesh(std::string name, std::string entry, int elementType, double size, std::string groupName) +{ + MESSAGE("addEnforcedMesh(\"" << name << ", \"" << entry << "\", " << elementType << ", " << size << ", \"" << groupName << "\")"); + bool okToCreate = true; + QString itemEntry = ""; + int itemElementType = 0; + int rowCount = myEnforcedMeshTableWidget->rowCount(); + bool allColumns = true; + for (int row = 0;row(myEnforcedMeshTableWidget->cellWidget(row, col)) == 0) { + allColumns = false; + MESSAGE("allColumns = false"); + break; + } + } + else if (myEnforcedMeshTableWidget->item(row, col) == 0) { + allColumns = false; + MESSAGE("allColumns = false"); + break; + } + if (col == ENF_MESH_CONSTRAINT_COLUMN) { + QComboBox* itemComboBox = qobject_cast(myEnforcedMeshTableWidget->cellWidget(row, col)); + itemElementType = itemComboBox->currentIndex(); + MESSAGE("itemElementType: " << itemElementType); + } + else if (col == ENF_MESH_ENTRY_COLUMN) + itemEntry = myEnforcedMeshTableWidget->item(row, col)->data(Qt::EditRole).toString(); + } + + if (!allColumns) + break; + + if (itemEntry == QString(entry.c_str()) && itemElementType == elementType) { +// // update size +// if (itemSize != size) { +// MESSAGE("Size is updated from \"" << itemSize << "\" to \"" << size << "\""); +// myEnforcedMeshTableWidget->item(row, ENF_MESH_SIZE_COLUMN)->setData( Qt::EditRole, QVariant(size)); +// } +// // update group name +// if (itemGroupName.toStdString() != groupName) { +// MESSAGE("Group is updated from \"" << itemGroupName.toStdString() << "\" to \"" << groupName << "\""); +// myEnforcedMeshTableWidget->item(row, ENF_MESH_GROUP_COLUMN)->setData( Qt::EditRole, QVariant(groupName.c_str())); +// } + okToCreate = false; + break; + } // if + } // for + + + if (!okToCreate) + return; + + MESSAGE("Creation of enforced mesh"); + + myEnforcedMeshTableWidget->setRowCount(rowCount+1); + myEnforcedMeshTableWidget->setSortingEnabled(false); + + for (int col=0;colpalette(); + pal.setColor(QPalette::Button, Qt::white); + comboBox->setPalette(pal); + comboBox->insertItems(0,myEnfMeshConstraintLabels); + comboBox->setEditable(false); + comboBox->setCurrentIndex(elementType); + MESSAGE("Add item in table at (" << rowCount << "," << col << "): " << comboBox->currentText().toStdString()); + myEnforcedMeshTableWidget->setCellWidget(rowCount,col,comboBox); + } + else { + QTableWidgetItem* item = new QTableWidgetItem(); + item->setFlags( Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled); + switch (col) { + case ENF_MESH_NAME_COLUMN: + item->setData( 0, name.c_str() ); + item->setFlags( Qt::ItemIsSelectable | Qt::ItemIsEnabled); + MESSAGE("Add item in table at (" << rowCount << "," << col << "): " << item->text().toStdString()); + myEnforcedMeshTableWidget->setItem(rowCount,col,item); + break; + case ENF_MESH_ENTRY_COLUMN: + item->setData( 0, entry.c_str() ); + item->setFlags( Qt::ItemIsSelectable | Qt::ItemIsEnabled); + MESSAGE("Add item in table at (" << rowCount << "," << col << "): " << item->text().toStdString()); + myEnforcedMeshTableWidget->setItem(rowCount,col,item); + break; + case ENF_MESH_SIZE_COLUMN: + item->setData( 0, size ); + MESSAGE("Add item in table at (" << rowCount << "," << col << "): " << item->text().toStdString()); + myEnforcedMeshTableWidget->setItem(rowCount,col,item); + break; + case ENF_MESH_GROUP_COLUMN: + item->setData( 0, groupName.c_str() ); + MESSAGE("Add item in table at (" << rowCount << "," << col << "): " << item->text().toStdString()); + myEnforcedMeshTableWidget->setItem(rowCount,col,item); + break; + default: + break; + } + } + MESSAGE("Done"); + } + +// connect( myEnforcedMeshTableWidget,SIGNAL( itemChanged(QTableWidgetItem *)), this, SLOT( updateEnforcedVertexValues(QTableWidgetItem *) ) ); + + myEnforcedMeshTableWidget->setSortingEnabled(true); +// myEnforcedTableWidget->setCurrentItem(myEnforcedTableWidget->item(rowCount,ENF_VER_NAME_COLUMN)); +// updateEnforcedVertexValues(myEnforcedTableWidget->item(rowCount,ENF_VER_NAME_COLUMN)); + +} + +/** GHS3DPluginGUI_HypothesisCreator::addEnforcedVertex( x, y, z, size, vertexName, geomEntry, groupName) +This method adds in the tree widget an enforced vertex with given size and coords (x,y,z) or GEOM vertex or compound and with optionally groupName. +*/ +void GHS3DPluginGUI_HypothesisCreator::addEnforcedVertex(double x, double y, double z, double size, std::string vertexName, std::string geomEntry, std::string groupName, bool isCompound) +{ + MESSAGE("addEnforcedVertex(" << x << ", " << y << ", " << z << ", " << size << ", \"" << vertexName << ", \"" << geomEntry << "\", \"" << groupName << "\", " << isCompound << ")"); + myEnforcedTableWidget->disconnect(SIGNAL( itemChanged(QTableWidgetItem *))); + bool okToCreate = true; + double itemX,itemY,itemZ,itemSize = 0; + QString itemEntry, itemGroupName = QString(""); +// bool itemIsCompound; + int rowCount = myEnforcedTableWidget->rowCount(); + QVariant data; + bool allColumns; + for (int row = 0;rowitem(row, col) == 0) { + allColumns = false; + break; + } + + data = myEnforcedTableWidget->item(row, col)->data(Qt::EditRole); + if (!data.isNull()) { + switch (col) { + case ENF_VER_GROUP_COLUMN: + itemGroupName = data.toString(); + break; + case ENF_VER_ENTRY_COLUMN: + itemEntry = data.toString(); + break; +// case ENF_VER_COMPOUND_COLUMN: +// itemIsCompound = data.toBool(); +// break; + case ENF_VER_X_COLUMN: + itemX = data.toDouble(); + break; + case ENF_VER_Y_COLUMN: + itemY = data.toDouble(); + break; + case ENF_VER_Z_COLUMN: + itemZ = data.toDouble(); + break; + case ENF_VER_SIZE_COLUMN: + itemSize = data.toDouble(); + break; + default: + break; + } + } + } + + if (!allColumns) + break; + + + if (( !isCompound && ((itemX == x) && (itemY == y) && (itemZ == z))) || /*( (itemEntry.toStdString() != "") && */ (itemEntry.toStdString() == geomEntry)/*)*/) { + // update size + if (itemSize != size) { + MESSAGE("Size is updated from \"" << itemSize << "\" to \"" << size << "\""); + myEnforcedTableWidget->item(row, ENF_VER_SIZE_COLUMN)->setData( Qt::EditRole, QVariant(size)); + } + // update group name + if (itemGroupName.toStdString() != groupName) { + MESSAGE("Group is updated from \"" << itemGroupName.toStdString() << "\" to \"" << groupName << "\""); + myEnforcedTableWidget->item(row, ENF_VER_GROUP_COLUMN)->setData( Qt::EditRole, QVariant(groupName.c_str())); + } + okToCreate = false; + break; + } // if + } // for + if (!okToCreate) { + if (geomEntry.empty()) { + MESSAGE("Vertex with coords " << x << ", " << y << ", " << z << " already exist: dont create again"); + } + else { + MESSAGE("Vertex with entry " << geomEntry << " already exist: dont create again"); + } + return; + } + + if (geomEntry.empty()) { + MESSAGE("Vertex with coords " << x << ", " << y << ", " << z<< " is created"); + } + else { + MESSAGE("Vertex with geom entry " << geomEntry << " is created"); + } + + int vertexIndex=0; + int indexRef = -1; + QString myVertexName; + while(indexRef != vertexIndex) { + indexRef = vertexIndex; + if (vertexName.empty()) + myVertexName = QString("Vertex #%1").arg(vertexIndex); + else + myVertexName = QString(vertexName.c_str()); + + for (int row = 0;rowitem(row,ENF_VER_NAME_COLUMN)->data(Qt::EditRole).toString(); + if (myVertexName == name) { + vertexIndex++; + break; + } + } + } + + MESSAGE("myVertexName is \"" << myVertexName.toStdString() << "\""); + myEnforcedTableWidget->setRowCount(rowCount+1); + myEnforcedTableWidget->setSortingEnabled(false); + for (int col=0;colsetFlags( Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled); + switch (col) { + case ENF_VER_NAME_COLUMN: + item->setData( Qt::EditRole, myVertexName ); + if (!geomEntry.empty()) { + if (isCompound) + item->setIcon(QIcon(iconCompound.scaled(iconCompound.size()*0.7,Qt::KeepAspectRatio,Qt::SmoothTransformation))); + else + item->setIcon(QIcon(iconVertex.scaled(iconVertex.size()*0.7,Qt::KeepAspectRatio,Qt::SmoothTransformation))); + } + break; + case ENF_VER_X_COLUMN: + if (!isCompound) + item->setData( 0, QVariant(x) ); + break; + case ENF_VER_Y_COLUMN: + if (!isCompound) + item->setData( 0, QVariant(y) ); + break; + case ENF_VER_Z_COLUMN: + if (!isCompound) + item->setData( 0, QVariant(z) ); + break; + case ENF_VER_SIZE_COLUMN: + item->setData( 0, QVariant(size) ); + break; + case ENF_VER_ENTRY_COLUMN: + if (!geomEntry.empty()) + item->setData( 0, QString(geomEntry.c_str()) ); + break; + case ENF_VER_COMPOUND_COLUMN: + item->setData( Qt::CheckStateRole, isCompound ); + item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsUserCheckable); + break; + case ENF_VER_GROUP_COLUMN: + if (!groupName.empty()) + item->setData( 0, QString(groupName.c_str()) ); + break; + default: + break; + } + + MESSAGE("Add item in table at (" << rowCount << "," << col << "): " << item->text().toStdString()); + myEnforcedTableWidget->setItem(rowCount,col,item); + MESSAGE("Done"); + } + + connect( myEnforcedTableWidget,SIGNAL( itemChanged(QTableWidgetItem *)), this, SLOT( updateEnforcedVertexValues(QTableWidgetItem *) ) ); + + myEnforcedTableWidget->setSortingEnabled(true); +// myEnforcedTableWidget->setCurrentItem(myEnforcedTableWidget->item(rowCount,ENF_VER_NAME_COLUMN)); + updateEnforcedVertexValues(myEnforcedTableWidget->item(rowCount,ENF_VER_NAME_COLUMN)); +} + +/** GHS3DPluginGUI_HypothesisCreator::onAddEnforcedMesh() +This method is called when a item is added into the enforced meshes tree widget +*/ +void GHS3DPluginGUI_HypothesisCreator::onAddEnforcedMesh() +{ + MESSAGE("GHS3DPluginGUI_HypothesisCreator::onAddEnforcedMesh()"); + + GHS3DPluginGUI_HypothesisCreator* that = (GHS3DPluginGUI_HypothesisCreator*)this; + + that->getGeomSelectionTool()->selectionMgr()->clearFilters(); + myEnfMeshWdg->deactivateSelection(); + + for (int column = 0; column < myEnforcedMeshTableWidget->columnCount(); ++column) + myEnforcedMeshTableWidget->resizeColumnToContents(column); + + // Vertex selection + int selEnfMeshes = myEnfMeshWdg->NbObjects(); + if (selEnfMeshes == 0) + return; + + std::string groupName = myMeshGroupName->text().toStdString(); +// if (myGlobalGroupName->isChecked()) +// groupName = myGlobalGroupName->text().toStdString(); + + if (boost::trim_copy(groupName).empty()) + groupName = ""; + + + double size = -1; + if (!myMeshSizeValue->GetString().isEmpty()) + size = myMeshSizeValue->GetValue(); +// if (size < 0) +// return; + + int elementType = myEnfMeshConstraint->currentIndex(); + + + _PTR(Study) aStudy = SMESH::GetActiveStudyDocument(); + _PTR(SObject) aSObj; //SMESH::SMESH_IDSource::_nil; + QString meshEntry = myEnfMeshWdg->GetValue(); + MESSAGE("myEnfMeshWdg->GetValue()" << meshEntry.toStdString()); + + if (selEnfMeshes == 1) + { + MESSAGE("1 SMESH object selected"); +// myEnfMesh = myEnfMeshWdg->GetObject< SMESH::SMESH_IDSource >(); +// std::string entry = myEnfMeshWdg->GetValue(); + aSObj = aStudy->FindObjectID(meshEntry.toStdString().c_str()); + CORBA::Object_var anObj = SMESH::SObjectToObject(aSObj,aStudy); + if (!CORBA::is_nil(anObj)) { +// SMESH::SMESH_IDSource_var theSource = SMESH::SObjectToInterface( aSObj ); + addEnforcedMesh( aSObj->GetName(), aSObj->GetID(), elementType, size, groupName); + } + } + else + { + MESSAGE(selEnfMeshes << " SMESH objects selected"); + QStringList meshEntries = meshEntry.split(" ", QString::SkipEmptyParts); + QStringListIterator meshEntriesIt (meshEntries); + while (meshEntriesIt.hasNext()) { + aSObj = aStudy->FindObjectID(meshEntriesIt.next().toStdString().c_str()); + CORBA::Object_var anObj = SMESH::SObjectToObject(aSObj,aStudy); + if (!CORBA::is_nil(anObj)) { +// SMESH::SMESH_IDSource_var theSource = SMESH::SObjectToInterface( aSObj ); + addEnforcedMesh( aSObj->GetName(), aSObj->GetID(), elementType, size, groupName); + } + } + } + + myEnfVertexWdg->SetObject(SMESH::SMESH_IDSource::_nil()); + + for (int column = 0; column < myEnforcedMeshTableWidget->columnCount(); ++column) + myEnforcedMeshTableWidget->resizeColumnToContents(column); +} + + +/** GHS3DPluginGUI_HypothesisCreator::onAddEnforcedVertex() +This method is called when a item is added into the enforced vertices tree widget +*/ +void GHS3DPluginGUI_HypothesisCreator::onAddEnforcedVertex() +{ + MESSAGE("GHS3DPluginGUI_HypothesisCreator::onAddEnforcedVertex()"); + + GHS3DPluginGUI_HypothesisCreator* that = (GHS3DPluginGUI_HypothesisCreator*)this; + + that->getGeomSelectionTool()->selectionMgr()->clearFilters(); + myEnfVertexWdg->deactivateSelection(); + + for (int column = 0; column < myEnforcedTableWidget->columnCount(); ++column) + myEnforcedTableWidget->resizeColumnToContents(column); + + // Vertex selection + int selEnfVertex = myEnfVertexWdg->NbObjects(); + bool coordsEmpty = (myXCoord->text().isEmpty()) || (myYCoord->text().isEmpty()) || (myZCoord->text().isEmpty()); + if ((selEnfVertex == 0) && coordsEmpty) + return; + + std::string groupName = myGroupName->text().toStdString(); +// if (myGlobalGroupName->isChecked()) +// groupName = myGlobalGroupName->text().toStdString(); + + if (boost::trim_copy(groupName).empty()) + groupName = ""; + + double size = mySizeValue->GetValue(); + + if (selEnfVertex <= 1) + { + MESSAGE("0 or 1 GEOM object selected"); + double x = 0, y = 0, z=0; + if (myXCoord->GetString() != "") { + x = myXCoord->GetValue(); + y = myYCoord->GetValue(); + z = myZCoord->GetValue(); + } + if (selEnfVertex == 1) { + MESSAGE("1 GEOM object selected"); + myEnfVertex = myEnfVertexWdg->GetObject< GEOM::GEOM_Object >(); + std::string entry = ""; + if (myEnfVertex != GEOM::GEOM_Object::_nil()) + entry = myEnfVertex->GetStudyEntry(); + addEnforcedVertex(x, y, z, size, myEnfVertex->GetName(),entry, groupName, myEnfVertex->GetShapeType() == GEOM::COMPOUND); + } + else { + MESSAGE("0 GEOM object selected"); + MESSAGE("Coords: ("<GetIMeasureOperations( that->getGeomSelectionTool()->getMyStudy()->StudyId() ); + if (CORBA::is_nil(measureOp)) + return; + + CORBA::Double x = 0, y = 0,z = 0; + for (int j = 0 ; j < selEnfVertex ; j++) + { + myEnfVertex = myEnfVertexWdg->GetObject< GEOM::GEOM_Object >(j); + if (myEnfVertex == GEOM::GEOM_Object::_nil()) + continue; + if (myEnfVertex->GetShapeType() == GEOM::VERTEX) { + measureOp->PointCoordinates (myEnfVertex, x, y, z); + if ( measureOp->IsDone() ) + addEnforcedVertex(x, y, z, size, myEnfVertex->GetName(),myEnfVertex->GetStudyEntry(), groupName); + } else if (myEnfVertex->GetShapeType() == GEOM::COMPOUND) { + addEnforcedVertex(0., 0., 0., size, myEnfVertex->GetName(),myEnfVertex->GetStudyEntry(), groupName, true); + } + } + } + + myEnfVertexWdg->SetObject(GEOM::GEOM_Object::_nil()); + + for (int column = 0; column < myEnforcedTableWidget->columnCount(); ++column) + myEnforcedTableWidget->resizeColumnToContents(column); +} + +/** GHS3DPluginGUI_HypothesisCreator::onRemoveEnforcedMesh() +This method is called when a item is removed from the enforced meshes tree widget +*/ +void GHS3DPluginGUI_HypothesisCreator::onRemoveEnforcedMesh() +{ + QList selectedRows; + QList selectedItems = myEnforcedMeshTableWidget->selectedItems(); + QTableWidgetItem* item; + int row; + foreach( item, selectedItems ) { + row = item->row(); + if (!selectedRows.contains( row ) ) + selectedRows.append(row); + } + + qSort( selectedRows ); + QListIterator it( selectedRows ); + it.toBack(); + while ( it.hasPrevious() ) { + row = it.previous(); + MESSAGE("delete row #"<< row); + myEnforcedMeshTableWidget->removeRow(row ); + } + + myEnforcedMeshTableWidget->selectionModel()->clearSelection(); +} + +/** GHS3DPluginGUI_HypothesisCreator::onRemoveEnforcedVertex() +This method is called when a item is removed from the enforced vertices tree widget +*/ +void GHS3DPluginGUI_HypothesisCreator::onRemoveEnforcedVertex() +{ + QList selectedRows; + QList selectedItems = myEnforcedTableWidget->selectedItems(); + QTableWidgetItem* item; + int row; + foreach( item, selectedItems ) { + row = item->row(); + if (!selectedRows.contains( row ) ) + selectedRows.append(row); + } + + qSort( selectedRows ); + QListIterator it( selectedRows ); + it.toBack(); + while ( it.hasPrevious() ) { + row = it.previous(); + MESSAGE("delete row #"<< row); + myEnforcedTableWidget->removeRow(row ); + } + + myEnforcedTableWidget->selectionModel()->clearSelection(); +} + void GHS3DPluginGUI_HypothesisCreator::onDirBtnClicked() { QString dir = SUIT_FileDlg::getExistingDirectory( dlg(), myWorkingDir->text(), QString() ); @@ -211,108 +1434,334 @@ void GHS3DPluginGUI_HypothesisCreator::updateWidgets() myOptimizationLevelCombo->setEnabled( !myBoundaryRecoveryCheck->isChecked() ); } -bool GHS3DPluginGUI_HypothesisCreator::checkParams() const +bool GHS3DPluginGUI_HypothesisCreator::checkParams(QString& msg) const { + MESSAGE("GHS3DPluginGUI_HypothesisCreator::checkParams"); + if ( !QFileInfo( myWorkingDir->text().trimmed() ).isWritable() ) { SUIT_MessageBox::warning( dlg(), - tr( "SMESH_WRN_WARNING" ), - tr( "GHS3D_PERMISSION_DENIED" ) ); + tr( "SMESH_WRN_WARNING" ), + tr( "GHS3D_PERMISSION_DENIED" ) ); return false; } + return true; } void GHS3DPluginGUI_HypothesisCreator::retrieveParams() const { + MESSAGE("GHS3DPluginGUI_HypothesisCreator::retrieveParams"); + GHS3DPluginGUI_HypothesisCreator* that = (GHS3DPluginGUI_HypothesisCreator*)this; GHS3DHypothesisData data; readParamsFromHypo( data ); if ( myName ) myName->setText( data.myName ); - myToMeshHolesCheck ->setChecked ( data.myToMeshHoles ); - myOptimizationLevelCombo->setCurrentIndex( data.myOptimizationLevel ); - myMaximumMemoryCheck ->setChecked ( data.myMaximumMemory > 0 ); - myMaximumMemorySpin ->setValue ( qMax( data.myMaximumMemory, - myMaximumMemorySpin->minimum() )); - myInitialMemoryCheck ->setChecked ( data.myInitialMemory > 0 ); - myInitialMemorySpin ->setValue ( qMax( data.myInitialMemory, - myInitialMemorySpin->minimum() )); - myWorkingDir ->setText ( data.myWorkingDir ); - myKeepFiles ->setChecked ( data.myKeepFiles ); - myVerboseLevelSpin ->setValue ( data.myVerboseLevel ); - myToCreateNewNodesCheck ->setChecked ( data.myToCreateNewNodes ); - myBoundaryRecoveryCheck ->setChecked ( data.myBoundaryRecovery ); - myTextOption ->setText ( data.myTextOption ); - - GHS3DPluginGUI_HypothesisCreator* that = (GHS3DPluginGUI_HypothesisCreator*)this; - that->updateWidgets(); -} - -QString GHS3DPluginGUI_HypothesisCreator::storeParams() const -{ - GHS3DHypothesisData data; - readParamsFromWidgets( data ); - storeParamsToHypo( data ); - - QString valStr = ""; + myToMeshHolesCheck ->setChecked ( data.myToMeshHoles ); + myOptimizationLevelCombo ->setCurrentIndex( data.myOptimizationLevel ); + myMaximumMemoryCheck ->setChecked ( data.myMaximumMemory > 0 ); + myMaximumMemorySpin ->setValue ( qMax( data.myMaximumMemory, + myMaximumMemorySpin->minimum() )); + myInitialMemoryCheck ->setChecked ( data.myInitialMemory > 0 ); + myInitialMemorySpin ->setValue ( qMax( data.myInitialMemory, + myInitialMemorySpin->minimum() )); + myWorkingDir ->setText ( data.myWorkingDir ); + myKeepFiles ->setChecked ( data.myKeepFiles ); + myVerboseLevelSpin ->setValue ( data.myVerboseLevel ); + myToCreateNewNodesCheck ->setChecked ( data.myToCreateNewNodes ); + myRemoveInitialCentralPointCheck ->setChecked ( data.myRemoveInitialCentralPoint ); + myBoundaryRecoveryCheck ->setChecked ( data.myBoundaryRecovery ); + myFEMCorrectionCheck ->setChecked ( data.myFEMCorrection ); + myTextOption ->setText ( data.myTextOption ); - if ( !data.myBoundaryRecovery ) - valStr = "-c " + QString::number( !data.myToMeshHoles ); + TEnfVertexList::const_iterator it; + int rowCount = 0; + myEnforcedTableWidget->setSortingEnabled(false); + myEnforcedTableWidget->disconnect(SIGNAL( itemChanged(QTableWidgetItem *))); + for(it = data.myEnforcedVertices.begin() ; it != data.myEnforcedVertices.end(); it++ ) + { + TEnfVertex* enfVertex = (*it); + myEnforcedTableWidget->setRowCount(rowCount+1); - if ( data.myOptimizationLevel >= 0 && data.myOptimizationLevel < 4 && !data.myBoundaryRecovery) { - char* level[] = { "none" , "light" , "standard" , "strong" }; - valStr += " -o "; - valStr += level[ data.myOptimizationLevel ]; - } - if ( data.myMaximumMemory > 0 ) { - valStr += " -m "; - valStr += QString::number( data.myMaximumMemory ); - } - if ( data.myInitialMemory > 0 && !data.myBoundaryRecovery ) { - valStr += " -M "; - valStr += QString::number( data.myInitialMemory ); + for (int col=0;colisCompound: " << enfVertex->isCompound); + QTableWidgetItem* item = new QTableWidgetItem(); + item->setFlags( Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled); + switch (col) { + case ENF_VER_NAME_COLUMN: + item->setData( 0, enfVertex->name.c_str() ); + if (!enfVertex->geomEntry.empty()) { + if (enfVertex->isCompound) + item->setIcon(QIcon(iconCompound.scaled(iconCompound.size()*0.7,Qt::KeepAspectRatio,Qt::SmoothTransformation))); + else + item->setIcon(QIcon(iconVertex.scaled(iconVertex.size()*0.7,Qt::KeepAspectRatio,Qt::SmoothTransformation))); + + MESSAGE("Add item in table at (" << rowCount << "," << col << "): " << item->text().toStdString()); + } + break; + case ENF_VER_X_COLUMN: + if (!enfVertex->isCompound) { + item->setData( 0, enfVertex->coords.at(0) ); + MESSAGE("Add item in table at (" << rowCount << "," << col << "): " << item->text().toStdString()); + } + break; + case ENF_VER_Y_COLUMN: + if (!enfVertex->isCompound) { + item->setData( 0, enfVertex->coords.at(1) ); + MESSAGE("Add item in table at (" << rowCount << "," << col << "): " << item->text().toStdString()); + } + break; + case ENF_VER_Z_COLUMN: + if (!enfVertex->isCompound) { + item->setData( 0, enfVertex->coords.at(2) ); + MESSAGE("Add item in table at (" << rowCount << "," << col << "): " << item->text().toStdString()); + } + break; + case ENF_VER_SIZE_COLUMN: + item->setData( 0, enfVertex->size ); + MESSAGE("Add item in table at (" << rowCount << "," << col << "): " << item->text().toStdString()); + break; + case ENF_VER_ENTRY_COLUMN: + item->setData( 0, enfVertex->geomEntry.c_str() ); + MESSAGE("Add item in table at (" << rowCount << "," << col << "): " << item->text().toStdString()); + break; + case ENF_VER_COMPOUND_COLUMN: + item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsUserCheckable); + item->setData( Qt::CheckStateRole, enfVertex->isCompound ); + MESSAGE("Add item in table at (" << rowCount << "," << col << "): " << enfVertex->isCompound); + break; + case ENF_VER_GROUP_COLUMN: + item->setData( 0, enfVertex->groupName.c_str() ); + MESSAGE("Add item in table at (" << rowCount << "," << col << "): " << item->text().toStdString()); + break; + default: + break; + } + + myEnforcedTableWidget->setItem(rowCount,col,item); + MESSAGE("Done"); + } + that->updateEnforcedVertexValues(myEnforcedTableWidget->item(rowCount,ENF_VER_NAME_COLUMN)); + rowCount++; } - valStr += " -v "; - valStr += QString::number( data.myVerboseLevel ); - if ( !data.myToCreateNewNodes ) - valStr += " -p0"; + connect( myEnforcedTableWidget,SIGNAL( itemChanged(QTableWidgetItem *)), this, SLOT( updateEnforcedVertexValues(QTableWidgetItem *) ) ); + myEnforcedTableWidget->setSortingEnabled(true); + + for (int column = 0; column < myEnforcedTableWidget->columnCount(); ++column) + myEnforcedTableWidget->resizeColumnToContents(column); - if ( data.myBoundaryRecovery ) - valStr += " -C"; + // Update Enforced meshes QTableWidget + TEnfMeshList::const_iterator itMesh; + rowCount = 0; + myEnforcedMeshTableWidget->setSortingEnabled(false); +// myEnforcedMeshTableWidget->disconnect(SIGNAL( itemChanged(QTableWidgetItem *))); + for(itMesh = data.myEnforcedMeshes.begin() ; itMesh != data.myEnforcedMeshes.end(); itMesh++ ) + { + TEnfMesh* enfMesh = (*itMesh); + myEnforcedMeshTableWidget->setRowCount(rowCount+1); - valStr += " "; - valStr += data.myTextOption; + for (int col=0;colpalette(); + pal.setColor(QPalette::Button, Qt::white); + comboBox->setPalette(pal); + comboBox->insertItems(0,myEnfMeshConstraintLabels); + comboBox->setEditable(false); + comboBox->setCurrentIndex(enfMesh->elementType); + MESSAGE("Add item in table at (" << rowCount << "," << col << "): " << comboBox->currentText().toStdString()); + myEnforcedMeshTableWidget->setCellWidget(rowCount,col,comboBox); + } + else { + QTableWidgetItem* item = new QTableWidgetItem(); + item->setFlags( Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled); + switch (col) { + case ENF_MESH_NAME_COLUMN: + item->setData( 0, enfMesh->name.c_str() ); + item->setFlags( Qt::ItemIsSelectable | Qt::ItemIsEnabled); + MESSAGE("Add item in table at (" << rowCount << "," << col << "): " << item->text().toStdString()); + myEnforcedMeshTableWidget->setItem(rowCount,col,item); + break; + case ENF_MESH_ENTRY_COLUMN: + item->setData( 0, enfMesh->entry.c_str() ); + item->setFlags( Qt::ItemIsSelectable | Qt::ItemIsEnabled); + MESSAGE("Add item in table at (" << rowCount << "," << col << "): " << item->text().toStdString()); + myEnforcedMeshTableWidget->setItem(rowCount,col,item); + break; + case ENF_MESH_SIZE_COLUMN: + item->setData( 0, enfMesh->size ); + MESSAGE("Add item in table at (" << rowCount << "," << col << "): " << item->text().toStdString()); + myEnforcedMeshTableWidget->setItem(rowCount,col,item); + break; + case ENF_MESH_GROUP_COLUMN: + item->setData( 0, enfMesh->groupName.c_str() ); + MESSAGE("Add item in table at (" << rowCount << "," << col << "): " << item->text().toStdString()); + myEnforcedMeshTableWidget->setItem(rowCount,col,item); + break; + default: + break; + } + } + +// myEnforcedMeshTableWidget->setItem(rowCount,col,item); + MESSAGE("Done"); + } +// that->updateEnforcedVertexValues(myEnforcedTableWidget->item(rowCount,ENF_VER_NAME_COLUMN)); + rowCount++; + } +// connect( myEnforcedMeshTableWidget,SIGNAL( itemChanged(QTableWidgetItem *)), this, SLOT( updateEnforcedVertexValues(QTableWidgetItem *) ) ); + myEnforcedMeshTableWidget->setSortingEnabled(true); + + for (int col=0;colresizeColumnToContents(col); + + that->updateWidgets(); + that->checkVertexIsDefined(); +} + +QString GHS3DPluginGUI_HypothesisCreator::storeParams() const +{ + MESSAGE("GHS3DPluginGUI_HypothesisCreator::storeParams"); + GHS3DHypothesisData data; + readParamsFromWidgets( data ); + storeParamsToHypo( data ); + + QString valStr = ""; + + if ( !data.myBoundaryRecovery ) + valStr = "-c " + QString::number( !data.myToMeshHoles ); + + if ( data.myOptimizationLevel >= 0 && data.myOptimizationLevel < 5 && !data.myBoundaryRecovery) { + const char* level[] = { "none" , "light" , "standard" , "standard+" , "strong" }; + valStr += " -o "; + valStr += level[ data.myOptimizationLevel ]; + } + if ( data.myMaximumMemory > 0 ) { + valStr += " -m "; + valStr += QString::number( data.myMaximumMemory ); + } + if ( data.myInitialMemory > 0 && !data.myBoundaryRecovery ) { + valStr += " -M "; + valStr += QString::number( data.myInitialMemory ); + } + valStr += " -v "; + valStr += QString::number( data.myVerboseLevel ); + + if ( !data.myToCreateNewNodes ) + valStr += " -p0"; + + if ( data.myRemoveInitialCentralPoint ) + valStr += " -no_initial_central_point"; + + if ( data.myBoundaryRecovery ) + valStr += " -C"; + + if ( data.myFEMCorrection ) + valStr += " -FEM"; + + valStr += " "; + valStr += data.myTextOption; + +// valStr += " #BEGIN ENFORCED VERTICES#"; +// // Add size map parameters storage +// for (int i=0 ; irowCount() ; i++) { +// valStr += " ("; +// double x = mySmpModel->data(mySmpModel->index(i,ENF_VER_X_COLUMN)).toDouble(); +// double y = mySmpModel->data(mySmpModel->index(i,ENF_VER_Y_COLUMN)).toDouble(); +// double z = mySmpModel->data(mySmpModel->index(i,ENF_VER_Z_COLUMN)).toDouble(); +// double size = mySmpModel->data(mySmpModel->index(i,ENF_VER_SIZE_COLUMN)).toDouble(); +// valStr += QString::number( x ); +// valStr += ","; +// valStr += QString::number( y ); +// valStr += ","; +// valStr += QString::number( z ); +// valStr += ")="; +// valStr += QString::number( size ); +// if (i!=mySmpModel->rowCount()-1) +// valStr += ";"; +// } +// valStr += " #END ENFORCED VERTICES#"; +// MESSAGE(valStr.toStdString()); return valStr; } bool GHS3DPluginGUI_HypothesisCreator::readParamsFromHypo( GHS3DHypothesisData& h_data ) const { + MESSAGE("GHS3DPluginGUI_HypothesisCreator::readParamsFromHypo"); GHS3DPlugin::GHS3DPlugin_Hypothesis_var h = GHS3DPlugin::GHS3DPlugin_Hypothesis::_narrow( initParamsHypothesis() ); HypothesisData* data = SMESH::GetHypothesisData( hypType() ); h_data.myName = isCreation() && data ? hypName() : ""; - h_data.myToMeshHoles = h->GetToMeshHoles(); - h_data.myMaximumMemory = h->GetMaximumMemory(); - h_data.myInitialMemory = h->GetInitialMemory(); - h_data.myInitialMemory = h->GetInitialMemory(); - h_data.myOptimizationLevel = h->GetOptimizationLevel(); - h_data.myKeepFiles = h->GetKeepFiles(); - h_data.myWorkingDir = h->GetWorkingDirectory(); - h_data.myVerboseLevel = h->GetVerboseLevel(); - h_data.myToCreateNewNodes = h->GetToCreateNewNodes(); - h_data.myBoundaryRecovery = h->GetToUseBoundaryRecoveryVersion(); - h_data.myTextOption = h->GetTextOption(); + h_data.myToMeshHoles = h->GetToMeshHoles(); + h_data.myMaximumMemory = h->GetMaximumMemory(); + h_data.myInitialMemory = h->GetInitialMemory(); + h_data.myInitialMemory = h->GetInitialMemory(); + h_data.myOptimizationLevel = h->GetOptimizationLevel(); + h_data.myKeepFiles = h->GetKeepFiles(); + h_data.myWorkingDir = h->GetWorkingDirectory(); + h_data.myVerboseLevel = h->GetVerboseLevel(); + h_data.myToCreateNewNodes = h->GetToCreateNewNodes(); + h_data.myRemoveInitialCentralPoint = h->GetToRemoveCentralPoint(); + h_data.myBoundaryRecovery = h->GetToUseBoundaryRecoveryVersion(); + h_data.myFEMCorrection = h->GetFEMCorrection(); + h_data.myTextOption = h->GetTextOption(); + GHS3DPlugin::GHS3DEnforcedVertexList_var vertices = h->GetEnforcedVertices(); + MESSAGE("vertices->length(): " << vertices->length()); + h_data.myEnforcedVertices.clear(); + for (int i=0 ; ilength() ; i++) { + TEnfVertex* myVertex = new TEnfVertex(); + myVertex->name = CORBA::string_dup(vertices[i].name.in()); + myVertex->geomEntry = CORBA::string_dup(vertices[i].geomEntry.in()); + myVertex->groupName = CORBA::string_dup(vertices[i].groupName.in()); + myVertex->size = vertices[i].size; + myVertex->isCompound = vertices[i].isCompound; + if (vertices[i].coords.length()) { + for (int c = 0; c < vertices[i].coords.length() ; c++) + myVertex->coords.push_back(vertices[i].coords[c]); + MESSAGE("Add enforced vertex ("<< myVertex->coords.at(0) << ","<< myVertex->coords.at(1) << ","<< myVertex->coords.at(2) << ") ="<< myVertex->size); + } + h_data.myEnforcedVertices.insert(myVertex); + } + + GHS3DPlugin::GHS3DEnforcedMeshList_var enfMeshes = h->GetEnforcedMeshes(); + MESSAGE("enfMeshes->length(): " << enfMeshes->length()); + h_data.myEnforcedMeshes.clear(); + for (int i=0 ; ilength() ; i++) { + TEnfMesh* myEnfMesh = new TEnfMesh(); + myEnfMesh->name = CORBA::string_dup(enfMeshes[i].name.in()); + myEnfMesh->entry = CORBA::string_dup(enfMeshes[i].entry.in()); + myEnfMesh->groupName = CORBA::string_dup(enfMeshes[i].groupName.in()); + myEnfMesh->size = enfMeshes[i].size; + switch (enfMeshes[i].elementType) { + case SMESH::NODE: + myEnfMesh->elementType = 0; + break; + case SMESH::EDGE: + myEnfMesh->elementType = 1; + break; + case SMESH::FACE: + myEnfMesh->elementType = 2; + break; + default: + break; + } +// myEnfMesh->elementType = enfMeshes[i].elementType; + h_data.myEnforcedMeshes.insert(myEnfMesh); + } return true; } bool GHS3DPluginGUI_HypothesisCreator::storeParamsToHypo( const GHS3DHypothesisData& h_data ) const { + MESSAGE("GHS3DPluginGUI_HypothesisCreator::storeParamsToHypo"); GHS3DPlugin::GHS3DPlugin_Hypothesis_var h = GHS3DPlugin::GHS3DPlugin_Hypothesis::_narrow( hypothesis() ); @@ -340,11 +1789,84 @@ bool GHS3DPluginGUI_HypothesisCreator::storeParamsToHypo( const GHS3DHypothesisD h->SetVerboseLevel ( h_data.myVerboseLevel ); if ( h->GetToCreateNewNodes() != h_data.myToCreateNewNodes ) h->SetToCreateNewNodes( h_data.myToCreateNewNodes ); + if ( h->GetToRemoveCentralPoint() != h_data.myRemoveInitialCentralPoint ) + h->SetToRemoveCentralPoint( h_data.myRemoveInitialCentralPoint ); if ( h->GetToUseBoundaryRecoveryVersion() != h_data.myBoundaryRecovery ) h->SetToUseBoundaryRecoveryVersion( h_data.myBoundaryRecovery ); + if ( h->GetFEMCorrection() != h_data.myFEMCorrection ) + h->SetFEMCorrection( h_data.myFEMCorrection ); if ( h->GetTextOption() != h_data.myTextOption ) h->SetTextOption ( h_data.myTextOption.toLatin1().constData() ); - } + + // Enforced vertices + int nbVertex = (int) h_data.myEnforcedVertices.size(); + GHS3DPlugin::GHS3DEnforcedVertexList_var vertexHyp = h->GetEnforcedVertices(); + int nbVertexHyp = vertexHyp->length(); + + MESSAGE("Store params for size maps: " << nbVertex << " enforced vertices"); + MESSAGE("h->GetEnforcedVertices()->length(): " << nbVertexHyp); + + // 1. Clear all enforced vertices in hypothesis + // 2. Add new enforced vertex according to h_data + if ( nbVertexHyp > 0) + h->ClearEnforcedVertices(); + + TEnfVertexList::const_iterator it; + double x = 0, y = 0, z = 0; + for(it = h_data.myEnforcedVertices.begin() ; it != h_data.myEnforcedVertices.end(); it++ ) { + TEnfVertex* enfVertex = (*it); + x =y =z = 0; + if (enfVertex->coords.size()) { + x = enfVertex->coords.at(0); + y = enfVertex->coords.at(1); + z = enfVertex->coords.at(2); + } + ok = h->p_SetEnforcedVertex( enfVertex->size, x, y, z, enfVertex->name.c_str(), enfVertex->geomEntry.c_str(), enfVertex->groupName.c_str(), enfVertex->isCompound); + } // for + + // Enforced Meshes + int nbEnfMeshes = (int) h_data.myEnforcedMeshes.size(); + GHS3DPlugin::GHS3DEnforcedMeshList_var enfMeshListHyp = h->GetEnforcedMeshes(); + int nbEnfMeshListHyp = enfMeshListHyp->length(); + + MESSAGE("Store params for size maps: " << nbEnfMeshes << " enforced meshes"); + MESSAGE("h->GetEnforcedMeshes()->length(): " << nbEnfMeshListHyp); + + // 1. Clear all enforced vertices in hypothesis + // 2. Add new enforced vertex according to h_data + if ( nbEnfMeshListHyp > 0) + h->ClearEnforcedMeshes(); + + TEnfMeshList::const_iterator itEnfMesh; + _PTR(Study) aStudy = SMESH::GetActiveStudyDocument(); + for(itEnfMesh = h_data.myEnforcedMeshes.begin() ; itEnfMesh != h_data.myEnforcedMeshes.end(); itEnfMesh++ ) { + TEnfMesh* enfMesh = (*itEnfMesh); + + _PTR(SObject) aSObj = aStudy->FindObjectID(enfMesh->entry.c_str()); + SMESH::SMESH_IDSource_var theSource = SMESH::SObjectToInterface( aSObj ); + SMESH::ElementType elementType; + MESSAGE("enfMesh->elementType: " << enfMesh->elementType); + switch(enfMesh->elementType) { + case 0: + elementType = SMESH::NODE; + break; + case 1: + elementType = SMESH::EDGE; + break; + case 2: + elementType = SMESH::FACE; + break; + default: + break; + } + + ok = h->p_SetEnforcedMesh(theSource, elementType, enfMesh->size, enfMesh->groupName.c_str()); + } // for + } // try +// catch(const std::exception& ex) { +// std::cout << "Exception: " << ex.what() << std::endl; +// throw ex; +// } catch ( const SALOME::SALOME_Exception& ex ) { SalomeApp_Tools::QtCatchCorbaException( ex ); @@ -355,17 +1877,72 @@ bool GHS3DPluginGUI_HypothesisCreator::storeParamsToHypo( const GHS3DHypothesisD bool GHS3DPluginGUI_HypothesisCreator::readParamsFromWidgets( GHS3DHypothesisData& h_data ) const { - h_data.myName = myName ? myName->text() : ""; - h_data.myToMeshHoles = myToMeshHolesCheck->isChecked(); - h_data.myMaximumMemory = myMaximumMemoryCheck->isChecked() ? myMaximumMemorySpin->value() : -1; - h_data.myInitialMemory = myInitialMemoryCheck->isChecked() ? myInitialMemorySpin->value() : -1; - h_data.myOptimizationLevel = myOptimizationLevelCombo->currentIndex(); - h_data.myKeepFiles = myKeepFiles->isChecked(); - h_data.myWorkingDir = myWorkingDir->text().trimmed(); - h_data.myVerboseLevel = myVerboseLevelSpin->value(); - h_data.myToCreateNewNodes = myToCreateNewNodesCheck->isChecked(); - h_data.myBoundaryRecovery = myBoundaryRecoveryCheck->isChecked(); - h_data.myTextOption = myTextOption->text(); + MESSAGE("GHS3DPluginGUI_HypothesisCreator::readParamsFromWidgets"); + h_data.myName = myName ? myName->text() : ""; + h_data.myToMeshHoles = myToMeshHolesCheck->isChecked(); + h_data.myMaximumMemory = myMaximumMemoryCheck->isChecked() ? myMaximumMemorySpin->value() : -1; + h_data.myInitialMemory = myInitialMemoryCheck->isChecked() ? myInitialMemorySpin->value() : -1; + h_data.myOptimizationLevel = myOptimizationLevelCombo->currentIndex(); + h_data.myKeepFiles = myKeepFiles->isChecked(); + h_data.myWorkingDir = myWorkingDir->text().trimmed(); + h_data.myVerboseLevel = myVerboseLevelSpin->value(); + h_data.myToCreateNewNodes = myToCreateNewNodesCheck->isChecked(); + h_data.myRemoveInitialCentralPoint = myRemoveInitialCentralPointCheck->isChecked(); + h_data.myBoundaryRecovery = myBoundaryRecoveryCheck->isChecked(); + h_data.myFEMCorrection = myFEMCorrectionCheck->isChecked(); + h_data.myTextOption = myTextOption->text(); + + // Enforced vertices + h_data.myEnforcedVertices.clear(); + QVariant valueX, valueY, valueZ; + for (int row=0 ; rowrowCount() ; row++) { + + TEnfVertex *myVertex = new TEnfVertex(); + myVertex->name = myEnforcedTableWidget->item(row,ENF_VER_NAME_COLUMN)->data(Qt::EditRole).toString().toStdString(); + MESSAGE("Add new enforced vertex \"" << myVertex->name << "\"" ); + myVertex->geomEntry = myEnforcedTableWidget->item(row,ENF_VER_ENTRY_COLUMN)->data(Qt::EditRole).toString().toStdString(); + if (myVertex->geomEntry.size()) + MESSAGE("Geom entry is \"" << myVertex->geomEntry << "\"" ); + myVertex->groupName = myEnforcedTableWidget->item(row,ENF_VER_GROUP_COLUMN)->data(Qt::EditRole).toString().toStdString(); + if (myVertex->groupName.size()) + MESSAGE("Group name is \"" << myVertex->groupName << "\"" ); + valueX = myEnforcedTableWidget->item(row,ENF_VER_X_COLUMN)->data(Qt::EditRole); + valueY = myEnforcedTableWidget->item(row,ENF_VER_Y_COLUMN)->data(Qt::EditRole); + valueZ = myEnforcedTableWidget->item(row,ENF_VER_Z_COLUMN)->data(Qt::EditRole); + if (!valueX.isNull() && !valueY.isNull() && !valueZ.isNull()) { + myVertex->coords.push_back(valueX.toDouble()); + myVertex->coords.push_back(valueY.toDouble()); + myVertex->coords.push_back(valueZ.toDouble()); + MESSAGE("Coords are (" << myVertex->coords.at(0) << ", " + << myVertex->coords.at(1) << ", " + << myVertex->coords.at(2) << ")"); + } + myVertex->size = myEnforcedTableWidget->item(row,ENF_VER_SIZE_COLUMN)->data(Qt::EditRole).toDouble(); + MESSAGE("Size is " << myVertex->size); + myVertex->isCompound = myEnforcedTableWidget->item(row,ENF_VER_COMPOUND_COLUMN)->data(Qt::CheckStateRole).toBool(); + MESSAGE("Is compound ? " << myVertex->isCompound); + h_data.myEnforcedVertices.insert(myVertex); + } + + // Enforced meshes + h_data.myEnforcedMeshes.clear(); + + for (int row=0 ; rowrowCount() ; row++) { + + TEnfMesh *myEnfMesh = new TEnfMesh(); + myEnfMesh->name = myEnforcedMeshTableWidget->item(row,ENF_MESH_NAME_COLUMN)->data(Qt::EditRole).toString().toStdString(); + MESSAGE("Add new enforced mesh \"" << myEnfMesh->name << "\"" ); + myEnfMesh->entry = myEnforcedMeshTableWidget->item(row,ENF_MESH_ENTRY_COLUMN)->data(Qt::EditRole).toString().toStdString(); + MESSAGE("Entry is \"" << myEnfMesh->entry << "\"" ); + myEnfMesh->groupName = myEnforcedMeshTableWidget->item(row,ENF_MESH_GROUP_COLUMN)->data(Qt::EditRole).toString().toStdString(); + MESSAGE("Group name is \"" << myEnfMesh->groupName << "\"" ); + myEnfMesh->size = myEnforcedMeshTableWidget->item(row,ENF_MESH_SIZE_COLUMN)->data(Qt::EditRole).toDouble(); + MESSAGE("Size is " << myEnfMesh->size); + QComboBox* combo = qobject_cast(myEnforcedMeshTableWidget->cellWidget(row,ENF_MESH_CONSTRAINT_COLUMN)); + myEnfMesh->elementType = combo->currentIndex(); + MESSAGE("Element type: " << myEnfMesh->elementType); + h_data.myEnforcedMeshes.insert(myEnfMesh); + } return true; } @@ -389,19 +1966,3 @@ QString GHS3DPluginGUI_HypothesisCreator::helpPage() const { return "ghs3d_hypo_page.html"; } - -//============================================================================= -/*! GetHypothesisCreator - * - */ -//============================================================================= -extern "C" -{ - GHS3DPLUGIN_EXPORT - SMESHGUI_GenericHypothesisCreator* GetHypothesisCreator( const QString& aHypType ) - { - if ( aHypType == "GHS3D_Parameters" ) - return new GHS3DPluginGUI_HypothesisCreator( aHypType ); - return 0; - } -} diff --git a/src/GUI/GHS3DPluginGUI_HypothesisCreator.h b/src/GUI/GHS3DPluginGUI_HypothesisCreator.h index 55c7433..693f9ce 100644 --- a/src/GUI/GHS3DPluginGUI_HypothesisCreator.h +++ b/src/GUI/GHS3DPluginGUI_HypothesisCreator.h @@ -1,21 +1,22 @@ -// Copyright (C) 2004-2008 CEA/DEN, EDF R&D +// Copyright (C) 2004-2012 CEA/DEN, EDF R&D // -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License. +// 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. +// 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 +// 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 +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // + // GHS3DPlugin GUI: GUI for plugged-in mesher GHS3DPlugin // File : GHS3DPluginGUI_HypothesisCreator.h // Author : Michael Zorin @@ -24,35 +25,134 @@ #ifndef GHS3DPLUGINGUI_HypothesisCreator_HeaderFile #define GHS3DPLUGINGUI_HypothesisCreator_HeaderFile -#include "GHS3DPlugin_Defs.hxx" +#ifdef WIN32 + #if defined GHS3DPluginGUI_EXPORTS + #define GHS3DPLUGINGUI_EXPORT __declspec( dllexport ) + #else + #define GHS3DPLUGINGUI_EXPORT __declspec( dllimport ) + #endif +#else + #define GHS3DPLUGINGUI_EXPORT +#endif + #include +#include +#include + +#include +#include +#include +#include +#include +#include CORBA_SERVER_HEADER(GHS3DPlugin_Algorithm) +#include CORBA_SERVER_HEADER(SMESH_Gen) +#include CORBA_SERVER_HEADER(SMESH_Mesh) class QWidget; class QComboBox; class QCheckBox; class QLineEdit; class QSpinBox; +class QTableWidget; +class QTableWidgetItem; +class QHeaderView; + +class SMESHGUI_SpinBox; +class StdMeshersGUI_ObjectReferenceParamWdg; +class LightApp_SelectionMgr; +class SUIT_SelectionFilter; + +class QTEnfVertex +{ + +public: + QTEnfVertex(double size, double x=0., double y=0., double z=0., QString name="", QString geomEntry="", QString groupName="", bool isCompound = false); + +private: + bool operator == (const QTEnfVertex* other) const { + if (other) { + if (this->coords.size() && other->coords.size()) + return (this->coords == other->coords); + else + return (this->geomEntry == other->geomEntry); + } + } + + QString name; + QString geomEntry; + bool isCompound; + QString groupName; + double size; + std::vector coords; +}; + +typedef QList< QTEnfVertex* > QEnfVertexList; + +// Enforced vertex +struct TEnfVertex{ + std::string name; + std::string geomEntry; + bool isCompound; + std::vector coords; + std::string groupName; + double size; +}; + +struct CompareEnfVertices +{ + bool operator () (const TEnfVertex* e1, const TEnfVertex* e2) const { + if (e1 && e2) { + if (e1->coords.size() && e2->coords.size()) + return (e1->coords < e2->coords); + else + return (e1->geomEntry < e2->geomEntry); + } + return false; + } +}; + +// List of enforced vertices +typedef std::set< TEnfVertex*, CompareEnfVertices > TEnfVertexList; + +// Enforced mesh +struct TEnfMesh{ + std::string name; + std::string entry; + int elementType; + std::string groupName; + double size; +}; + +struct CompareEnfMeshes +{ + bool operator () (const TEnfMesh* e1, const TEnfMesh* e2) const { + if (e1 && e2) { + if (e1->entry == e2->entry) + return (e1->elementType < e2->elementType); + else + return (e1->entry < e2->entry); + } + else + return false; + } +}; +// List of enforced meshes +typedef std::set< TEnfMesh*, CompareEnfMeshes > TEnfMeshList; typedef struct { - bool myToMeshHoles; - int myMaximumMemory; - int myInitialMemory; - int myOptimizationLevel; - bool myKeepFiles; - QString myWorkingDir; - QString myName; + bool myToMeshHoles,myKeepFiles,myToCreateNewNodes,myBoundaryRecovery,myFEMCorrection,myRemoveInitialCentralPoint; + int myMaximumMemory,myInitialMemory,myOptimizationLevel; + QString myName,myWorkingDir,myTextOption; short myVerboseLevel; - bool myToCreateNewNodes; - bool myBoundaryRecovery; - QString myTextOption; - + TEnfVertexList myEnforcedVertices; + TEnfMeshList myEnforcedMeshes; } GHS3DHypothesisData; /*! \brief Class for creation of GHS3D2D and GHS3D3D hypotheses */ -class GHS3DPLUGIN_EXPORT GHS3DPluginGUI_HypothesisCreator : public SMESHGUI_GenericHypothesisCreator +class GHS3DPLUGINGUI_EXPORT GHS3DPluginGUI_HypothesisCreator : public SMESHGUI_GenericHypothesisCreator { Q_OBJECT @@ -60,7 +160,7 @@ public: GHS3DPluginGUI_HypothesisCreator( const QString& ); virtual ~GHS3DPluginGUI_HypothesisCreator(); - virtual bool checkParams() const; + virtual bool checkParams(QString& msg) const; virtual QString helpPage() const; protected: @@ -73,31 +173,126 @@ protected: virtual QString type() const; protected slots: - void onDirBtnClicked(); - void updateWidgets(); - + void onDirBtnClicked(); + void updateWidgets(); + + void addEnforcedVertex(double x=0, double y=0, double z=0, double size = 0, + std::string vertexName = "", std::string geomEntry = "", std::string groupName = "", + bool isCompound = false); + void onAddEnforcedVertex(); + void onRemoveEnforcedVertex(); + void synchronizeCoords(); + void updateEnforcedVertexValues(QTableWidgetItem* ); + void onSelectEnforcedVertex(); + void clearEnforcedVertexWidgets(); + void checkVertexIsDefined(); + void clearEnfVertexSelection(); + + void addEnforcedMesh(std::string name, std::string entry, int elementType, double size = 0, std::string groupName = ""); + void onAddEnforcedMesh(); + void onRemoveEnforcedMesh(); + //void synchronizeEnforcedMesh(); + void checkEnfMeshIsDefined(); + +signals: + void vertexDefined(bool); + void enfMeshDefined(bool); + private: - bool readParamsFromHypo( GHS3DHypothesisData& ) const; - bool readParamsFromWidgets( GHS3DHypothesisData& ) const; - bool storeParamsToHypo( const GHS3DHypothesisData& ) const; + bool readParamsFromHypo( GHS3DHypothesisData& ) const; + bool readParamsFromWidgets( GHS3DHypothesisData& ) const; + bool storeParamsToHypo( const GHS3DHypothesisData& ) const; + GeomSelectionTools* getGeomSelectionTool(); + GEOM::GEOM_Gen_var getGeomEngine(); private: - QWidget* myStdGroup; - QLineEdit* myName; - QCheckBox* myToMeshHolesCheck; - QComboBox* myOptimizationLevelCombo; - - QWidget* myAdvGroup; - QCheckBox* myMaximumMemoryCheck; - QSpinBox* myMaximumMemorySpin; - QCheckBox* myInitialMemoryCheck; - QSpinBox* myInitialMemorySpin; - QLineEdit* myWorkingDir; - QCheckBox* myKeepFiles; - QSpinBox* myVerboseLevelSpin; - QCheckBox* myToCreateNewNodesCheck; - QCheckBox* myBoundaryRecoveryCheck; - QLineEdit* myTextOption; + QWidget* myStdGroup; + QLineEdit* myName; + QCheckBox* myToMeshHolesCheck; + QComboBox* myOptimizationLevelCombo; + + QWidget* myAdvGroup; + QCheckBox* myMaximumMemoryCheck; + QSpinBox* myMaximumMemorySpin; + QCheckBox* myInitialMemoryCheck; + QSpinBox* myInitialMemorySpin; + QLineEdit* myWorkingDir; + QCheckBox* myKeepFiles; + QSpinBox* myVerboseLevelSpin; + QCheckBox* myToCreateNewNodesCheck; + QCheckBox* myRemoveInitialCentralPointCheck; + QCheckBox* myBoundaryRecoveryCheck; + QCheckBox* myFEMCorrectionCheck; + QLineEdit* myTextOption; + + QWidget* myEnfGroup; + QPixmap iconVertex, iconCompound; + StdMeshersGUI_ObjectReferenceParamWdg *myEnfVertexWdg; + GEOM::GEOM_Object_var myEnfVertex; + QTableWidget* myEnforcedTableWidget; + SMESHGUI_SpinBox* myXCoord; + SMESHGUI_SpinBox* myYCoord; + SMESHGUI_SpinBox* myZCoord; + SMESHGUI_SpinBox* mySizeValue; + QLineEdit* myGroupName; +// QGroupBox* makeGroupsCheck; +// QCheckBox* myGlobalGroupName; + QPushButton* addVertexButton; + QPushButton* removeVertexButton; + + QWidget* myEnfMeshGroup; + StdMeshersGUI_ObjectReferenceParamWdg *myEnfMeshWdg; +// SMESH::SMESH_IDSource_var myEnfMesh; + QComboBox* myEnfMeshConstraint; + QStringList myEnfMeshConstraintLabels; +// SMESH::mesh_array_var myEnfMeshArray; + QTableWidget* myEnforcedMeshTableWidget; + SMESHGUI_SpinBox* myMeshSizeValue; + QLineEdit* myMeshGroupName; + QPushButton* addEnfMeshButton; + QPushButton* removeEnfMeshButton; + + GeomSelectionTools* GeomToolSelected; +// SVTK_Selector* mySelector; +// LightApp_SelectionMgr* mySelectionMgr; /* User shape selection */ +}; + +class EnforcedVertexTableWidgetDelegate : public QItemDelegate +{ + Q_OBJECT + +public: + EnforcedVertexTableWidgetDelegate(QObject *parent = 0); + + QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, + const QModelIndex &index) const; + + void setEditorData(QWidget *editor, const QModelIndex &index) const; + void setModelData(QWidget *editor, QAbstractItemModel *model, + const QModelIndex &index) const; + + void updateEditorGeometry(QWidget *editor, + const QStyleOptionViewItem &option, const QModelIndex &index) const; + + bool vertexExists(QAbstractItemModel *model, const QModelIndex &index, QString value) const; +}; + +class EnforcedMeshTableWidgetDelegate : public QItemDelegate +{ + Q_OBJECT + +public: + EnforcedMeshTableWidgetDelegate(QObject *parent = 0); + + QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, + const QModelIndex &index) const; + + void setEditorData(QWidget *editor, const QModelIndex &index) const; + void setModelData(QWidget *editor, QAbstractItemModel *model, + const QModelIndex &index) const; + + void updateEditorGeometry(QWidget *editor, + const QStyleOptionViewItem &option, const QModelIndex &index) const; }; #endif diff --git a/src/GUI/GHS3DPlugin_images.ts b/src/GUI/GHS3DPlugin_images.ts index 14c420b..7f59dfe 100644 --- a/src/GUI/GHS3DPlugin_images.ts +++ b/src/GUI/GHS3DPlugin_images.ts @@ -1,25 +1,6 @@ + - - + @default diff --git a/src/GUI/GHS3DPlugin_msg_en.ts b/src/GUI/GHS3DPlugin_msg_en.ts index cf795b8..65569d8 100644 --- a/src/GUI/GHS3DPlugin_msg_en.ts +++ b/src/GUI/GHS3DPlugin_msg_en.ts @@ -1,110 +1,207 @@ + - - - - @default - - GHS3D_ADV_ARGS - Advanced - - - GHS3D_HYPOTHESIS - GHS3D - - - GHS3D_OPTIMIZATIOL_LEVEL - Optimization level - - - GHS3D_PERMISSION_DENIED - Working directory is not writable - - - GHS3D_STD_ARGS - Parameters - - - GHS3D_TITLE - Hypothesis Construction - - - GHS3D_TO_MESH_HOLES - To mesh holes - - - INIT_MEMORY_SIZE - Initial memory size - - - KEEP_WORKING_FILES - To keep working files - - - LEVEL_LIGHT - Light - - - LEVEL_MEDIUM - Medium (standard) - - - LEVEL_NONE - None - - - LEVEL_STRONG - Strong - - - MAX_MEMORY_SIZE - Maximum memory size - - - MEGABYTE - Megabytes - - - RECOVERY_VERSION - To use boundary recovery version - - - SELECT_DIR - ... - - - TEXT_OPTION - Option as text - - - TO_ADD_NODES - To create new nodes - - - VERBOSE_LEVEL - Verbose level - - - WORKING_DIR - Working directory - - + + + @default + + GHS3D_ADV_ARGS + Advanced + + + GHS3D_HYPOTHESIS + GHS3D + + + GHS3D_OPTIMIZATIOL_LEVEL + Optimization level + + + GHS3D_PERMISSION_DENIED + Working directory is not writable + + + GHS3D_STD_ARGS + Parameters + + + GHS3D_TITLE + Hypothesis Construction + + + GHS3D_TO_MESH_HOLES + To mesh holes + + + INIT_MEMORY_SIZE + Initial memory size + + + KEEP_WORKING_FILES + To keep working files + + + LEVEL_NONE + None + + + LEVEL_LIGHT + Light + + + LEVEL_MEDIUM + Medium (standard) + + + LEVEL_STANDARDPLUS + Standard+ + + + LEVEL_STRONG + Strong + + + MAX_MEMORY_SIZE + Maximum memory size + + + MEGABYTE + Megabytes + + + NO_INITIAL_CENTRAL_POINT + To remove initial central point + + + RECOVERY_VERSION + To use boundary recovery version + + + FEM_CORRECTION + To use FEM correction + + + SELECT_DIR + ... + + + TEXT_OPTION + Option as text + + + TO_ADD_NODES + To create new nodes + + + VERBOSE_LEVEL + Verbose level + + + WORKING_DIR + Working directory + + + GHS3D_ENFORCED_VERTICES + Enforced vertices + + + GHS3D_ENFORCED_MESHES + Enforced meshes + + + GHS3D_ENF_NAME_COLUMN + Name + + + GHS3D_ENF_VER_X_COLUMN + X + + + GHS3D_ENF_VER_Y_COLUMN + Y + + + GHS3D_ENF_VER_Z_COLUMN + Z + + + GHS3D_ENF_SIZE_COLUMN + Size + + + GHS3D_ENF_ENTRY_COLUMN + Vertex Entry + + + GHS3D_ENF_MESH_CONSTRAINT_COLUMN + Constraint + + + GHS3D_ENF_VER_COMPOUND_COLUMN + Compound + + + GHS3D_ENF_GROUP_COLUMN + Group + + + GHS3D_ENF_SELECT_VERTEX + Select a vertex + + + GHS3D_ENF_SELECT_MESH + Select a mesh + + + GHS3D_ENF_VER_X_LABEL + X: + + + GHS3D_ENF_VER_Y_LABEL + Y: + + + GHS3D_ENF_VER_Z_LABEL + Z: + + + GHS3D_ENF_MESH_CONSTRAINT_LABEL + Constraint: + + + GHS3D_ENF_MESH_CONSTRAINT_NODE + Nodes + + + GHS3D_ENF_MESH_CONSTRAINT_EDGE + Edges + + + GHS3D_ENF_MESH_CONSTRAINT_FACE + Faces + + + GHS3D_ENF_SIZE_LABEL + Size: + + + GHS3D_ENF_GROUP_LABEL + Group: + + + GHS3D_ENF_ADD + Add + + + GHS3D_ENF_REMOVE + Remove + + + GHS3D_ENF_VER_INFO + <b>Warning</b>: Enforced vertices are currently only taken into account for meshes w/o associated geometry. + + + GHS3D_ENF_MESH_INFO + <b>Warning</b>: Enforced meshes are currently only taken into account for meshes w/o associated geometry. + + diff --git a/src/GUI/GHS3DPlugin_msg_fr.ts b/src/GUI/GHS3DPlugin_msg_fr.ts new file mode 100755 index 0000000..86452f3 --- /dev/null +++ b/src/GUI/GHS3DPlugin_msg_fr.ts @@ -0,0 +1,207 @@ + + + + + @default + + GHS3D_ADV_ARGS + Avancé + + + GHS3D_HYPOTHESIS + GHS3D + + + GHS3D_OPTIMIZATIOL_LEVEL + Niveau d'optimisation + + + GHS3D_PERMISSION_DENIED + Il n'est pas possible d'écrire dans le répertoire + + + GHS3D_STD_ARGS + Paramètres + + + GHS3D_TITLE + Construction de l'hypothèse + + + GHS3D_TO_MESH_HOLES + Mailler les trous + + + INIT_MEMORY_SIZE + Taille initiale de la mémoire + + + KEEP_WORKING_FILES + Conserver les fichiers temporaires + + + LEVEL_NONE + Zéro + + + LEVEL_LIGHT + Léger + + + LEVEL_MEDIUM + Moyen (standard) + + + LEVEL_STANDARDPLUS + Standard+ + + + LEVEL_STRONG + Fort + + + MAX_MEMORY_SIZE + Taille maximale de la mémoire + + + MEGABYTE + Megabytes + + + NO_INITIAL_CENTRAL_POINT + Supprimer le point central initial + + + RECOVERY_VERSION + Utiliser la version de restauration des frontières + + + FEM_CORRECTION + Utiliser correction FEM + + + SELECT_DIR + ... + + + TEXT_OPTION + Option comme texte + + + TO_ADD_NODES + Créer de nouveaux nœuds + + + VERBOSE_LEVEL + Niveau de verbosité + + + WORKING_DIR + Répertoire de travail + + + GHS3D_ENFORCED_VERTICES + Points de passage + + + GHS3D_ENFORCED_MESHES + Maillages de contrainte + + + GHS3D_ENF_NAME_COLUMN + Nom + + + GHS3D_ENF_VER_X_COLUMN + X + + + GHS3D_ENF_VER_Y_COLUMN + Y + + + GHS3D_ENF_VER_Z_COLUMN + Z + + + GHS3D_ENF_SIZE_COLUMN + Taille + + + GHS3D_ENF_ENTRY_COLUMN + ID de point + + + GHS3D_ENF_MESH_CONSTRAINT_COLUMN + Contrainte + + + GHS3D_ENF_VER_COMPOUND_COLUMN + Compound + + + GHS3D_ENF_GROUP_COLUMN + Groupe + + + GHS3D_ENF_SELECT_VERTEX + Sélectionnez une/des point(s) + + + GHS3D_ENF_SELECT_MESH + Sélectionnez une/des maillage(s) + + + GHS3D_ENF_VER_X_LABEL + X: + + + GHS3D_ENF_VER_Y_LABEL + Y: + + + GHS3D_ENF_VER_Z_LABEL + Z: + + + GHS3D_ENF_MESH_CONSTRAINT_LABEL + Contrainte: + + + GHS3D_ENF_MESH_CONSTRAINT_NODE + Noeuds + + + GHS3D_ENF_MESH_CONSTRAINT_EDGE + Segments + + + GHS3D_ENF_MESH_CONSTRAINT_FACE + Faces + + + GHS3D_ENF_SIZE_LABEL + Taille: + + + GHS3D_ENF_GROUP_LABEL + Groupe: + + + GHS3D_ENF_ADD + Ajouter + + + GHS3D_ENF_REMOVE + Supprimer + + + GHS3D_ENF_VER_INFO + <b>Attention</b>: Les points de passage ne sont pris en compte que pour des maillage sans géométrie associée. + + + GHS3D_ENF_MESH_INFO + <b>Attention</b>: Les éléments de contraintes ne sont pris en compte que pour des maillage sans géométrie associée. + + + diff --git a/src/GUI/Makefile.am b/src/GUI/Makefile.am index 83b7dd9..e0331d3 100644 --- a/src/GUI/Makefile.am +++ b/src/GUI/Makefile.am @@ -1,21 +1,22 @@ -# Copyright (C) 2004-2008 CEA/DEN, EDF R&D +# Copyright (C) 2004-2012 CEA/DEN, EDF R&D # -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License. +# 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. +# 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 +# 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 +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com # + # -* Makefile *- # Author : Edward AGAPOV (OCC) # Modified by : Alexander BORODIN (OCN) - autotools usage @@ -25,37 +26,49 @@ include $(top_srcdir)/adm_local/unix/make_common_starter.am # header files -salomeinclude_HEADERS = +salomeinclude_HEADERS = \ + GHS3DPluginGUI_HypothesisCreator.h \ + GHS3DPluginGUI_Enums.h # Libraries targets lib_LTLIBRARIES = libGHS3DPluginGUI.la -dist_libGHS3DPluginGUI_la_SOURCES = GHS3DPluginGUI_HypothesisCreator.cxx - -MOC_FILES = GHS3DPluginGUI_HypothesisCreator_moc.cxx -nodist_libGHS3DPluginGUI_la_SOURCES= $(MOC_FILES) - -libGHS3DPluginGUI_la_CPPFLAGS = \ - $(QT_INCLUDES) \ - $(KERNEL_CXXFLAGS) \ - $(GUI_CXXFLAGS) \ - $(GEOM_CXXFLAGS) \ - $(MED_CXXFLAGS) \ - $(SMESH_CXXFLAGS) \ - $(BOOST_CPPFLAGS) \ - $(CORBA_CXXFLAGS) \ - $(CORBA_INCLUDES) \ - $(CAS_CPPFLAGS) \ - -I$(srcdir)/.. \ - -I$(top_builddir)/idl \ - -I$(top_builddir)/salome_adm/unix +dist_libGHS3DPluginGUI_la_SOURCES = \ + GHS3DPluginGUI.cxx \ + GHS3DPluginGUI_HypothesisCreator.cxx + +MOC_FILES = \ + GHS3DPluginGUI_HypothesisCreator_moc.cxx + +nodist_libGHS3DPluginGUI_la_SOURCES= \ + $(MOC_FILES) + +libGHS3DPluginGUI_la_CPPFLAGS = \ + $(QT_INCLUDES) \ + $(CAS_CPPFLAGS) \ + $(KERNEL_CXXFLAGS) \ + $(GUI_CXXFLAGS) \ + $(GEOM_CXXFLAGS) \ + $(MED_CXXFLAGS) \ + $(SMESH_CXXFLAGS) \ + $(BOOST_CPPFLAGS) \ + $(CORBA_CXXFLAGS) \ + $(CORBA_INCLUDES) \ + -I$(srcdir)/../GHS3DPlugin \ + -I$(top_builddir)/idl libGHS3DPluginGUI_la_LDFLAGS = \ ../../idl/libSalomeIDLGHS3DPLUGIN.la \ - $(SMESH_LDFLAGS) -lSMESH \ + $(QT_LIBS) \ + $(KERNEL_LDFLAGS) -lSALOMELocalTrace \ + $(MED_LDFLAGS) -lSalomeIDLMED \ + $(GEOM_LDFLAGS) -lGEOM \ + $(SMESH_LDFLAGS) -lSMESH -lGeomSelectionTools -lStdMeshersGUI -lSMESHFiltersSelection \ + $(GUI_LDFLAGS) -lsuit -lqtx -lSalomeApp \ $(CAS_KERNEL) # resources files nodist_salomeres_DATA= \ GHS3DPlugin_images.qm \ - GHS3DPlugin_msg_en.qm + GHS3DPlugin_msg_en.qm \ + GHS3DPlugin_msg_fr.qm diff --git a/src/Makefile.am b/src/Makefile.am index e42af47..4f68158 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,21 +1,22 @@ -# Copyright (C) 2004-2008 CEA/DEN, EDF R&D +# Copyright (C) 2004-2012 CEA/DEN, EDF R&D # -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License. +# 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. +# 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 +# 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 +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com # + # -* Makefile *- # Author : Edward AGAPOV (OCC) # Modified by : Alexander BORODIN (OCN) - autotools usage @@ -24,43 +25,10 @@ # include $(top_srcdir)/adm_local/unix/make_common_starter.am +SUBDIRS = GHS3DPlugin + if GHS3DPLUGIN_ENABLE_GUI - SUBDIRS = GUI + SUBDIRS += GUI endif -DIST_SUBDIRS = GUI - -# header files -salomeinclude_HEADERS = \ - GHS3DPlugin_Defs.hxx \ - GHS3DPlugin_GHS3D.hxx \ - GHS3DPlugin_GHS3D_i.hxx \ - GHS3DPlugin_Hypothesis.hxx \ - GHS3DPlugin_Hypothesis_i.hxx - -# Libraries targets -lib_LTLIBRARIES = libGHS3DEngine.la - -dist_libGHS3DEngine_la_SOURCES = \ - GHS3DPlugin_GHS3D.cxx \ - GHS3DPlugin_GHS3D_i.cxx \ - GHS3DPlugin_i.cxx \ - GHS3DPlugin_Hypothesis.cxx \ - GHS3DPlugin_Hypothesis_i.cxx - -libGHS3DEngine_la_CPPFLAGS = \ - $(KERNEL_CXXFLAGS) \ - $(CAS_CPPFLAGS) \ - $(GEOM_CXXFLAGS) \ - $(MED_CXXFLAGS) \ - $(SMESH_CXXFLAGS) \ - $(BOOST_CPPFLAGS) \ - $(CORBA_CXXFLAGS) \ - $(CORBA_INCLUDES) \ - -I$(top_builddir)/idl \ - -I$(top_builddir)/salome_adm/unix - -libGHS3DEngine_la_LDFLAGS = \ - ../idl/libSalomeIDLGHS3DPLUGIN.la \ - $(SMESH_LDFLAGS) -lSMESHimpl -lSMESHEngine - $(KERNEL_LDFLAGS) -lSalomeGenericObj +DIST_SUBDIRS = GHS3DPlugin GUI -- 2.39.2

    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 literal 0 HcmV?d00001 diff --git a/doc/salome/gui/GHS3DPLUGIN/images/ghs3d_screenshot_enf2.png b/doc/salome/gui/GHS3DPLUGIN/images/ghs3d_screenshot_enf2.png new file mode 100644 index 0000000000000000000000000000000000000000..5daf8a26952fde18e16200b3514741cbe53e3699 GIT binary patch literal 91984 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