From 050d4f68cef408bbfb95f69f1f3ac1f3701034c3 Mon Sep 17 00:00:00 2001 From: gdd Date: Wed, 17 Oct 2012 14:42:42 +0000 Subject: [PATCH] Merge from BR_meshgems --- adm_local/cmake_files/FindCADSURF.cmake | 46 + .../config_files/check_MESHGEMS_CADSURF.m4 | 129 +++ configure.ac | 18 +- .../BLSURFPLUGIN/images/blsurf_parameters.png | Bin 37081 -> 53508 bytes .../images/blsurf_parameters_advanced.png | Bin 36675 -> 35575 bytes .../gui/BLSURFPLUGIN/input/blsurf_hypo.doc | 260 ++---- doc/salome/gui/BLSURFPLUGIN/input/index.doc | 2 +- idl/BLSURFPlugin_Algorithm.idl | 153 +++- src/BLSURFPlugin/BLSURFPluginDC.py | 769 +++++++++------- src/BLSURFPlugin/BLSURFPlugin_BLSURF.cxx | 641 ++++++++------ src/BLSURFPlugin/BLSURFPlugin_BLSURF.hxx | 6 +- src/BLSURFPlugin/BLSURFPlugin_Hypothesis.cxx | 560 ++++++++---- src/BLSURFPlugin/BLSURFPlugin_Hypothesis.hxx | 152 ++-- .../BLSURFPlugin_Hypothesis_i.cxx | 548 +++++++++--- .../BLSURFPlugin_Hypothesis_i.hxx | 82 +- src/BLSURFPlugin/Makefile.am | 30 +- src/GUI/BLSURFPluginGUI_AdvWidget.cxx | 56 ++ src/GUI/BLSURFPluginGUI_AdvWidget_QTD.ui | 202 +++++ src/GUI/BLSURFPluginGUI_Dlg.h | 106 +++ src/GUI/BLSURFPluginGUI_HypothesisCreator.cxx | 835 +++++++----------- src/GUI/BLSURFPluginGUI_HypothesisCreator.h | 122 +-- src/GUI/BLSURFPluginGUI_StdWidget.cxx | 164 ++++ src/GUI/BLSURFPluginGUI_StdWidget_QTD.ui | 548 ++++++++++++ src/GUI/BLSURFPlugin_msg_en.ts | 171 +++- src/GUI/BLSURFPlugin_msg_fr.ts | 169 +++- src/GUI/Makefile.am | 18 +- 26 files changed, 3836 insertions(+), 1951 deletions(-) create mode 100644 adm_local/cmake_files/FindCADSURF.cmake create mode 100644 adm_local/unix/config_files/check_MESHGEMS_CADSURF.m4 create mode 100644 src/GUI/BLSURFPluginGUI_AdvWidget.cxx create mode 100644 src/GUI/BLSURFPluginGUI_AdvWidget_QTD.ui create mode 100644 src/GUI/BLSURFPluginGUI_Dlg.h create mode 100644 src/GUI/BLSURFPluginGUI_StdWidget.cxx create mode 100644 src/GUI/BLSURFPluginGUI_StdWidget_QTD.ui diff --git a/adm_local/cmake_files/FindCADSURF.cmake b/adm_local/cmake_files/FindCADSURF.cmake new file mode 100644 index 0000000..1954cb7 --- /dev/null +++ b/adm_local/cmake_files/FindCADSURF.cmake @@ -0,0 +1,46 @@ +# 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 +# + +SET(MESHGEMSHOME $ENV{MESHGEMSHOME}) +FIND_PATH(CADSURF_INCLUDES_DIR meshgems/cadsurf.h ${MESHGEMSHOME}/include) +SET(CADSURF_INCLUDES) +SET(CADSURF_INCLUDES ${CADSURF_INCLUDES} -I${CADSURF_INCLUDES_DIR}) + +SET(CADSURF_LIBS_PATHS) +SET(CADSURF_LIBS_PATHS ${CADSURF_LIBS_PATHS} ${MESHGEMSHOME}/lib) +IF(WINDOWS) + SET(CADSURF_LIBS_PATHS ${CADSURF_LIBS_PATHS} ${MESHGEMSHOME}/lib/WinXP_VC9) +ELSE(WINDOWS) + IF(CMAKE_SIZEOF_VOID_P STREQUAL 8) + SET(CADSURF_LIBS_PATHS ${CADSURF_LIBS_PATHS} ${MESHGEMSHOME}/lib/Linux_64) + ELSE() + SET(CADSURF_LIBS_PATHS ${CADSURF_LIBS_PATHS} ${MESHGEMSHOME}/lib/Linux) + ENDIF() +ENDIF(WINDOWS) + +FIND_LIBRARY(mg-cadsurf mg-cadsurf PATHS ${CADSURF_LIBS_PATHS}) +FIND_LIBRARY(mg-precad mg-precad PATHS ${CADSURF_LIBS_PATHS}) +FIND_LIBRARY(meshgems meshgems PATHS ${CADSURF_LIBS_PATHS}) + +SET(CADSURF_LIBS) +SET(CADSURF_LIBS ${CADSURF_LIBS} ${mg-cadsurf}) +SET(CADSURF_LIBS ${CADSURF_LIBS} ${mg-precad}) +IF(meshgems) + SET(CADSURF_LIBS ${CADSURF_LIBS} ${meshgems}) +ENDIF(meshgems) diff --git a/adm_local/unix/config_files/check_MESHGEMS_CADSURF.m4 b/adm_local/unix/config_files/check_MESHGEMS_CADSURF.m4 new file mode 100644 index 0000000..d2a0914 --- /dev/null +++ b/adm_local/unix/config_files/check_MESHGEMS_CADSURF.m4 @@ -0,0 +1,129 @@ +dnl Copyright (C) 2007-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 +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 +dnl See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +dnl + +dnl File : check_MESHGEMS_CADSURF.m4 +dnl Author : Gilles DAVID, Open CASCADE S.A.S (gilles.david@opencascade.com) +dnl +AC_DEFUN([CHECK_MESHGEMS_CADSURF],[ + +AC_REQUIRE([AC_PROG_CXX])dnl +AC_REQUIRE([AC_PROG_CXXCPP])dnl + +AC_CHECKING([for MeshGems-CADSurf commercial product]) + +AC_LANG_SAVE +AC_LANG_CPLUSPLUS + +MESHGEMS_CADSURF_INCLUDES="" +MESHGEMS_CADSURF_LIBS="" + +AC_ARG_WITH([meshgems], + [ --with_meshgems=DIR root directory path of MeshGems-CADSurf installation]) + +CADSURF_ok=no + +if test "$with_meshgems" != "no" ; then + if test "$with_meshgems" == "yes" || test "$with_meshgems" == "auto"; then + MESHGEMS_CADSURF_HOME="" + else + MESHGEMS_CADSURF_HOME="$with_meshgems" + fi + + if test "$MESHGEMS_CADSURF_HOME" == "" ; then + if test "x$MESHGEMS_CADSURFHOME" != "x" ; then + MESHGEMS_CADSURF_HOME=$MESHGEMS_CADSURFHOME + fi + if test "x$CADSURFHOME" != "x" ; then + MESHGEMS_CADSURF_HOME=$CADSURFHOME + fi + if test "x$MESHGEMSHOME" != "x" ; then + MESHGEMS_CADSURF_HOME=$MESHGEMSHOME + fi + fi + + if test "x$MESHGEMS_CADSURF_HOME" != "x"; then + + echo + echo ------------------------------------------------- + echo You are about to choose to use somehow the + echo MeshGems-CADSurf commercial product to generate 2D mesh. + echo + + LOCAL_INCLUDES="-I$MESHGEMS_CADSURF_HOME/include" + LOCAL_LIBS="-L$MESHGEMS_CADSURF_HOME/lib/Linux" + archtest="$(`which arch`)" + if test "x$archtest" = "x" ; then + archtest="`uname -m`" + fi + if test $archtest = "x86_64" ; then + LOCAL_LIBS="-L$MESHGEMS_CADSURF_HOME/lib/Linux_64" + fi + LOCAL_LIBS="${LOCAL_LIBS} -lmeshgems -lmg-cadsurf -lmg-precad" + + CPPFLAGS_old="$CPPFLAGS" + CXXFLAGS_old="$CXXFLAGS" + CPPFLAGS="$LOCAL_INCLUDES $CPPFLAGS" + CXXFLAGS="$LOCAL_INCLUDES $CXXFLAGS" + + AC_MSG_CHECKING([for MeshGems-CADSurf header file]) + + AC_CHECK_HEADER([meshgems/meshgems.h],[CADSURF_ok=yes],[CADSURF_ok=no]) + AC_CHECK_HEADER([meshgems/cadsurf.h],[CADSURF_ok=yes],[CADSURF_ok=no]) + + if test "x$CADSURF_ok" == "xyes"; then + + AC_MSG_CHECKING([for MeshGems-CADSurf library]) + + LIBS_old="$LIBS" + LIBS="-L. $LOCAL_LIBS $LIBS" + + AC_TRY_LINK( +extern "C" { +#include "meshgems/meshgems.h" +}, context_new(), + CADSURF_ok=yes,CADSURF_ok=no + ) + + LIBS="$LIBS_old" + + AC_MSG_RESULT([$CADSURF_ok]) + fi + + CPPFLAGS="$CPPFLAGS_old" + CXXFLAGS="$CXXFLAGS_old" + + fi +fi + +if test "x$CADSURF_ok" == xno ; then + AC_MSG_RESULT([for MeshGems-CADSurf: no]) + AC_MSG_WARN([MeshGems-CADSurf includes or libraries are not found or are not properly installed]) + AC_MSG_WARN([Cannot build without MeshGems-CADSurf. Use --with_meshgems option to define MeshGems installation.]) +else + MESHGEMS_CADSURF_INCLUDES=$LOCAL_INCLUDES + MESHGEMS_CADSURF_LIBS=$LOCAL_LIBS + AC_MSG_RESULT([for MeshGems-CADSurf: yes]) +fi + +AC_SUBST(MESHGEMS_CADSURF_INCLUDES) +AC_SUBST(MESHGEMS_CADSURF_LIBS) + +AC_LANG_RESTORE + +])dnl diff --git a/configure.ac b/configure.ac index a8d2a7e..d68d4fd 100644 --- a/configure.ac +++ b/configure.ac @@ -317,13 +317,21 @@ echo CHECK_HTML_GENERATORS +dnl echo +dnl echo --------------------------------------------- +dnl echo Testing BLSURF +dnl echo --------------------------------------------- +dnl echo +dnl +dnl CHECK_BLSURF + echo echo --------------------------------------------- -echo Testing BLSURF +echo Testing MeshGems-CADSurf echo --------------------------------------------- echo -CHECK_BLSURF +CHECK_MESHGEMS_CADSURF echo echo --------------------------------------------- @@ -368,11 +376,11 @@ echo echo Configure if test "${gui_ok}" = "yes"; then - variables="cc_ok boost_ok lex_yacc_ok python_ok swig_ok threads_ok OpenGL_ok qt_ok vtk_ok hdf5_ok omniORB_ok occ_ok doxygen_ok graphviz_ok Kernel_ok Geom_ok Med_ok SMesh_ok gui_ok BLSURF_ok" + variables="cc_ok boost_ok lex_yacc_ok python_ok swig_ok threads_ok OpenGL_ok qt_ok vtk_ok hdf5_ok omniORB_ok occ_ok doxygen_ok graphviz_ok Kernel_ok Geom_ok Med_ok SMesh_ok gui_ok CADSURF_ok" elif test "${SalomeGUI_need}" != "no"; then - variables="cc_ok boost_ok lex_yacc_ok python_ok swig_ok threads_ok vtk_ok hdf5_ok omniORB_ok occ_ok doxygen_ok graphviz_ok Kernel_ok Geom_ok Med_ok SMesh_ok gui_ok BLSURF_ok" + variables="cc_ok boost_ok lex_yacc_ok python_ok swig_ok threads_ok vtk_ok hdf5_ok omniORB_ok occ_ok doxygen_ok graphviz_ok Kernel_ok Geom_ok Med_ok SMesh_ok gui_ok CADSURF_ok" else - variables="cc_ok boost_ok lex_yacc_ok python_ok swig_ok threads_ok vtk_ok hdf5_ok omniORB_ok occ_ok doxygen_ok graphviz_ok Kernel_ok Geom_ok Med_ok SMesh_ok BLSURF_ok" + variables="cc_ok boost_ok lex_yacc_ok python_ok swig_ok threads_ok vtk_ok hdf5_ok omniORB_ok occ_ok doxygen_ok graphviz_ok Kernel_ok Geom_ok Med_ok SMesh_ok CADSURF_ok" fi for var in $variables diff --git a/doc/salome/gui/BLSURFPLUGIN/images/blsurf_parameters.png b/doc/salome/gui/BLSURFPLUGIN/images/blsurf_parameters.png index 4da8a9e3a11d9e5f1c4b7c392fbaf2b406762a1d..82c7e90a83b55b84fb312e6f0fa19dfd2d368c77 100644 GIT binary patch literal 53508 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

h5h-To)RA{ku{_pja8 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

w6YKb{3bmH{|yrDpX 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 E0J3qxDF6Tf diff --git a/doc/salome/gui/BLSURFPLUGIN/images/blsurf_parameters_advanced.png b/doc/salome/gui/BLSURFPLUGIN/images/blsurf_parameters_advanced.png index 4fadb6b489bfadef4355128d9dc4014f9811c40e..1f2b0eebcdb1d7a016abcac6a3009bd47672760d 100644 GIT binary patch literal 35575 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 R0~IbP)fCj^3uTQ1{x6scAr1fl literal 36675 zcmb@uWmp|e6D_)NcXt9ogS!(55(rL^;O_1OclY4#1b26L3GVLh4tIFJd+(p~_wXQl z_RQ|7sqX5owQ4mXax&sb@c8f`5C}=)yNCh^1kMHmfeph#1MgryPu&B5Ank=Ee!>D@ z?yv^Iz%iW7_h0tF_2?iFVlS9Jso)X_L<*7+5&G$pc9QPwjybzD;Ki$6y~qacj|v<8 zwdh|y4pu&fnTZ1C&02{s8LZu`d6NrPJj0k17Soofed!xOy^^D|nC|F<8|Lfnuv|$A)3DT&LLZ~8-ox<`a zqM`8UOu!MO{A&@ak0Kh`x7=!(kJG(nNQ%E0?S~b0is10jxjrtjHP4~c8P;6*6O<)~ zPG{yd@&)=o6KSz2rgHA)-P&gU)FsJb&~4@O4O4uWo^wTt&9o&tq(%8BzfvwGKpven z&6g2qNeESmq)Kj6^jNaHKuT2l7aTl0bB_?M2^Xmh#09>$DeB1g$^RK4>=Ouv4{d`u zXdi}O6^&;7ZPPl020s zL5hRHec^6I@LoTZ9Zb=~uH-OS)kq^D2nqEF330c{T;md$GxRA7vvfb3{b%uTu5AdO zbWETr8=>|f7I)Uvg^X_Qt`8rvH^fm6WuC8?^k}28VQug(_XQu$A?*C+CNjOfzbW1} zHxtA__xI8NS?$}OqdTeU8WFh7t`_F^WsV2FuFuJaFbX^prksm3y^MxcUJ+j?`{trT zebU57O|5sKZo}0QlB9e)LRYPS*>N;$KJfB4eZ}-q*1Rp-w{QRRScF)QPR(`Ns&0b~ zM^L|+y$M%(I;%P%XOkW;*SL>4PtcEprNxaox(CJ20N)7=MQ zX=Z!R>&MUstg#KKao zc&yyec6HzncWX8u4we+S?;3ydgG494%UFjZs(JLNBt?F)&Sa9?^e5-Azqj4Ypz<(M zA3ANN`+8r{!LZ)=TbYJe!MrmlRuDcRI=*7-m%wgfmUnf8I7I^sZJxv8!*`-)jCm?U zj09Gk$Ze3x!eZ-}`MvUogIvFk*T^L}XyX7>$baKWyHfptq93-Y6WlQ88V&luBL;9muP36Z0 z7*(JRUOhwQh2Guh98>F+@DzNHayAx2V^5rGAtNxN$NKbOa zoA;Lxx;C0|kccyXSO5BeP6xKI2V#AUbRoS5roS@(I&T%{}k3QAO^LUWfM7<*$124C8>Mh{Qs z$in(Uk9l~b&p|ptPxFlsfe6Le#D9q4q4koX`6igx2ATbQw(HVl2Jjr9+q$yYle(KO zY~lo1$gUn~ditqD@wO5M#7WMlzhGug&E{NeZZJQ-b}9#w+|NRLXcLwBj@@^j$#fey zZBlaScY_OtEvP8eb3wDGs-%zn7=`ptNxF>hEu6ZK3~d8Xqo7SZd{--aPz{mOXJ8PM z-$Xild=8456&Dk++uWoq>%z2}BtYaD&jJjJ#6u+9jv#c&z<7O$5f^u<_baHKm<$e{ z_HHmEL;GvX;Q!bVb*^ZTqoS%;O?Ag*&nV!wlzU5v z{-pM)=tKSSd3kW?8=-h>wb)}xQkP^Vyw!@07qr-(Z!L)Ngz?lyZ?>#fbZ~~hQ z7T1iZO%QfnGo*Qh@;#FJ!Q?5>8|o{qry`H*X>9Bsg2$dpB3hyL4if2LRF@mF);)3J zwZg{AZY+Y;)fGFq`Mpr8tV(C(pDGo6arP_EU_jk+Q$?~kUf70guTeNWaCz& zLP1bYUiV7C>e*NMDQV2qF(&+;Y)-D_0S%4tiwm11DYVH)*ONM+*|AvsUjO8rT*AGr zRE~6kaKKebeWmOR4r%Gk$l<1dBWZTR*vHqMN53eoSPe@~x;%aFX9G?9GxHDJNI{e( z0Mj*5;p{ORPr8;lTi~%DCPG&Z$4};dojNt!$1AMQoL1orDeM$jI-v5M{q3F0?clHy zB)=|D#6PxX^9xv>98@^uci(~C%^qZvpT+c&c|}cmPNul+|Av=Gu>$A>C5W&><5dmG zo2du9Ewos~{!tbiXSjPwh$5wNeBHdm&@ZP{Y=ojfXOuFSa#>t)>s!s~Z;AVf!H|C< zWk@{=DP)SGczsE3@bmOYSgbPf>uAv~W$E9)$iKL*;GY}*a-h#xb26VxyN<$}{?ssp zD#?#Okstpa+Z(ik>U13*G;7wEKax0AB=qew6(_dFiiek{kbq1&UkHz_?U6@^0$O*Y z9Uf9#?9^upet~& zwS64Msx_S_PJ^yg9UVWk#leq&o|2C-nQdnGD1CLTkS1IJACU; zc^+^HawnS|2?%){P;KkXdvLJ})L=68-MJP18JiRnA_qb2k7tV4?2YNxsL5&kgbZ6m zEa@Yo!>+;W6BV^tI5nAT_EgsZ5*GHUnyNB(yvVnyYRE-*1OQ|wKX1>Y@F|smlQNa<e7+(_18Q?K9wb>{HT00WT@M_8^j|ci%;@ZK3AKvSE0rhVUM<>RGHYj`_z%QQ0m? z0cAXq0fedd1Ujyc^MdW&iYuG>5?y6$D)#_Zi@An;NUOmg8|8sbn~j&pYm>EB(XWms zi#br^P~05KnDLU67s#wGL3qe+%qLE)771hv^iY*J+Fgr1=bJ}OBs%TMQ8}q9@($O~ zSB#lG`HJh?CsXg6zq{~;z_3Wv`f;zWuhFoupg>GGI9+CSMGSp?oM0d{G_=8qi9~88 z`2vcPyb9#bw%uv*#k1N$-ddd#-yjs;EM-U2{h~?!A>~;fvw(8hPnttKWHHW1Be}Sw2RfzaJGnR$aynlW+oL-SD-?#s3g5{5N!D z2XaA#Seu$|CAXdJZ7&$1pa)jrmCKGcmv2k+=PaRP+eU{wDv<$7+Pz~NE}PpUB{uUl zLQVv0Zzv`rqXsoJ5|Su#@yINrv6NvHxGyVvdKc_i=haV6@XYc1uJ}a@e21;Re;Pxq z1e+?j>x|7HQ>j#3GyaWhkpG|xovZsRUm0>bmcr2$lPhlMXyZH+s(o%$zA0uxV!Fh- zKi;Fq@xy(`a~xf{LL&qM#IB?IQo?f!^>_KvJ9(A3n_q!~X-!xdkY`F!~&4i0Rm5-i89ZQGXx z+nM5D7;5px0;{ftd3l5V@r>;+=o5U`jC|KO)3|&t(Ut4z_fxsz@dNSbUUCe-c!K-} zW=mA2T164Ek)!xIAW#G@Ko-hh3Z&g2N!%Yk{hMa3G#bNKrN`c1P~`;kdb^}Dn=6J& zufJ*~XiylNG>LG`=A-~U;ihrj5k!(`pv3Kx9u06sC#?`U9&?J>cG0{%oLadjv>^}3 z688KJ!`5hZfD%(oW5o#gh2M`G8Wxs4ZI-TRs$60)G%^x*%BoH`dF(*Vz<{h4@N}n) zN7&kcxspWEGQHLE?QUJS1e${N&x91xwQgKt+?dICWe=o3S~WzmGBYJVr^-uI5SUCh zKwK`wh~BG4;_sfX7pD#DS*|q&Nu1~FA0Z;}wxhp^@$}~LJlUcmdvi96@qB*@0b(;x z0SB3+#QGM{Nc)3px!q#joJ>Ke|7&Rc$4dBcD8Az1OoB+n0=a&=&Inm=+arc}u#Q3_ zjo-t+9IeVI6zsA6goHa;L85@qiEZTE+fZ0nZ1Y zmij!y!CW0e`|F*0He75RzV6#g;#A!a9E-JD36oSHd~?_NopWs!$YE=!Y(nwxr6hq- zr24RA-dJXc5EW&fLe?Zt{;5Ln{RJaeEK;PVfabf5+2=n9^XmpGcp+rW0X=(l{dmZ6tnk~8`dt;$~EpC+k?-t?j>OVY<4GjF6b_}rHo-1h< zL}L=9MqO4L5x-Y5k#M+f8d4a&kg*{so;<6RsYMiK{Kgj*6|Gb&1G=ZbV}Gotq=G*B z_O*5Er1gt)yzTC^tYF^{#hTue=kk+24)!uP^cA8p`ALA9C*IMY$O+E zb|+2cf`QIkZ#gnN?znqfhp}94s_>GyOwms`Qc-hTay4kGc~3Zk z3xDF`GH5h<*IO>b-*>N~T$!?UE}ys3_r8qtTIZ@aSP3ufjj8MO4SSB`4uoS3r@S5L zf3)Hf^i5gt-VsNW9J=G}Eoc%gl-Ke8X{AYaYn=D2w;Aaejfe=Mq%S8r^H=O15N5Hx z%SwdSVF{{J6@nSAPc-4g{Ln{C`GR&W#Zh*`du@uBODbPxek6Q>r)2*`v2+z5lEbuUNgZTWE#ciyPx4k{Qi5-l5AS(<*j6{e zxWgugs-^O7`#P4ty+!oi>n-QH&gK?{>T5s2!D0>7Qms`4&HXA&&{(AB>l3`|m&h+~ zy=f_Ry@yG9&l*E5{`ghwF+2{qYaaIK?+dv2!W`dv-027lMI9`N zR+u+PaM^Z|aPh-?-`k&{Vcweq-%Q`T1@}GtXXH_`JpBrS%T`g*rfetiy7^t1Dkf;k zt)*A#7y|qBV(9HN(hyR|D3`T=YMh*`Y98)}l@RW=2voCyJ$`xq(B5kqWESvTUIMAue2UcDgt&e|lcppBI}!%&yT?X0B=+UI|ih@;Y<-W#i2 zvQTX^V<%33qdr0A1#M)woe5ZZw_<`wx*u%yFJJH1;T&B|-`p+M+mU*Lkov|_IVo;^ zMztUh{hAORG0<%`I-{x`!ogs?p5R`e?nKwy?>7n|VE9;ZL1N*!J`9@8T>1{L&l4kz zZo{;+zJ0UY%@q{RaEb*|Q0FPDc9}RFEvxq7cs<%)Zz0cT9V7r6+dpOP*J0*`3h%RU zI*s!W_k%&nv0itxkzH@O1m+TnEg}JTE*|HzaQ%Tu35=#(oTa|!R(&mjtLyKoitcyf z4s*X(Fw5CvG>tIW|HQ7w7pg?$&BI??>Z6w|u|q?p&a>~t7nUN29_G(CwMPDXgMxP* z!It;HdVbr|D_yU}112+<4WEw9(PY+zKN(r8|>Tw+2yOHV~XMsA+vQ7B-tCKn_o&6~AonT~42_9#o;JY1(n zj|dHMRiWY2vl-0~>$J6iwkWW+`Bh7c7!lfUN2^3wC|1y?>*s4SiQryaL3GsQYf-|d zQ<2%WnUf4;nbq;nM2!l+Z<$0LBu>UX<|{P&Zq4UywwKtu@(shV z8=X$^6BsnZgM(pLT<0}~Gf4J#Hn!6UYfY!I&p0gBvmxy4?4sl1Ban%B;RAa6`Zi~V z;$mfR!@D-o#m}T#?hkzWek5!yglOz!@X*7?3OKI@jH%ayK%P7gafMIiV9gVn9+j>? zny25U!G2*x;l~FmeNoYUZ+Nyj+!7si+l2aben-TkV=aSxceWY^+(mNfd+wA=d%~ev zMa%QbDa~5ty|EPbM$gxj9o)XY zzE7O@{yRxc$43_1Q897p+h+PG_!0JVDkqF90l!?Yp($lFwoTrE9*i>0*4R)l>U?(^95_Vtq3G-U+8Pg1e>wFAW8Qs>HSPX;q9 z)#wNLJuxMa2z16*n*O!+h`5&2{?(RD8{cNEjWV&2ni%{#w`O4>BP$*T#5FfR#Pi+h zz%z;G#^0X&A7J4TShD#zY@jU8_fWB_0IsX$hDLc8{tJHwtYKTi9I{-SgA3gQB$O4@gr01_AT&HYnii~lx#*oJx7mBs0qeBYf zP$zlgLbYGAZ+5J4ONIgpEoOxz-qISWS^g1;Smn(;C&=NMHjHzv4bUipEJ(;fnw2B~ z%)H+32!AeIVRZ0jH5%=Fx;?Ja-4^4!ThQ+&JR{ zD$lmM@O9-Kx91zMeEh00+T01zkkCTFrt6*8_6itpSdXNPhzrnX|FDz8ff`8H64K>_ zTaVK(CH4Q1$WA<}3xkmpxbsux9MMHSh#3B(#+)$SvrKFbSysdjB}t{*C$)^FCvmzb z{=14G;a2QGiQWR9!xOg2g&ZR<&-HRW5!?Pgyvvuybw%Z5bk@~pZyfD>>6>>h=zd@< zA}Z?o%|V&>-Db0fR6iap5$S718k@feV16py)MiStBvEO zFwTW#_l}#o_}lC6+n9_hBsEaSyE|+`j&Pp!GVm}22##DX7pP>p;CKXI5@Oxw#mFTG zny~3n3q`|~aCABGADGgGD%kOx25sW{QL#)zLn3FzXUi>1f7K`(q(6mdGiGofcQ@65 zVeWd@AE1a}8|GdNqtUG^`}h9QI&c-I-P$^aL92r1L_oNlk0A$gzwc5-VX5VA`H~`H zqU85Crv9m9lclDLB4T3D3v#g)doJflv=Q!!Cttq7Pn16li)XCqtH^%2R=7dq|CE~& zRETJZGo)gN>CRTIBn@YoA-xVmTOdYPuH8m!AwFN^b39+(y=kL!x)fEZKi~u`Mm>uX zCTXmkRCcn$h4Vcc8i*~c$VeKj{$k{y{Th;SV`VlbT*Phy0Qs$aHTe0*MoUbjd7gcP zYy8o4(6OSqs1kJ&R1o|fG;XclXg!ofM&`e7D}{#UyZSmB;%s=EBm3*@`Ov#2cbWhZ z1WFyF9Ub%!O4VUt0MGJa<|8~?*Jlk3f&c-@(8FGgOrf7l1{T$_aY6zwabZGl`01|C%-m4h{W@$tt`S089<@+DxfqU=d%aWHZGYY0#xp*+u^x zKOw~@*(x636IgP5LB~LsW2^!T4Yk@j`5WgeyZZYUO}zwLW`BMYbk7BE5s4B_twr9gsxMly5aT{N|lw`rP~^$z}K3tNC-=*eJao znI4|#sX>!W$@mvn|6DvYe`$bsYV3YNAaJh8y(|y>EE!)cte`HdT+V;Qq4IN$SF>EI z_HPW)j=2iLXQzfn)Ae$qX2;`5Bmxd!W-W#Crbb*QH)u=f{gH-~a-W|XB=@J%&Ts*o zeCfKI5d__~yRI;!Mwci}JR|mkLF7weIjI>QK8R}>SNQ{e`$UyVVVfR*R=~k^avZpCB0L3PsE4ctUKN#bE)iNR*HOn zuY2uKvk?aMM{J{6u?>rOJ4YTwX2*NVtB#KoYioQw{>sn~kG7a6?;#4jop_lnRzn@llq1RXbalDxXb$&SuX_f~HLM0ghlB)ID8lfR)rPo- zVKl&O+>*sBgy46Y>)fMLW*FqS=Y{aae)}ceSo-E4v5|e1k@63o;8L`Z219pyo`H}g zrtuP8VC^ohaH7+yA@^ZVdfyT$ahTWsjIUg~g%-0YW@mGiJ#1;vGKR>FaTk8dHleOW zOt&)TPk}o)%kG@Ya8C)B5_lVjhtrUd2g7yTWTA`>xZO?BWrcl^o|DP5>FiSdh z&LnyPbm_Q7A=q7{94m7?oO;P+|AZ*;xV~>PmDA*|v3SqFv@(Yua%L-9cpFn9nJg5F z7u90zm988HIGsu5+5P44eX=^<-Qwjo_0?qch~qQmoOt@fgXHZS9_J@CHj1+nf5fyL zXxP?k$h4dSt5ry#zEFgxjxleoF>vn1RfrHFMvjh-ZX;f?791A#&B38|KTi=0Rlv`` z;k*1Kp4MA5+^1cZUGg?6>k1)tdD2H5jyJE-e|RN~QwmRb1hV`q0vUpKeOs58PmiLP zU$-pp$+g(ltfQs}jjdMBx=(2$?!Tf1cgkNV0t^(7Yqdcvk4q2czhL`61N#Vdt*!QS z^qzKCG(6y=UvM|K>b^w#EEZh6|iJ@oSzttZ>@UT5WUanor zk)zf2yRpXEx_1^k>Px%4fQ66tFP~66PM$Js0EM6uqxk^E5Zmo1$Csz&OeXbFra3B$^f(QtIM0#0Y|Zxmc2_8B^}w{<*IX4s4~^2(fXo8^CluYlcQ_C9JB7 zTdOvHEZ&eLW%7VcmE!>4-RV3!Z2D*9C$_pw=2ysA4P4ig^6cqzOX@#ml`#R^6q8w) zcHF@PU7CCwZb&;?PNF1Vl{R2M1?ycFM^sy*3J=63gm7YBCI&Sa?~*bZ?(%MZ4G4=$ z!wiszgACVW@p}A|9*lNZw3B_N$n76)#xTmAx^?oLt5dH!Nlk;tcMcjb)ny4FA0<6~ zR?3w(`JOHlw6LHmA}-#eSCu8N0N`;5Ai-2@jPBa1hq4^h5kwxNplJT*^?Vi=IQDCd((2%tM9k<+Gh5pEf>_N(eh`WF*2JT* ze3?ubY&slJo7%`l(|m6ijeA0NUZYHh+pKO?Vud4pChe1=5s8K#<>pA~)`drLuqfs8 z7n}SOlVQ8J%LC{4yIhP;Mr8WMQ(uAj)*}q#UAc*Zw27P>E}hqXY_4dR;x~gBGwHqP znHd%1SQdJS%FWdilZwFAgz&IsNlMEX5?kW}wBzxgcb{FSlEmm^G>Nt_J!cvVL zw`5_5&}(UcoX4l|y2VhXFCz@l6}n6c^3Kw~m|_9bKK2O}s>sF8%3M*=Y=Y!`c*b8y z=f(W?6Bp5=Azkw4n>)DqPx<8sa~v-+5iRWr3tGQtEE0iBa?HH8IA?J}|7bMCE`-?F zFw&-uR^<51=v6z~>pQroCj1y!Zz+Ta`jKDJ4wKiKR8_(7jieIcZ_`cUPED0l-^)Go zheJhzax$($MVX1GHopAk5F27>XV1IbhDeOko2OwAAs0YiBWiYD5jYu#?=%m30lDpy zS5$7@ghS&8y!p|PXiwR*S3f<^P_&OrS9HIotFSmK#z0OfKG@zaLVHRHh~^%t;s;mw zCWijIC>xtZfs;MO%<5Gg1!_Gj>TmiVR8DXEqh(*0^ABl}2Y~`4sXzjqU7~$K6 z5O8-#ceh;*MZ#w$yq2NJ3|`i+E@OTuVY7Ud+Y;82y2WPwN`c1K4&;~r6TDE8vCz(Z z`WcZa@IN8f1r!|qe}buEzRxEANxO=!qO(5zPj`gT9pwAt-QhN+?id78q>`m`)cQ}+ z^ykl{mwxf^_+;s?7Ub!IiGB#v8YtcW6hR_Ia1o7g=~=oteJJL0<%*c}o1pRxM&yOe zkNXANkp?rjwHDp5vH>T1azw)_O{U0J=F0slQ9z+!nA+Y3>%h&JPP-P9n39aF{xhQ) zHP+Zfl6-5fR5NIC+86=^&j1=)^)X#F-ZlfPG&}U{uOk&6F892?@k|f6Sd`9oCqmpQ-U-2e-{;?ons`b zFn$7y65t^sT53pKSfP%8J#F_;ZMh@g+1<@{Oy&4az>Z#K-6H+noF!SV!AcVmp9}Q& z@83zgc&!HX59!ih*qAIhD}muxx^VT;y!J^kN-LhVRn=IdsT|RV+eullM1WL)YFUkB z?0CbsZolPNb3K;Me7n~6K+2u|chNigYjC2&7iG@#Gi=J&ks4LHhpUo`%d?hqz1>hO z^i;;`>N~x?(d6$%1W~JQcN@SXbOqj$NL=wdy>Ka)sUd|ehF9qiKojEpCvg&`y%l#p zxBg;Eip8#H+XFgDxv!bH@j*A5e7^mg8122aMV2ODj~@~e;^h7oSL$9n zdlyY+KM7G9wZ4bq&FZIoVSJyMZnU2F$3s+YHOXFo_+WBR)@op^TQ8x@wL5&o3uVO< z8PXxjGh14L+S=x#@q4}rg!{zY&OXjYe&XKtW)O)&E!CWCZ~l)&@W_ylv06+U|0LbD zhtU~O(nsA0sy#VdDWo(C4DB7|RFBGi0Jjmq0gZx*#sOXq>hZDeSPe3)U>rD7`r`2f z)K3WR*PThuI?e@N?v|}p>zLRj})EDK8>!Uw{dO zQcs<;thC)03nvjI27SD!wOkfU5O;9EBu*6|Vm0RX0lJu!jEp6VsiwO6;w{LW`F@DI zyJtiXpbH~O1byPIOZ&awUcras{&N*eHX0jPdvHI!2oR(&m|XXNLz1oQiGvnlI}tUQ zGNbcQ{NEs8ghp&l)^fOs-v++1q$U9ovNBzWqNQ1h>gwtWBb`T|+E&snO8?d^o1iyPJqbtT?vxyWx{Yv7`m<4E_8YP0M&|J%qC^TC)$6Q z7(^ve#hS~iHAZEFJhvDf8eIBw0X4?{h+&~tPxLdd{W_hCR@KRPjy;t z(=xRT8U zx1a75Shaor{CW1PZTSES2zr$j5}2$LPRN0FVYlWA{vqIZl1uf1Qyfo|=$4{If)9Er zrTQcOHxDohKd8&(w@h;!WGn|H6Z}ucizb<5LeD1q?`H@eKKu8}O1nFWi4C zk2_j3UW(*}ve17=!=Qp{EuTrm|D=!e#}iek4cg_|Pc9M@Z23nUB-H!%PL!h|=s`^hRbg z!EhgE3utJ#>~5$(7QkRy852lpntZ}lo=?LmKxr=dh1*{C{?0(> zP_EsdT6I{eTTX#6s2;d8{X0rWUt6QNlZ2n_Xn9cuK?@Dm4K`!0%Y4UDh8;z8n}QYQ z^0poO8Y;5KO$p!)5UxPr1N4H8?a5?}!WXjS65^KDw50 zVp!GNm;Y58!)TDG)1)2evr)1!?DiT-%#IFJI%Bgw6%#34nJ@qLBj%f!M(;#m5p4evGKSuL6!9q72_-gl#vmfPF6m|M@V(%^ZovA1G#R_`^-Zt zb-5yruz&v5#&G)7E&_EAZxwA-OQ!z+Ggt1Y_sXZ%V=v>XdO3GDlf8lCyAe5G1V;89Xum^gqWY1JPR)Ooo*aCzh# z@UeWxkc)wXWHPz^sP^A5NZQ{85TW_$l)s#1vS1|52ZA=JT#?_Nolb4mcO*<^ zi?NpZJE}bnTCcc&})iK?+KTrLgJ{=qz>-%R|u{}7ITe*A+bX51Ey>XSpq8&hW zU=r~-bb7>5l5unYVouP}31_rbPuyp|8h7i;>BHrA$0c@i;DNtFsI=;Vb~sgI-fCsD zthFED7;++g)aYGIG^|TBOTkm^up0;-tm-UYlxa1p;|0dqAfQV>hun>S*-6p zQii*^0WbNO9BJ#%7r@$tqJrMuoYQzb@RO61gF_;_dL=NXs=m3U33?%yD0hVD56EU| zE^{QtVh1ej1Mf-eZepu z&w$dGLjU1f<#ul+)q1aGQl}=B!UWdhbl$)Ie#Z&w1k`p@CB`U-($amA>AYaT9tn)8 z99Me-Lu1{CO5MTnaj`J$u_;n!G*I;amTZsbd;Ok%>4%B1YY-?PAi(81V)o(fndG8t zsqSFr(1}j18neOqB>0i>9R>|82ILLYkFr%JG9K=)Cv@MP*L6>u9bMiQjj{CM0%Ktf zI3*8dGI=8ARmyu06$_^-b-(d(c;Mr6m<0owv+nE>r_ITOEx@sD;zr^oLq~2;7B~{D z@aod3u~}y)ISacJVPfHI&KypE2s*sRJrpj`GNbhBtw-ee?|rjNmj{Vz?wi)Lzrkc9 z_lSpg-&x`npB{Rg($-a|t=ik$R~alGQx7tJ1v=5F(3r{!muN7AuSZ z2Zc-g=pml(JhI^efi??l+%Mknxd@T-3XQYe8mv_79pDI^ctNn9TYP=b)|grYTcQX| zPB$i_Ub{*wt-peyD%wIneS_BT35>AeB2;bH!{Tv13U63b{fKuR!1cmU-Q5JL)h3^y zQ3!(_2{_2eJy=1cz%Q16oIL=ae!WM3Fkitq=W&x=$(Tf;TB=M?eSg;X<9h#NGW)3e z8k~>$%$h-f2>BdPdjgR~EiC8)Q3xpW2zZUy>hlVFEI9P96CA>cSfN1|vnty9d!BI5)p)2TB zgFT+_p2I2RTryCa`Qyjo?yI@^iB6a5`-!~+I7RO$fX(~b7kt=ZTD+2ggxOm zV+)PCM9_!_LGm?I{6e@7wcuOA^Pcy!-nrO10|B{;1&F8z&;}V}tEtX5svEMt97 z(g=Zm+1c62GL?isnv1x1rEl4mZw_2Fgv2nGD0jQBVS|)kg>q)_R-p^7nZEea8Lq&cS*I z$x?%PlxA`ZGn*r`OG6FQ*6M3F{6b+CfKh znQwxeh6YZv*+Hm6iysXG(mRN+pUIm&z?}M5~eJ# zcTzPv7bkCNX|3;&a#J6SE<5T@_#>e$5-7=Y34Ss*);(LHs&YK$7)|0vz+un; zZL~)0eo6RBZ7ww3>}Y;6HYC*H=~2b$#)yt_40IQp#RBM;TQ#%A0xCd4gS=4$pJ4AJ zNrLJvm$o{6AU*)tY?sZ@KSSJf4){8=+3u;_0UL_<(34hfhX>=<+dE#D%XLQB{kjT! zM!Dhb1dJ^AGq;M8Ix5mOr}!n6va=5?e#wI~&6ZDNHXGh&UcvCOcmwLmtp@(SOBd}P ztB(J=N7gs6sQhOW&M{b*#|RBC6^y=Ep~TBG;E}_zwdbDbA9vWWzyYX&&N;fYr7sC zWIN<~iao2<3*^w<(=CZ^Z}8?qy(RCSz@zNSTr)fI?*kH>3%<9vhK|is=eMx*7N;&? z-Uf_{<}rYst5^?4IWcE8sI2jr880E`|E<#(I@=iQ1tqPJ0{hr(d%=gzs0AL@=S#IO zK+(H>yn^tj+KSwERIl|I;%gm$+v|U>{}xoJH(SgZogN?I;|ERC4-WbkSfDqwm7m0K zoS=hpqjuLGxO(@$;J}6W=l~mGukrYuQ#pKjp7A;pA1->m(q`C}sZL-k$nUbLLD9fe zw!otAic$`x0>w_2`eP||WXChIFM3_MHRI{r^adu(sSphAKYl|48lgbn5|tmQzc(9FN2eHEKy!)^Fhw((x^>xL9l}5XU!|89ZnlGD|~&rX$#mV+y8 zFyEk2;2pW*Q;I!_J~mQfG;1$2h^{y450tYYn$uU&{=(B6^HWPN zC+Dw6F{*eJVZL@Wm89ro$C4JDz`4K3^BQB&o zr5uUGpM(!6_I37Y_KwzZgog9}Gyj6*9|8w0fZO3R1u`CT@hD{)Aw`OHOsW6y;itg= zZJt9_%0PX)5u$MM4gSEj!3sUJT~Q?eKRnDpg~Lxt{~uj>l7;twP?`Q`{A>>M|M59i zNW$+@Ok@A;;e?dG{Ur21zB0a0^7RHx2sPjMwE1?S!ON?thjcjEO0z}psuxbcqy2po zW@j&>G%Gk*4($d-Iw4k$UtZWZkhB=hiuwA@?H$0GBHXOIJ{@4*#YMJZ$ux>*C4-g0 zs24yc30|Zo$o30enA+sv??y4CM{EiH!}I5Q>vzxArr%KT2nb)8Xvr|?)E@Bn_#S1I zgyK@&(64q;y@K^lp={)QwF_G(Y)aV- z)tp*DObxN|9*3*%0JU}n=@NdZQ3U<7li5h1o)*4&SLC6O-stzu0osvVF;FNm2K4@& zW>vIHFonoH8KddL^<5BE#)|M{z0YXgRUJYNybWmjDT;_CBvYb%ZegwLvi_Ghh?8HtHO z10-&kFvx^o2O^0spF-n-DkXwwuoCt;UJ4*2EPe`oE$&7fixMR6Y{hx^GtTsY*5q-% zJ1oIAHr*!SaR2NSYPEQ}Qgxc}jHw=PWCF;v6;GCuLlAHnvt- z6=yOk(ailrB@cUA{#rfar2x5%ZdW%{W3Gy|4IvD`9gnI1yX>}~*gR>fQEj&1jwI#}MJD3eXqUi< zNlOa{C_UYmM%xeU=49nud<977b(Zfei+ zeY0b{R`z2KB%p8+44yJUBt4&W9LHhQ64qKXr2Ey1T4OZP6>yD%s?A9ZicU=pqZrW= z7xDyCPz-9+Gc11YOA~O!uK>15Oc%=J>h=V>SUj<@S|5an{oCO@Fd~%$3^ZrG;xE(S+zVqqw{aIqROxca0_to=B49GO&^cLYm$q{oYRiaA z4**!*TC-VrBy@s}l8Sa{(96|vg-O!FSNTzpTzG?!9vJ|4Bk5Gu78e&kC|~@~luxDF zuCbY3P!R;2&>%Le6li6Xf*{GFnn+NL-ha$G&IW6*9!<9 zZE!vuN$~@coTgo46OayotpET_an_j2$ziz^ju*ub{~y5geB8xpeVkJVfzrpP3CROd z5-m^&crXEc(s`lVb1_Li4FUa*+V>oZ#%Fd0}lj_>gS1WSFMu?~Q(lelcb z0mxc_zwC!1;H{$NhUC05MUd(KL?c!>R2aKj)W_>I3V`xkC1C#t2>{}NbdvA1!E;vv zNPKKw9&7;#E%ZPXi8ufhX!BOoLt@)iD}env$;oanE>$3F>3DjMRHTpgfK36PPQrj~ ztq-;z(lOhI{mjcw2t`yPq6i@f7&3l-2)>DuGaUPe3tb?_U_SsAmk!A3bQseez`%@o z9(s3#x*g5{oA^9R1?0O24m>w!s|Xd0+Gw#HH>oDPjd2phRw{Q8K# z&?I*Ymz?!?aL;nRou7=1{Bp|+sDTt_AXeG*)R8wh5529dPu>YSi4GY8REx>pLckbhK!xL^ z;+v}~KzVE|l#-y6i$rJ`=ulvB14AgE>)Dg7@$!d|mn8<|EXmK>2@Jg61H6=z_SBYk zY}p#{eU_7Dk?RJZLcqdN=y+xB;#EAo>zw<;1)pt&zNBNC1@~)~Is5grI~*)*uO`hw zg80jw{^4wX7E>i{Qw(1e}@7w|MUl$TZE$X^)MN zFvtSqpK2Iie978y^OV+oS{KGbMC4{PA>S6l5&Zi%jnnQ79#G}P<>e#3+_zVgzxf_` z2%W59@wqvKz!3kKO!?%~iSqh1Hary`Rju-u;%>c#Mns}E%xAlcA&17DkFM7Sys-&b z^?yVpRSo$rQDhjHukoQ{+})C2Y;D`J+oW+6z$a<{H1qJV%9bfcXq4%#9E8L<3> zLI{&t-}frXmva9V+12@WIKWJ9Tbt%Tzs_wzj7Q3?F%(Jj>R&e3kp7Tp!)r3xoeu|G z$ICM`Vs^+hKfhtbo8R5PE?n+KghY-}?1)Q;&_Ohj)1G;mD(FjAwJ!8NoZ$FigE|^H ztxhVZZG|hNwfS}tV4^pM5m^Q;KA*VGGYEyvQh($7mwUz81gNbc!VL@s3Jf%R@3(!R z41jS6dBU8eas~!bAb9+oxf<>w>*xSuyh<|X@aW_FHH8N5{cREL=p?1SHo$Bn_!@K- zfYbXf?Xfy}q%T1S_nuR#)$jv*?H`)XSS~s5Fh+?^v~xa&qw-pys(j4*w4v#(wmZ|A z{LJdbL}A9oW$~z4ny|NQ_t0KF+g>!#H8v(|*?|7RC^i*OkiLF6;~(VaFtGEefdv;; zXM}4bAA{+G`=DqDhp|*vL4jta!KNPf0^3B@^xN*9O9W%7r!BQ+R}ozmUenlfb@n+s z56XT-kh-$**v?>Xv5Wh+|7tzH_rWSoXeom(#-zVf$&pe^aiqkw89(j-OIfQ1MKpE^ z;$Yt2s3*e2cEoA=Y$cO&Z$m|t%Ju($%V!TAm=-s*`e6+F_xAR~9j-w&Sq_Onr1S98 zA10q|rDirNVytb+MOu|s-(AiVtL4{+p{#Xy1cvBT2-`FfGvXv;eGO}*tfQ(^*RPb0 zV~ObTy@J>^8`|zn9Zog6=VUi=ib~)-;(4p7VZF7bKyg~8xGqjHSF|n{G**bst@9E= zfwq8GOwE!|)wf~+5anvt>c2WXBs(ytIPx5`1eEonIObOLIWipNmc@b;&W4x(I{&SawcUE&OjUN%qYLAu*h6 zxaOG~7@z_wUoGpuJS9UZf2n;8r16IG`TqiHCoJ?-6n|qZRA<6K@&}h5bfj|r1^Ppi zHN9!F?4mCa0zDy(_jf%o&;z@Jg3%OMRAw+lG#^8X(h{#Vc@$(A?Y%&o6&5h39zAa| zU?3^lP4RzUBx$oJ0|ag)Ub%x=amfSCzBTMxXUi=^6SF;)-MTp=shr`ZgF(?mI{EAf z=xiPuM6GZ|1<$yw?5p)C5>OC3x-z^RdIv{XQjCZr_KI^ zP>=6(lf18*G2}C>!;P5;2DrhgjXYZ7qn`rw< zk?dTotJVP~&nUE~-`i^uvu90zY7100jkL2SdBWs~N1vcE_G7>uI0(N(->5~|p~ z*lUnSMuSf68!`IYt}3<2jkr{sLNqYcF}k{5N9~;2TiDX&Nj&AKJDzZR7a4$hM^lCVkUdae7l;d+hqKS!# zVfUPnr=g|I0s=tYee?Af>ua8|60OHdgK6QvJ9~=m?v4aKb_n%#zF;CEUJ~*f(TH3e zNHFVE63Qj8w9nc$qeQI$W+v_-`472ceaQf%_gNMn{8XCJmYZxZy1641NrJ#3Ramrp zzz{(1>wk$keV;_o&`6&BIQVGcX1ApVEAIsY$T042_xYT!xB)#)MJIp+I9SOp^j%ta zbF;ng5ky==+ z8y&LYIGOgz;of^_)5~=hY$y{o4}kqDlP-}lpXb>VefQI6C7R8k1C`Vltx3i*O z0KzOVXi2y9SjML~S)3{Jv3;c9Vvi#*zko$vq7?vm-qz*ZUWAnPH(j984I%@==t`b~ z&#m_~ugy%LpvQS9_%pD*phIAaCNT|9s|N5DK`vG&4Tjk(#PBe=2DIQ8oSy~~%wrRY za4KldUCaMf7av5tQT0Fq#C{0x>vHi17wZbIam%*-&VCZjMiZ>gXwvXR19v>$a2uoH z?}#sfmKPjJV!Eo=7#H&6$5rL+9_>>>663Cj;NTT@n?Ayw=@gdt>N`5TlyL6uiR#CX zHXpd_*v=-Gx#`weD(MunBZKxzdV7Dob$ zUPMdOla7Rw2*0C}jZfR-a?hJQP%f5x*=U=mJ?~qZ1f#>3e@=GYtMT?zbvIMXjv*kD zNUGr2$z^lcQ21-n^*pC@jO~#><4gMHxc|208(93uv2BvpV?x9A-d-%y^EJ*hLu}F( zxOX&C9eUHIyQM`wzJ|5)3cM)_8oWZb2B-de0_y8yn>7O=s_SY^(Qzm}z{{fgxuo5j z$Oab`YEs>y0oO+A` zgM!{{#ysVfY1nTje>2~S2Jwp)xg$ipOn2>R=jgiE;)#Fzg?a59pG6nBS{qF(K}BCb z>cwN*7f>iN{({F-#WVp^8I2Da(MunxIXuspKgs8nO}4dt685BPzTSh@-el+G*lnFy zgxuSsA;F7WUEl~cT@n3eVQU>N&S;Y+_kIx2wsi2r{cKK4@`V(W&v$z_Y=@(}ycjf| zjL>fbyS2NM`CCg|rA1|(N<<>?8w2sM**E$h~jg zn>OVP8Xb=4LcmP^rrF3n8KanBnkwXu9W7je-TT<4eMPBEQb8fo^fs@5|JUAk&%=!s zrRAY4UyOo2#LG)J^WBDo{m5acq)d+)F79ugBdz3=ko&9s#mu7mnM$^8PHl3M7LBrd zA2e3e87HguvJg6IYWP{#9Z6MHoEn>1OD<90*)vk8jZJ6G?(D~p=?hj@=@a?6`O`at zZ`H&f(CNC8f`x=304z}7I*6nzx{OGyYzUJ_b{=V`8w%yeN|}3V0Pbg`1^~CUIYD3dQXuTj&hHIE)_IBDD+q+p~7|12j=M_;Vr9Wp49hb zIoq4HRh>{wLtpf|X3=+Fb)It@)m`;8e!}d4vCU(nivgLcvu_%;zLu!efl#=AN1&mJ z_`aTN`T_E!u&A>@B?nWK2@YZyBiVR!WWa9R$z8Ij`2eN$n5{XGh|6qg-}VM=a?uWc z!To&R=6Y?pt~t${?DX`s&PKd)^)wI#XJ}~1u&VUdyyEnz^`=y()^K}*CBX^X&y_ch zf|{Dt_jcRrlMp}Y;QcCX?^R6{Pvgb+W6eqvj=ReNL3pO)slydaEUb5fXS*Q?OF6=x znB*CL_A6Zy^}2a6F=(1!-6$ulr=Y4l*T%dpYv(_!7t6D3rW9tIw+93d&t|IKmfA9? zz*P|i8L?L&UN-3ZZpBAZQgSI#>9%q5M7XqN3>o>Ad@N$V}kK ztld^@Z7BrkkPt6>Ddn(Xw431Tk}uO{zx;K+*sMtPrE!r!l$GsB9!NzzcQV1XX?ADD zXVzT$s5)#qZLgPNt$ANIdU}fnO}*{V({#f~cVFX&*%t=Wg*6jWjAa_^hQ$K|0}T(C zJKRn_c2V?lMv)6f75!vtJnUSAgNTTTJh}R=gY^)XlNb4e|xatIm^6hqf_w!?EXp66+PYeF388*Wy0e4IB^9? z=F+bx&={ucP%uO;ASPN;S{6h#Z{0EIEiC~7kTndgk5`WYRy#;+kBNK6;?pe*(+9+e z&CzQ_iaFBs%c8!AaqZl$w@Zq1rvZZ23yulRwYQPvyy(8y+uKlE+x8jP$v1!+NpNm! zYwPar{=)rr;kgU@vDs~XbyIU9CV8|p*C5`UiBd$cinat@A(HZM5AS5>9j`nX1+bHWo^W3 zaM|;JT^z*ROX%7EtnMy&o5OS9ZD4R9Y5}u}j=AG{U)vgs4m(|8@uX{S!nxf_B<~FD z)CC3yFVB5*1O#!_w5_&>0HBp3b!_$gNCjP}?47br4c6p-MExAj;IyjNMnFPbR`S&j z!g@#jAt3=tE8#GD*=Wx3To2$`&gQEv3VpXZ@-uvbBO*|D=DxKbiL_`e zgbg|nJJ@`4rW|9!lZqw^$SC(3Insar9CCN9(X!=S<8S^e&42y{5|Zv@*&`@q37AXU zbE1WUvpvJ#j-dGah4`GYf2aO_cwrnZo?t3;HAOvD?<|<^u|-hO1PbPRvl|(KbpJM`$zzjSF&BhqjftO?)sRJ9wklY zQP4$}_AZWSV=Ml4G~@NJbx{Kgt;ECzRNJOgwwv32UkYCOE;B)`1pBVt+Lbidg|_77 z+7GVoYm_Y-V+IRj+2}=Wb<&YJ-X7acb|wpqQ`RPh*I#!{)mCO4Z4T_>FLUKfJ~ZlT%P;`tU&yzy%n zn;(FG-;ZW)lIUn?mJYkfHfz|n2cJBzoxEk_g2-oxkfyK>{^TleFm3ait2At;RZtvw zmD0$?Nk`qj#e)X=TCJUjT}8s7oxXR^WI_|k^@KtwM12u&Zf`4&dg#lx91u>Ui$z3T zj{-SAn5%4&WKFd*UK+GsAN*J)la0=TGfYx2%`jW(JiQ@9&AuBe&G*7jS4Mi3PVeXFHkTkXAn|__FQKpE>5!->k|@sNx6+3OtO%_$JjF`n1;Z zAYrhbq*q8+%lEZSt};&f5+O0tvjr1vGqVg5*&{CtZI&AA`2|mLVkhtt;x@kiE7Fv# ztS@7HNwryFJ<~Az&BlPIPpF`$l9bKw$czx)1b05B`Rk;S7k1%q&NtwxsHliN2!}vG z{y1s;Tmr;VeWfHnsmlu3OYXogA;F=cp^fQAaFM7B9GWs#Vd3$t53sP%usGvvC-FQ_ z-qA~Ou1PIO=ZNV#p?HkM8k@TEWg&&7?}*c{G6NrEBP}`?-h&@%83^F z4hzblV~EY=wIw(56QaQFvL^JNo*reC@8hIXtKI~7`tIF&DsL!XebrV|SJORhejf_` z6r0v;M}oMIyYmhU%}>2pqaDh=bnvU4;px*CHj3y1GlEx*x3!Dj;agj_?B1PD@=2U{ zpq3~1J%Agb&(F!de5H{LK5^OM11&7@84DSq))u=7_eoslUrc-PFRreP0QaF6-Owz1 z28S9zL`CI*wmR#ypgH(%tB7eVy#+E%Lq*4fP9H_up1f=XNH;YNjg`HIJ#jg?$Fg$0 zLsL_JQ*~}8@`}=+dMhe!Zp)?(XSX+cM7*^gyZmOc(ZKH@-q0o1C2fYys+wyW5PM%~xFC#U(zbr3HN% zVlQE2l>#fAi;9ZasSFX!K*zE38XH82P_+ZCU)chYW3+L zRujw+4c2p-D6&W$eCFqBPTc99YeW&Gg7`t__*rW|P`vc?qxh@Lv#OiWR=Og)zHylk zO;4Xj;0&95Pa4gKKtO9P(meU32co{BpY!sT7VqzPU(qQBwi$k5455)ZI6r;i=*T7B z-d>N$y^6O=C`^ZSKG1*>f=>FQO(Nur$)OSCxuhDdkJnr#E|s%YF&{PL!w%F)}vz+gaYAy=QC!sfzJpb2bb7NdD@&Qhn5iHT4l7q_;)lhH~6 zNUFZ+t6)~gpIh`LXjJHS$Ph@!V*Us+i>G`$d2H>LT6&kn-R|1Dv6hmGs> zYevd?zl5>3u>Yw?s<0!z$}mTrPbcaVLHj2LLbtRdqa*B;{NDzhH3XY^jg@!_> zh>qYQi+f@aAfJS-=oB-A!wJ$o@e^6AAsfUgF> z71muYeLvIR4@4=Z78SxlXy|A%-}*AXo~wEAe3F*UAQDMTjGBYPnQE=S1+hO;VgBdG zGKH>TV`-Jw+F=)Un#}!LkD5Twu9uhyZ)>=u(MAH=P3;hf@+@P3lkF>cw#E5dhx8oHdJWI33uzbkDjtJ=Ezs=IX+ibDWr!I zE8CAVi(Tm{MaT+c=_skF9uONC5TYTCjZYYDF4NYT-MEeEHA1HcL0QiJW?3>YNLn-R z6}%r!7&~Dk)W%ZWSVE%q2uyJb!KWnOdXF#(aRbk4cv1yDi6QK^cV3_KbE$kYZqHg6>zjg4#1mAvk~YtLu2b%rNqW~}bcPCSGM(nWUd^z?RLjE(Dm z^(@DCehnAO&t`sI!4`h`EZ-9c>tp_}9E@N>#T+^+DpRz4lI@-vV=e@OIh4dQLySjQ zSl?ouQ_99z&ZZ>($}k`Oq|W?wXmGHwhKJh7z!{`E@&H#qG_-r0BNLn?s`C6PW_r!V zcL`Ogu>6zgoFX!}hx^vM5!L+9dwTiPU$pdKLkCLJ?<7dvAX)uB{X31RLQx}82kVxl zz#lb~E~UvC&c9lBa)Eae0S~`!h9Pk8WPslw77)r(SSN)2xI@}67jj}HH7)f>5LQL< zm1JbZEPwtGV+P$5u}%@;iJz*gt6!Y%`z)@X_+HH062bDNJH(Wgzo&9{SQ%hAh0_WK?o_+P#uRWZWK4gzG=^;>2Wy8IBZrl|w%uTP9 z_M`iQA;gbH=Hl*x1A_Vl9Gz}IHJRe3jIKK)Bjp?1tu5lE{o*#@y!*(V0~KZZmNpnv}SS##u^w|u|(8a;koy>4vo!E-5Yz8VGf%?ha!Bl~9tK?&X0b{KN zhtTX$5PIdV?$(@dBZ&B1mie09uH?Xt^hVsF@~?vrI_!}U$jL{MP+N~*e{cWlzyI7v9jeyM@NSwdb=6$l2{P^S>i*)l>YQ* zIQfI=9ghcv!{rjSA+2VpVazhh`pp6VcmcpNMHg)JIPZ5OHLt;0MJF~`6tP}ZP3A7e zH+_hn`L!C6v9K`V`kmf^t(p}PmqJoVxpMQ&9I{pu@Gij)V z9$X^!Vv!LA-CmzjuDyCpBjZrt#9y9%1a@gXT6KTzC-u<~d9v;4SXFuVI z$JoR~{pUL{p|2#8LR5c}d3N;V3Ug1q3#vMgM1p5c6^(wpK6qZYYgOKa9#28R&5g?c zjep2_%VTaKxeBx(M(>Iut8OeSZsN;qOeLiUMJGo3P+nC?r>v~(qjas)b)Q^U0y(8n zW{LdCmARx*2`V;lFKZ|>WUA~LOKH}dp--R->xn{{9JkR7IHqs zh;{#|r%&I#Jy$~UI(bK`fylJhshRrM|5lG8#%F%N-fxM%x$!C(xBMiDl_D$q#jx!Gvi}mhs1-Ok4r^^X zrf4-P3Oj^6`E>ulK(}52F-%MXg7Aowp3tx;m*fSN>F?s!#||zxAhu04*pdr?_T@1# zMly>-Q+~jmpHo$Z15|V1=VlLk^f+yA9k8Dgrp|b*&uSqbRMa##Mh4?TLxnKli3Q70 zq3PP+upyX4MDK&-@PS$dXFzX;NXnkf}zL}7rpI^&p`w~hR78a(gV-Q_g`HDvArIe1E1t72>EK zOq+YET(pzJs$I?G*noin#j(lpmG762=Z^#(x8fAsS=_fz`8?N{v$Ktr-G3u9J$-sO zSi2YujXhm875IA>?>^@hH#E5{Vx2vo3i>@^p|EIj|yt;z(4F==C#C;4EayC53 zl<&g#J2dXf0+&7Z)hn3rl`7(i&n9%v%&KPz2T8FfJ2U;_oA#gOspYrNv78)u89SE< zz-U4rfkX{x0+0Uk{Kl_^vC1w>j{&;Ch-Hno!a|52JrR!Y@6&PzRcIV3pWny?KB&3% z83X<^O^}@%r@z6+#`b4a&8OnzjDbVL8m8dnMcm!}so?bnmiiI7&*0jtC-uX>9N2;6 zE`j^vvqg2C{hn?FDtZm~(Ag}XCn+|u|4zx<->kh7hRT>Tvom&kI~I`Ejp6rh7r#P2 z@|mG3W(c7`kRLsA_>^&4hi&doOK%XeU1jqe6we4^t$ovuNV+^#=|8Ky+{v)9aee^- zH!sBo2_hLNP0?b=|D8JLi|?Yy4_(W5G%||ks%n~{0Qo^cMXsWwvwgq?BKV|*m6e2+ z7GtM=ai6IVETv6L7>i<77gh`(H4GcJg8J6}*Ucqat^JvH`Q*xu#q9I8lIq;tS(kyM zZ8?1fG&HCs^h@KSvH|Z><>_lO(C)-oI$B$Qa$FxQMLC<-pDAT`%8%9^<=;6HO&P;z&R}L`A2hp_bop|a8SgbGBcku z_w%gt5@KpGPm45-(WW= z?1~1R^}Rc`{)1)Hl}+s1<(e1&_Bg{z7R|RZMGfgJU9})nt27tX{yK9_>8JTgfbe z-EqeTAW-+Hdn*O;*%03sW;Tp{>jnRBj_cn|xLtHw^6CivDJWQ3@rgELvG7PEVd?t+ z&^*a0DHXo=>(KhKh%ZCRCg$dp%-nruzW)s|KrP>XUjWUgho|3xsVjFC+=&Ep-=(Fc zy_At@`_&!-ORi3$QG9aSJA6-8EzZV%#zPD@3#YHA%`blEM8B=cFZ0W*E-hW0y}Z80 z5Vru63BTh3F~-iPiqQA(UpT4Z0uAeZ;Kg2~J>c@_0PHWSeDqLOj)RU71%io99Gsm^ zH8wGsQ&NK4gA)T(F8v6y*ig^)`4C{OU0%wP(5!UhI1y+v_03330EVy%hQ?atXY`6o z+eZ$4Ny3j;@$d)*ZJ5^vGopc)ZX~8Tdl|Vinmig?l=l3D zMLt*}r1XjFzlPbJO-*U>ps0Z~`2X3~c*%%~iL2BdXfcUB8%>?)@Nuu$@Tqa}F3F*jwLlb^U|8kIs~=q*Miv7jHi>>PWBDjx zjDyzGJ96b%AoZ+Pxfaz7f_9MHQkIu83Qez&c4?k4TtCRQE(H_e33qd|@Lt!)g^?NZ zkSZa18v2#X_4EL-@_l>HdIw`+u4~UB&4%NsS(X+qz%gv4IS6x;%`8kmgiO-VQc_d5 z9|`bZ3g~7y!vl2@oK3TV^c6e7wm#bTlS)7s}2bh)AoG5jt(9Iu*n-* zzyJ_z{;cY`#cb_-&G%nTP@4v8#C&U!^y8oRZ93o(o^(4W01% z8Ex?M1jmu5C9CUf(lR}CDU)XwZU7!-FW4)8Nn~PT-l@M2{~Ktf!_(RJJ2F)4XL0Bx z)S~L}*tS(Rnxaou0j)qN13;@G@;4xscEoLvYoI(WUY<^DWn;BN}*39dZI)*3P{M-A71DZ?~Dk~!@$<-m7HdbepQz6O6j*j~JC z9^AY?XjtTgF$dxzv+}oQJ3?>J3FJ1ILCuJ%wwk!OG=ogXwU7Y(F zZ`RkZxM*mRA81g(&>;05f(T;Ib#<9JN9X~fAO-+1Yur*rPcO1zzy9&R;k)H8@@tKg z;2>wd%BztTNTYk0m&^1cmkNirsFYzk*^kG!s>5v zOoZ;r2!#}0yzk&^DHa_NZPJKK5`NGHKeY*3j?V;CNr>y5P;{v_XMRCJ;y)P9WG{ z)tEhJ;Q>*c{0}e*F&yaU&AFPj&Ez7+T-pwqnb8hJ3NhR|kxwn-M`_X*^;1d&VEPX) zDj4vL;o@If#@mG!Kt_zEmb8s3m3QVvlBj@yx3)&tm(l{s?g`v4Du(?5=IR45@}k_} z_K_`Kd0WLw7XZm>KtFSGX9gU!y?8HmU!4AF8-aNK>Yz^saPU}-O7w-gx-7!RDqf;Hlz=v zksd&}iP4BjNPx`#ZxFF^@~Cj!5`bo{C>XeeWR`rz9R@v`UunIstJ91?ek2Z{5c>V~ zq909GJ@6r6{FP1x=UQ&-|67ty1qXYTen#+zaNIk^#C`%R_H^squt1#$65|UA3BB@D zSP;sUryeBPp0+oAehjA0!8jBXmm3>LmELIKMrUYl$|SZ^XaFpwMe19s2x{_?>Pa#-X9;ko>B;6Z2qTsy1kSi8)f z$8j~)Mmu%(Ll;-tH8P`?70$CfeX0C7&CNbgTdRFlVSs?vmop6oL69uTmy*jy4j2wy z%cJAw;ntj(&F9)UEhsI8Ip`9Y^&>6o(`Y|>?;2ERd-8Z~P})OV;5#+7At$l@*@;Dj?8{c*dcq{dfhUi| zFf$uOfXFK!M2crW_}aG&1@qZ`)&i zRSEcH)`yaiAv<@wircgQ#g0y`HEtS&*dgld9{#rSdn2kTq-LtXn< zteN)t7D-7$J)lHDd-LRv+{KzRXSzM5zFRsN*teu3>zyxk zs$ZDlD`^<@P@_8xfkveJg3M;n!GSF)(gj147m!@L!5z%>T4p)(I1}Jt^w5-`FM@BF z=^cHrNv!iV!4wBufcKf_WXY*>jW+w%U}hWQqws%oS3CwKgrMtgXIWZS@zXlny#*B?w$R{MFn##^wm(#DShnLSB;mZFtw&wFBl@`1&r#wQ!YZWrdF9UB}u70hhpmzTYuts?q{lLzGa zUgavpk0nL!?a^Gd6|YT$HzL3}h%kQaJ6rnIHwB_DeJ*?huS;4p`HZMRk=bxS&MirT z+9|mi$#e%ci8WL#6Gp$dC&V)MDiT066B2E!K26S_=aBybPcZrsMcQxx8Xqn+?%(@~-tCiTzA9wi#%HcW1eQQex9w85<(_zO#aCBX z-OiH6kx@`OOCRGK&erTEoIJK|8aMMaHw_DmkW@FtGwb_g!>HlYX3et+{B1y|2y409 zMf=g!Maj%uGAmLFn+WExiQq2y!UJm3U^;Xh>$#t0UsI-<-(K%JxzcjKt>Jc^Rt;5Ymep>cr_IpVSOie{-l#1z$azFc8Bf~+(==$Ewa-47 zvOXUXNg}8G+64l*5n#SAQ6TDXVbiKaXmD+bei4rEA{dn()uTlU3pIg)vrgu5DK)zj zQeV%d8VoyjdCGZ9dhsVFzNaI?n26xcrFCZb78`Ms;@#t;#w}mtJeoEya zishoynOI$4rxX<(G)oD*a1%N@7_8s50zOS1Q%#i*(RhfLJnl)rftZ>r_o2$^eLLs$ ze(x2ZhujLXClm-|vy86f#JuKwguD|ZOuXA9#L{AtlI=vEP$cN?Ol^q#V5c%aI*9ho z!7rY-hp3)KIR7VAFrT3fL4H zm%y)aOEQji|Ho%P!DnlKK0DM>1pk+W|Ns8EKQt}y_rY!xkYfHVo%VKn{lT-tt?Yk0 zFJ3;+QFFxwTcRoai8ud4_x?E;;JE0F|9jhic;Nqfl(1AQxD89J+y8*+f7{M9&O@L2 z-~O`Ah&{wGP718ek^zx}4&anh5o7*6S{NGvJH`KPNdGdATr%kS-NCLotX0rt6nVLm z3OJ|1C9o*~9G0>KIR=ePnMojbXBKAzDgbH+5_`qhZ?}0vl4j+PpnheUX07os5u=qcF7uc7DePNllKvhN;on2TMS;d`MS)ReXTASh4*uJM@^^{yPfm|+Rz1)FPn61A z`#jQdpxHE^oP0W2Ra{@qi-pE7WPa8+I+#R8GW4lM^Ti8MwR#3JtN!F#Nb4_xh||f2 zbYRB_CP?S0+4=!ff0=y zrbu{trbHm>b2b*g9mjEqGS4~vr2+xw-UW=5=uLFSuhNz#A-`;Ng|#d2z~`w7V}jSX zzg^{w^?ZM8DxFG8wm%+BYTDjRbw8Zb>fJ|qZ)`VNESPRpEbJ*YIW=YYwzPb|Zft~x zM0@sg%>a5%!D!(LokT^i+ zd^+rzc0${K&{0oGr2|g&kJ0VU9QfoiGFGA&7(x-x%I{xnF1w*RdY_!Fa!!)-cY^J# z{#=r6sU*L=L1!w77}LhfneY!nja2hJy5!!3VqBlMtStsO-_F)|m|l|zJd=rUG>45psocEz@aM5jX*X!P@C&H&T~);zaFBHOJ$I1% zJFRQ+bQzPFa~c~Tls6s`llg4qzf6nUs^Qe$%9*^;y+?#KuKQx$h5mbWjf#s4Cowst z0(71P62doba&uh|A+o!S*wDHDrpTI{#;ceXqjy0e8C-ZM(BC31(n&e1_ZQPE7qh*C zXby#CpsG^6x#$uVcXQ)|7;4#|FWg)cmuT9Xnw)o$@3#Sl{NQ@=9tk`<)aKSdX*;J@ zsQ+|bcDBa03)tRajv+XRe}J^nYOK=K?lbUEC?W)<3SCtt#w(J$O4+*YnDJch}l&Z`%Be$uL!8l?y2_Xo7amF#Fas ztGlTF6drw_eLR???dy4~4l`mb=+!P%VkD9c8hTs2@3#83ErjlLduZOIxxP5-jtQYr z`4P@06tX#*2P%i-r9_>i=+A>fcQLWRRn|lO^l&D;cs{`j7_gcz*L38QV&EV!ZV5aj z{R2%;%$jS28Qd*1B3wMw97*GIc`~j( z?snYo3xR;`n74J^g_6(Jsz;$B0)gU2$#Mz!LB@1&`(Ku=!GpwvcSDjP@*m8ChCjX47`$05V4?WT=nB#heV?vq0b?$&n9W!bVd+;dS*o@ zE-ub&QR-XopMSqj^RJ22^4qEZSyRSCS5Rg?#_#LeJ6{ZO8Tl;6){vjUB`lE1fiZNo zX{_`seqG}m%VcAtu9J()5<$xiEd;Pu{gO67_lP_MPSAt<+r8S0+xr_VFjYVkS!cOR z5XnNwh&6oS*83ZX{AF7wtY;59NqnW961O<8G?^?5?X3C@XFHtMVQ5PIEApaimxF zG+d8{AJ){{IGh~dwEQqgzm3&#Xk3XRKdHN$cU`oXM zJ)hGYR9}DPx`;3YQWYqYyh-a!n$s_rx$f6%Y+9?W7WZ=HfBJr20}z*x*tQ_$?x5xf zdw9uVl8{&|8tk1n^Tr_fSyJPP+YYLqfzG%WCaCG=_ zQ0T^^)j^r`=93^n^Dr${y39@E6S`hMW*Il1@%yFW_!fU=nVWA%8nCy|6F%#==&oI@ zEStOmt0-Q(4LJ4ltEv@*NPQG*v&Egia5MH!GYuI)LS)lP2*}IJgTu9V`(R20^g&kv zhEJdx_*a^r9OWPNP_}b3!S!i08$2Myol7K32F1%1=pf0Nuiz~4zHzjz9G#NUBBI^- zf9Lsz=5((3t*pZ-u{I!yz&WW?@F&D^cfL|O)AViHF1!ncy8Ys>a`hHA|LF}~c^E(i zr(lp%3)qUcc4ZH?fef_|Mva#10mTL6NnabNZ-Wg=r@aib6RSR0(iMl z3_Mu?3}ayuetvoPry$EN#>d3;b3b0EW@lIac!NiTTf&tr87ZrrVxTi<0ApqLM+>(R zlKrl(kYcefF>Ej*nRRUD@?W7mfOPv)Jh9~%N4IPS-^~r^s5CuMHUpbS=xANQ3IVOY-GqxG2h)AWLE!5*0MdK_@|MuAT&{I?4{l|~}Ld<=Xlm-*-} z`=`c4fhoBAk3On3TgI1XPF!3RczcgG-}zWZmY2_TEh^T5Kz13T+;H`_|Ti!`bDl9O>?Ewpf0E zjQLoPM-zpZ+WQ!&auUtPIQ9_bub(;SNKZEE>`)cbP}M)p(N)XA`In<2^hi~kyppTz zfwFIoc{C|vka#^f`4-vAI-@Rx$!nn?JKt z5l!151&WAeEX9UG_HT1+G*Z$|MFUZ>)s@lr;m$E8+{6O2v)+Ke)OBVDKl&LpR==D; zaCY`2kvOH}EXu{$+_M3?v4Ke&D}#AT*G7|!5Fmzq!h|9suF+>mF6~65{DJEOYy}3N zo52T4P%XJ6fYCIM)@A=Uy+XK z?$XjXbQg*FGs%zBxrS1Y`D7a&V2#I!mB)CiWy>nVm$G=M#3^JiY=9+#Mc%hJCe@Y{ zD{i3b?+!rDrU^r8S}@!gdT*V!o1K-T&Yg_P)HIwqL2{Da!|+Iiu0kP~AnTQD2Wk{R zzP~LW5Ys27sbP!Lh>aKGn~DbX7@pv8H}Co@(NnySG2wh)DLb5!dUxfi6#_ak zaMT<*_^TwyXZIL#*KE_Isg!eWo>sPf=Iz-P$Wh^ZWEmhcUWk>2Ps3f9ipT|zZdqog zSZ7#Uz{+Mxp&N;*LJB>aeCb0R$$WVM^-^n&X(`W$o&ojxIMgJ*JUUwYRZpdd@_H_~ zEryqH5L9^HGs%2Fr5iTnPL>Q%$>rLJr0bz50HyiL@g9#_yMS;hHG->D>=UzQ?ZEZ;@zx@JBz)nZ*w|0xl*5G z&}3dAzK0WuY3Y$pxEZVbtkUZf^HXW0z%=r6j49e5iq@T9j9u1Wg?3Y2N@b{+M$8l! zFDwI2gJXEI@~z6z@v|tty0&yZWq6e!OcmHq$Wo6v z_!T73`o=TMF+Inpxc-CTyJt~6h%imWlx6&7=~2=wEA+-G#dH7PChgKQUa87{u*bb; z;l_LIwF$|hR~%SfRtTuAR4CPTELz|-O?9fyX{ITa8o>3*f;)q%uPgJiII3>td@B^P zYTZ&#)!2C#Q)*Y9w3@*fQ*iTSC}Zzm|JMtS-HBezh1eDu>jQ_E1nSSvscD zZZgl*SD$)6Ul9sOw@*73XpsE3IN@ge*<*a)9={Np(tJ8FkV%1)0kTxfc>?3qpA*^o z^t3H^A6fEZK|=cPB9SXM_HXkC%|PEf|4(Sr;?rJw{J?d>>>^Fg_hng4nQ^%v}9Oy`>G0nX+0z34b+AaZ7hc0RCZ3u;@OkQz{x zx@M>HiVf$R8+kwr!_wt<@OUXCKYRC}=^#kpgW(ECAWagO*!|~!spZMHsTBt67=Xaj L)z4*}Q$iB}+#jCU diff --git a/doc/salome/gui/BLSURFPLUGIN/input/blsurf_hypo.doc b/doc/salome/gui/BLSURFPLUGIN/input/blsurf_hypo.doc index 9bc028a..5702958 100644 --- a/doc/salome/gui/BLSURFPLUGIN/input/blsurf_hypo.doc +++ b/doc/salome/gui/BLSURFPLUGIN/input/blsurf_hypo.doc @@ -3,11 +3,8 @@ \page blsurf_hypo_page BLSURF Parameters hypothesis \anchor blsurf_top -BLSURF Parameters hypothesis works only with \b DISTENE \b BLSurf 2d -algorithm. This algorithm is a commercial software. To obtain a -licence, visit http://www.distene.com/en/corp/eval-distene.html -\tableofcontents +\tableofcontents \section blsurf_general_parameters General parameters @@ -16,96 +13,88 @@ licence, visit http://www.distene.com/en/corp/eval-distene.html - Name - allows defining the name of the hypothesis (BLSURF Parameters_n by default). -- Physical Mesh - can be set to None, Custom - or Size Map +- Physical Mesh - can be set to None, Global size + or Local size - - if set to Custom, allows user input in the in User size, - Max Physical Size and Min Physical Size fields. + - if set to Global size, only the User size, + Max Size and Min Size fields are taken into account. - - if set to Size Map, behaves like Custom mode and takes into - account the custom elements sizes given in the Size Map tab. + - if set to Local size, behaves like Custom mode and takes into + account the "Gradation" parameter and the custom elements sizes given in the + "Local size" tab. -- User size - defines the size of the generated mesh elements. +- Geometrical mesh - can be set to None, Global size -- Max Physical Size - defines the upper limit of mesh element size. + - if set to Global size, allows user input in Mesh angle, + Mesh distance and Gradation fields. These fields control + computation of the element size, so called geometrical size, conform + to the surface geometry considering local curvatures. If both the User size + and the geometrical parameters are defined, the eventual element size + corresponds to the least of the two. -- Min Physical Size - defines the lower limit of mesh element size. +- User size - defines the size of the generated mesh elements. If "Relative value" +is checked, the value is relative to the diagonal of the shape. -- Geometrical mesh - if set to Custom, allows user input in -Angle Mesh S, Angle Mesh C and Gradation -fields. These fields control computation of the element size, so -called geometrical size, conform to the surface geometry -considering local curvatures. If both the User size and the -geometrical size are defined, the eventual element size -corresponds to the least of the two. +- Max Size - defines the upper limit of mesh element size. If "Relative value" +is checked, the value is relative to the diagonal of the shape. -- Angle Mesh S - maximum angle between the mesh face and the -tangent to the geometrical surface at each mesh node, in degrees. +- Min Size - defines the lower limit of mesh element size. If "Relative value" +is checked, the value is relative to the diagonal of the shape. -- Angle Mesh C - maximum angle between the mesh edge and the -tangent to the geometrical curve at each mesh node, in degrees. +- Gradation - maximum ratio between the lengths of two adjacent edges. -- Max Geometrical Size - defines the upper limit of the - geometrical size. +- Quadratic mesh - if checked, quadratic elements will be generated. -- Min Geometrical Size - defines the lower limit of the - geometrical size. +- Mesh angle - Limiting angle (in degree) between the plane of a triangle of the mesh and each of the tangent planes at the three vertices. +The smaller this angle is, the closer the mesh is to the exact surface, and the denser the resulting mesh is. -- Gradation - maximum ratio between the lengths of two adjacent - edges. +- Mesh distance - Maximum desired distance between a triangle and its supporting CAD surface. +The smaller this distance is, the closer the mesh is to the exact surface (only available in isotropic meshing). -- Allow Quadrangles - if checked, allows the creation of - quadrilateral elements. +- Anisotropic - if checked, this parameter defines the maximum anisotropic ratio of the metric governing the anisotropic meshing process. +The default value (0) means that the metric (and thus the generated elements) can be arbitrarily stretched. -- Patch independent - if checked, geometrical edges are not -respected and all geometrical faces are meshed as one hyper-face. +- Remove tiny edges - if checked, the bad elements (slivers) are removed from the generated mesh. +The bad element value defines the aspect ratio triggering the "bad element” classification. -\ref blsurf_top "Back to top" +- Remove bad elements - if checked, the tiny (nano) edges are removed from the generated mesh. +The tiny edge value defines the minimal length under which an edge is considered to be a tiny one. -\section blsurf_advanced_parameters Advanced parameters +- Mesh optimisation - if checked, the mesh will be optimized in order to get better shaped elements. -The notion of diag used in the descriptions means the diagonal -of the bounding box of the geometrical object to mesh. +- Allow Quadrangles - if checked, allows the creation of quadrilateral elements. -\image html blsurf_parameters_advanced.png - -- Verbosity level - defines the percentage of "verbosity" of -BLSURF [0-100]. +\ref blsurf_top "Back to top" -- Topology - allows creation of a conform mesh on a shell of -not sewed faces. The following choices are allowed: +\section blsurf_advanced_parameters Advanced parameters - - "From CAD" means that mesh conformity is assured by conformity - of a shape. +The notion of diag used in the descriptions means the diagonal of the bounding box of the geometrical object to mesh. - - "Pre-process" and "Pre-process++" allow the BLSURF software to - pre-process the geometrical model to eventually produce a conform - mesh. +\image html blsurf_parameters_advanced.png - - "PreCAD" is an auxiliary CAD pre-processing module which has - two main goals: +- PreCAD options -if checked, the PreCAD module will be used. This module has +two main goals: - - Complete missing or inadequate CAD descriptions. + - Complete missing or inadequate CAD descriptions. - - Perform topology reconstruction and specific geometry - enhancement for mesh generation. + - Perform topology reconstruction and specific geometry + enhancement for mesh generation. - \n This module requires a specific licence. The following PreCAD - options are the most significant and important ones: + \n This module requires a specific licence. The following PreCAD + options are the most significant and important ones: - Merge Edges - allows PreCAD to optimize the geometry by merging some - edges. This option is 0 by default. + edges. This option is checked by default. - - Remove nano edges - allows PreCAD to optimize the geometry by removing - the nano edges whenever possible. This option is 0 by default. - - - Nano edge length - gives the length below which an edge is considered as nano - for the topology processing. See also the \b remove_nano_edges option. If unset, PreCAD - default value is \f$\mathrm{diag} \times 10^{-5}\f$. + - Process 3D topology - allows PreCAD to perform the cleanup processing. + This option is checked by default. - Discard input topology - computes the CAD topology from scratch, without considering the topological information contained in the original CAD - (useful for iges files). This option is 0 by default. + (useful for iges files). This option is unchecked by default. + +- Verbosity level - defines the percentage of "verbosity" of +MeshGems-CADSurf and MeshGems-PreCAD [0-100]. - ExportGMF - saves the computed mesh into a GMF file (.mesh or .meshb). @@ -117,27 +106,14 @@ possible to input the value of the option and edit it later. The following BLSURF options are commonly usable: -- \b topo_eps1 (real) - is the tolerance level inside a CAD -patch. By default is equal to \f$\mathrm{diag} \times 10^{-4}\f$. This tolerance is used to -identify nodes to merge within one geometrical face when \b Topology -option is to pre-process. - -- \b topo_eps2 (real) - is the tolerance level between two CAD -patches. By default is equal to \f$\mathrm{diag} \times 10^{-4}\f$. This tolerance is used to -identify nodes to merge over different geometrical faces when -\b Topology option is to pre-process. - -- \b LSS (real) - is an abbreviation for "length of sub-segment". It is -a maximal allowed length of a mesh edge. Default is \f$0.5\f$. - - \b frontal (integer) - 1 - the mesh generator inserts points with an advancing front method. - - 0 - it inserts them with an algebraic method (on internal edges). This method is + - 0 - it inserts them with an algebraic method (on internal edges). This method is slightly faster but generates less regular meshes. - \n Default is 0. + \n Default is 1. - \anchor blsurf_hinterpol_flag \b hinterpol_flag (integer) - determines the computation of an interpolated value v between two points P1 and P2 on a @@ -164,115 +140,57 @@ values: \n Default is 0. -- \b CheckAdjacentEdges, \b CheckCloseEdges and \b CheckWellDefined -(integers) - give the number of calls of equally named subroutines the -purpose of which is to improve the mesh of domains having narrow -parts. At each iteration,\b CheckCloseEdges decreases the sizes of the -edges when two boundary curves are neighboring,\b CheckAdjacentEdges -balances the sizes of adjacent edges, and \b CheckWellDefined checks if -the parametric domain is well defined. Default values are 0. +The following PreCAD options are commonly usable. -- \b CoefRectangle (real)- defines the relative thickness of the rectangles -used by subroutine \b CheckCloseEdges (see above). Default is 0.25. +- \b closed_geometry (boolean) - describes whether the working geometry +should be closed or not. When activated, this option helps PreCAD to process +the dirtiest geometries. By default this option is 0. -- \b eps_collapse (real) - if more than 0.0, BLSURF removes -curves whose lengths are less than \b eps_collapse. To obtain an -approximate value of the length of a curve, it is arbitrarily -split into 20 edges. Default is 0.0. +- \b create_tag_collision (boolean) - creates new tags from original ones in case +of collision (entity merge or association for example). By default +this option is 1. -- \b eps_ends (real) - is used to detect the curves whose lengths are very -small, that sometimes constitutes an error. A message is printed -if \f$\left|P2-P1\right| < eps\_ends\f$, where P1 and P2 are the -extremities of a curve. Default is \f$\frac{\mathrm{diag}}{500.0}\f$. +- \b debug (bool) - If debug = 1 PreCAD will be very verbose and will output +some intermediate files in the working directory. By default this +option is 0. -- \b prefix (char) - is a prefix of the files generated by -BLSURF. Default is "x". +- \b manifold_geometry (int) - describes whether the working geometry should be manifold or not. +When activated, this option helps PreCAD to process the dirtiest +geometries. By default this option is 0. -- \b refs (integer) - reference of a surface, used when exporting -files. Default is 1. +- \b periodic_tolerance (real) - defines the maximum distance error accepted between +two sets of periodic entities. By default this option is \f$\mathrm{diag} \times 10^{-5}\f$. -The following PreCAD options are commonly usable. +- \b remove_tiny_edges (boolean) -optimize the geometry by removing the nano edges whenever possible. +By default this option is 0. -- \b closed_geometry (int) - describes whether the working geometry -should be closed or not. When activated, this option helps PreCAD to process -the dirtiest geometries. By default this option is 0. +- \b required_entities (char) -controls the correction operations. Possible values are: -- \b debug (int) - If debug = 1 PreCAD will be very verbose and will output -some intermediate files in the working directory. By default this -option is 0. + - "respect" - PreCAD is not allowed to correct or optimize a required edge. -- \b eps_nano_relative (real) - the same as \b eps_nano, but relatively to -the diagonal of the box bounding the geometry. By default this option is \f$10^{-5}\f$. + - "ignore" - PreCAD is allowed to correct a required edge. -- \b eps_sewing (real) - tolerance of the assembly. It rarely requires to be tuned. + - "clear" - PreCAD will erase "required" status of each required entities, and will thus + be allowed to correct a required edge. + + \n By default this option is "respect". + +- \b sewing_tolerance (real) - tolerance of the assembly. It rarely requires to be tuned. By default this option is \f$\mathrm{diag} \times 5 \cdot 10^{-4}\f$. -- \b eps_sewing_relative (real) - the same as \b eps_nano but relatively to -the diagonal of the box bounding the geometry. By default this option -is \f$5 \cdot 10^{-4}\f$. +- \b tags (char) -controls the optimisation process. Possible values are: -- \b manifold_geometry (int) - describes whether the working geometry should be manifold or not. -When activated, this option helps PreCAD to process the dirtiest -geometries. By default this option is 0. + - "respect" - PreCAD is not allowed to cross the CAD attributes boundaries for optimisation purpose. -- \b create_tag_collision (int) - creates new tags from original ones in case -of collision (entity merge or association for example). By default -this option is 0. + - "ignore" - PreCAD is allowed to cross the CAD attributes boundaries for optimisation. -- \b periodic_tolerance (real) - defines the maximum distance error accepted between -two sets of periodic entities. By default this option is \f$\mathrm{diag} \times 10^{-5}\f$. + - "clear" - PreCAD will erase each tgas of each entities, and will thus + be allowed to cross the CAD attributes boundaries in its optimisation purpose. -- \b periodic_tolerance_relative (real) - the same as \b periodic_tolerance but in a relative unit. -By default this option is \f$10^{-5}\f$. + \n By default this option is "respect". -- \b periodic_split_tolerance (real) - This periodicity processing related option defines -the minimum distance between a CAD point and an imprinted point. It allows to indirectly -control the number of created points and small edges. By default this -option is \f$\mathrm{diag} \times 10^{-4}\f$. - -- \b periodic_split_tolerance_relative (real - the same as \b -periodic_split_tolerance but in a relative unit. By default this -option is \f$10^{-4}\f$. - -The following advanced options are not documented and you can use them -at your own risk. - -- Integer variables: - - addsurf_ivertex - - anisotropic - - background - - coiter - - communication - - decim - - export_flag - - file_h - - gridnu - - gridnv - - intermedfile - - memory - - normals - - optim - - pardom_flag - - pinch - - rigid - - surforient - - tconf - - topo_collapse -- Real variables: - - addsurf_angle - - addsurf_R - - addsurf_H - - addsurf_FG - - addsurf_r - - addsurf_PA - - angle_compcurv - - angle_ridge - - anisotropic_ratio - - eps_pardom -- String variables: - - export_format - - export_option - - import_option +- \b tiny_edge_length (real) - the length below which en edge is considered as nano for the topology processing. +By default this option is \f$10^{-5}\f$. \ref blsurf_top "Back to top" diff --git a/doc/salome/gui/BLSURFPLUGIN/input/index.doc b/doc/salome/gui/BLSURFPLUGIN/input/index.doc index 3a35d84..83ea929 100644 --- a/doc/salome/gui/BLSURFPLUGIN/input/index.doc +++ b/doc/salome/gui/BLSURFPLUGIN/input/index.doc @@ -7,7 +7,7 @@ used within the SALOME Mesh module for generation of 2D mesh. \note BLSURFPLUGIN plugin uses DISTENE BLSurf commercial meshing software and requires a license at the run time (to work within the -Mesh module). +Mesh module). To obtain a licence, visit http://www.distene.com/en/corp/eval-distene.html \b BLSURFPLUGIN plugin is destined for: - Meshing of the 2D geometric entities. diff --git a/idl/BLSURFPlugin_Algorithm.idl b/idl/BLSURFPlugin_Algorithm.idl index d26ce56..ec9d552 100644 --- a/idl/BLSURFPlugin_Algorithm.idl +++ b/idl/BLSURFPlugin_Algorithm.idl @@ -122,14 +122,6 @@ module BLSURFPlugin */ interface BLSURFPlugin_Hypothesis : SMESH::SMESH_Hypothesis { - /*! - * Sets topology usage way defining how mesh conformity is assured - * value=0 - mesh conformity is assured by conformity of a shape - * value=1,2 - mesh conformity is assured by pre-processing a CAD model - * value=3 - mesh conformity is assured by pre-processing a CAD model with Pre-CAD - */ - void SetTopology(in long way); - long GetTopology(); /*! * Sets a way to define size of mesh elements to generate @@ -140,73 +132,128 @@ module BLSURFPlugin void SetPhysicalMesh(in long isCustom); long GetPhysicalMesh(); + /*! + * Sets a way to define maximum angular deflection of mesh from CAD model + * 0 - deflection is defined automatically + * 1 - deflection is set by SetAngleMesh() method + * 2 - deflection is set by SetAngleMesh() method. A sizemap is defined (TODO). + */ + void SetGeometricMesh(in long isCustom); + long GetGeometricMesh(); + /*! * Sets size of mesh elements to generate */ void SetPhySize(in double size); + void SetPhySizeRel(in double size); double GetPhySize(); + boolean IsPhySizeRel(); /*! - * Sets lower boundary of mesh element size (PhySize) + * Sets lower boundary of mesh element size */ - void SetPhyMin(in double theMinSize); - double GetPhyMin(); + void SetMinSize(in double theMinSize); + void SetMinSizeRel(in double theMinSize); + double GetMinSize(); + boolean IsMinSizeRel(); /*! - * Sets upper boundary of mesh element size (PhySize) + * Sets upper boundary of mesh element size */ - void SetPhyMax(in double theMaxSize); - double GetPhyMax(); + void SetMaxSize(in double theMaxSize); + void SetMaxSizeRel(in double theMaxSize); + double GetMaxSize(); + boolean IsMaxSizeRel(); /*! - * Sets a way to define maximum angular deflection of mesh from CAD model - * 0 - deflection is defined automatically - * 1 - deflection is set by SetAngleMeshS() and SetAngleMeshC() methods + * Sets maximal allowed ratio between the lengths of two adjacent edges */ - void SetGeometricMesh(in long isCustom); - long GetGeometricMesh(); + void SetGradation(in double ratio); + double GetGradation(); /*! - * Sets angular deflection (in degrees) of a mesh face from CAD surface + * Sets to create quadrilateral elements or not */ - void SetAngleMeshS(in double angle); - double GetAngleMeshS(); + void SetQuadAllowed(in boolean allowed); + boolean GetQuadAllowed(); /*! - * Sets angular deflection (in degrees) of a mesh edge from CAD curve + * Sets angular deflection (in degrees) of a mesh face and edge from CAD surface */ - void SetAngleMeshC(in double angle); - double GetAngleMeshC(); + void SetAngleMesh(in double angle); + double GetAngleMesh(); /*! - * Sets lower boundary of mesh element size computed to respect angular deflection + * Sets the maximum desired distance between a triangle and its supporting CAD surface */ - void SetGeoMin(in double theMinSize); - double GetGeoMin(); + void SetChordalError(in double distance); + double GetChordalError(); /*! - * Sets upper boundary of mesh element size computed to respect angular deflection + * Determines whether the generated mesh will be isotropic or anisotropic */ - void SetGeoMax(in double theMaxSize); - double GetGeoMax(); + void SetAnisotropic(in boolean anisotropic); + boolean GetAnisotropic(); /*! - * Sets maximal allowed ratio between the lengths of two adjacent edges + * Defines the maximum anisotropic ratio of the metric governing the anisotropic process. + * The default value of 0 means that the metric (and thus the generated elements) + * can be arbitrarily stretched. */ - void SetGradation(in double ratio); - double GetGradation(); + void SetAnisotropicRatio(in double ratio); + double GetAnisotropicRatio(); /*! - * Sets to create quadrilateral elements or not + * This patch-independent correction option can be activated to remove the tiny + * (nano) edges from the generated mesh, without taking into account the tags + * (attributes) specifications. */ - void SetQuadAllowed(in boolean allowed); - boolean GetQuadAllowed(); + void SetRemoveTinyEdges(in boolean remove); + boolean GetRemoveTinyEdges(); + + /*! + * Defines the minimal length under which an edge is considered to be a tiny one + */ + void SetTinyEdgeLength(in double length); + double GetTinyEdgeLength(); + + /*! + * This patch independent correction option can be activated to remove the bad + * elements (often called slivers) from the generated mesh, without taking into account + * the tags (attributes) specification. + */ + void SetBadElementRemoval(in boolean remove); + boolean GetBadElementRemoval(); + + /*! + * This parameter defines the aspect ratio triggering the "bad element" + * classification for the force bad surface element removal option. + */ + void SetBadElementAspectRatio(in double ratio); + double GetBadElementAspectRatio(); + + /*! + * If this option is activated, MeshGems-CADSurf will optimize the mesh in order to + * get better shaped elements, during a process which respects the patch independent options. + * This optimisation cannot be fully performed when correct_surface_intersections = 1. + */ + void SetOptimizeMesh(in boolean optimize); + boolean GetOptimizeMesh(); /*! - * To respect geometrical edges or not + * Determines the order of mesh elements to be generated (linear or quadratic) */ - void SetDecimesh(in boolean toIgnoreEdges); - boolean GetDecimesh(); + void SetQuadraticMesh(in boolean quadratic); + boolean GetQuadraticMesh(); + + /*! + * Sets topology usage way defining how mesh conformity is assured + * value=0 - mesh conformity is assured by conformity of a shape + * value=1,2 - mesh conformity is assured by pre-processing a CAD model (OBSOLETE) + * value=3 - mesh conformity is assured by pre-processing a CAD model with Pre-CAD + */ + void SetTopology(in long way); + long GetTopology(); /*! * Sets verbosity level in the range 0 to 100. @@ -221,10 +268,16 @@ module BLSURFPlugin boolean GetPreCADMergeEdges(); /*! - * To remove nano edges. + * To process 3D topology. */ - void SetPreCADRemoveNanoEdges(in boolean toRemoveNanoEdges); - boolean GetPreCADRemoveNanoEdges(); + void SetPreCADProcess3DTopology(in boolean toProcess); + boolean GetPreCADProcess3DTopology(); + +// /*! +// * To remove nano edges. +// */ +// void SetPreCADRemoveNanoEdges(in boolean toRemoveNanoEdges); +// boolean GetPreCADRemoveNanoEdges(); /*! * To compute topology from scratch @@ -232,12 +285,12 @@ module BLSURFPlugin void SetPreCADDiscardInput(in boolean toDiscardInput); boolean GetPreCADDiscardInput(); - /*! - * Sets the length below which an edge is considered as nano - * for the topology processing. - */ - void SetPreCADEpsNano(in double epsNano); - double GetPreCADEpsNano(); +// /*! +// * Sets the length below which an edge is considered as nano +// * for the topology processing. +// */ +// void SetPreCADEpsNano(in double epsNano); +// double GetPreCADEpsNano(); /*! * Sets advanced option value @@ -282,12 +335,14 @@ module BLSURFPlugin * Set/unset a SizeMap on geom object */ void SetSizeMap(in GEOM::GEOM_Object GeomObj, in string sizeMap); + void SetConstantSizeMap(in GEOM::GEOM_Object GeomObj, in double sizeMap); void UnsetSizeMap(in GEOM::GEOM_Object GeomObj); /*! * Set a SizeMap on geom object given by entry */ void SetSizeMapEntry(in string entry, in string sizeMap); + void SetConstantSizeMapEntry(in string entry, in GEOM::shape_type shapeType, in double sizeMap); string GetSizeMapEntry(in string entry); string_array GetSizeMapEntries(); diff --git a/src/BLSURFPlugin/BLSURFPluginDC.py b/src/BLSURFPlugin/BLSURFPluginDC.py index 791744e..c7b5568 100644 --- a/src/BLSURFPlugin/BLSURFPluginDC.py +++ b/src/BLSURFPlugin/BLSURFPluginDC.py @@ -28,16 +28,18 @@ from smesh import AssureGeomPublished FromCAD, PreProcess, PreProcessPlus, PreCAD = 0,1,2,3 # Element size flag of BLSURF -DefaultSize, DefaultGeom, BLSURF_Custom, SizeMap = 0,0,1,2 +DefaultSize, DefaultGeom, BLSURF_GlobalSize, BLSURF_LocalSize = 0,0,1,2 +# Retrocompatibility +BLSURF_Custom, SizeMap = BLSURF_GlobalSize, BLSURF_LocalSize # import BLSURFPlugin module if possible noBLSURFPlugin = 0 try: - import BLSURFPlugin + import BLSURFPlugin except ImportError: - noBLSURFPlugin = 1 - pass + noBLSURFPlugin = 1 + pass #---------------------------- # Mesh algo type identifiers @@ -56,333 +58,432 @@ BLSURF = "BLSURF" # class BLSURF_Algorithm(Mesh_Algorithm): - ## name of the dynamic method in smesh.Mesh class - # @internal - meshMethod = "Triangle" - ## type of algorithm used with helper function in smesh.Mesh class - # @internal - algoType = BLSURF - ## doc string of the method - # @internal - docHelper = "Creates triangle 2D algorithm for faces" - - _angleMeshS = 8 - _gradation = 1.1 - - ## Private constructor. - # @param mesh parent mesh object algorithm is assigned to - # @param geom geometry (shape/sub-shape) algorithm is assigned to; - # if it is @c 0 (default), the algorithm is assigned to the main shape - def __init__(self, mesh, geom=0): - Mesh_Algorithm.__init__(self) - if noBLSURFPlugin: - print "Warning: BLSURFPlugin module unavailable" - self.Create(mesh, geom, BLSURF, "libBLSURFEngine.so") - self.params=None - #self.SetPhysicalMesh() - PAL19680 - pass - - ## Sets a way to define size of mesh elements to generate. - # @param thePhysicalMesh is: DefaultSize, BLSURF_Custom or SizeMap. - def SetPhysicalMesh(self, thePhysicalMesh=DefaultSize): - self.Parameters().SetPhysicalMesh(thePhysicalMesh) - pass - - ## Sets size of mesh elements to generate. - # @param theVal value of mesh element size - def SetPhySize(self, theVal): - self.Parameters().SetPhySize(theVal) - pass - - ## Sets lower boundary of mesh element size (PhySize). - # @param theVal value of mesh element minimal size - def SetPhyMin(self, theVal=-1): - self.Parameters().SetPhyMin(theVal) - pass - - ## Sets upper boundary of mesh element size (PhySize). - # @param theVal value of mesh element maximal size - def SetPhyMax(self, theVal=-1): - self.Parameters().SetPhyMax(theVal) - pass - - ## Sets a way to define maximum angular deflection of mesh from CAD model. - # @param theGeometricMesh is: 0 (None) or 1 (Custom) - def SetGeometricMesh(self, theGeometricMesh=0): - if self.Parameters().GetPhysicalMesh() == 0: theGeometricMesh = 1 - self.Parameters().SetGeometricMesh(theGeometricMesh) - pass - - ## Sets angular deflection (in degrees) of a mesh face from CAD surface. - # @param theVal value of angular deflection for mesh face - def SetAngleMeshS(self, theVal=_angleMeshS): - if self.Parameters().GetGeometricMesh() == 0: theVal = self._angleMeshS - self.Parameters().SetAngleMeshS(theVal) - pass - - ## Sets angular deflection (in degrees) of a mesh edge from CAD curve. - # @param theVal value of angular deflection for mesh edge - def SetAngleMeshC(self, theVal=_angleMeshS): - if self.Parameters().GetGeometricMesh() == 0: theVal = self._angleMeshS - self.Parameters().SetAngleMeshC(theVal) - pass - - ## Sets lower boundary of mesh element size computed to respect angular deflection. - # @param theVal value of mesh element minimal size - def SetGeoMin(self, theVal=-1): - self.Parameters().SetGeoMin(theVal) - pass - - ## Sets upper boundary of mesh element size computed to respect angular deflection. - # @param theVal value of mesh element maximal size - def SetGeoMax(self, theVal=-1): - self.Parameters().SetGeoMax(theVal) - pass - - ## Sets maximal allowed ratio between the lengths of two adjacent edges. - # @param theVal value of maximal length ratio - def SetGradation(self, theVal=_gradation): - if self.Parameters().GetGeometricMesh() == 0: theVal = self._gradation - self.Parameters().SetGradation(theVal) - pass - - ## Sets topology usage way. - # @param way defines how mesh conformity is assured - # - FromCAD - mesh conformity is assured by conformity of a shape - # - PreProcess or PreProcessPlus - by pre-processing a CAD model - # - PreCAD - by pre-processing with PreCAD a CAD model - def SetTopology(self, way): - self.Parameters().SetTopology(way) - pass - - ## To respect geometrical edges or not. - # @param toIgnoreEdges "ignore edges" flag value - def SetDecimesh(self, toIgnoreEdges=False): - self.Parameters().SetDecimesh(toIgnoreEdges) - pass - - ## Sets verbosity level in the range 0 to 100. - # @param level verbosity level - def SetVerbosity(self, level): - self.Parameters().SetVerbosity(level) - pass - - ## To optimize merges edges. - # @param toMergeEdges "merge edges" flag value - def SetPreCADMergeEdges(self, toMergeEdges=False): - self.Parameters().SetPreCADMergeEdges(toMergeEdges) - pass - - ## To remove nano edges. - # @param toRemoveNanoEdges "remove nano edges" flag value - def SetPreCADRemoveNanoEdges(self, toRemoveNanoEdges=False): - self.Parameters().SetPreCADRemoveNanoEdges(toRemoveNanoEdges) - pass - - ## To compute topology from scratch - # @param toDiscardInput "discard input" flag value - def SetPreCADDiscardInput(self, toDiscardInput=False): - self.Parameters().SetPreCADDiscardInput(toDiscardInput) - pass - - ## Sets the length below which an edge is considered as nano - # for the topology processing. - # @param epsNano nano edge length threshold value - def SetPreCADEpsNano(self, epsNano): - self.Parameters().SetPreCADEpsNano(epsNano) - pass - - ## Sets advanced option value. - # @param optionName advanced option name - # @param level advanced option value - def SetOptionValue(self, optionName, level): - self.Parameters().SetOptionValue(optionName,level) - pass - - ## Sets advanced PreCAD option value. - # @param optionName name of the option - # @param optionValue value of the option - def SetPreCADOptionValue(self, optionName, optionValue): - self.Parameters().SetPreCADOptionValue(optionName,optionValue) - pass - - ## Sets GMF file for export at computation - # @param fileName GMF file name - def SetGMFFile(self, fileName): - self.Parameters().SetGMFFile(fileName) - pass - - #----------------------------------------- - # Enforced vertices (BLSURF) - #----------------------------------------- - - ## To get all the enforced vertices - def GetAllEnforcedVertices(self): - return self.Parameters().GetAllEnforcedVertices() - - ## To get all the enforced vertices sorted by face (or group, compound) - def GetAllEnforcedVerticesByFace(self): - return self.Parameters().GetAllEnforcedVerticesByFace() - - ## To get all the enforced vertices sorted by coords of input vertices - def GetAllEnforcedVerticesByCoords(self): - return self.Parameters().GetAllEnforcedVerticesByCoords() - - ## To get all the coords of input vertices sorted by face (or group, compound) - def GetAllCoordsByFace(self): - return self.Parameters().GetAllCoordsByFace() - - ## To get all the enforced vertices on a face (or group, compound) - # @param theFace : GEOM face (or group, compound) on which to define an enforced vertex - def GetEnforcedVertices(self, theFace): - AssureGeomPublished( self.mesh, theFace ) - return self.Parameters().GetEnforcedVertices(theFace) - - ## To clear all the enforced vertices - def ClearAllEnforcedVertices(self): - return self.Parameters().ClearAllEnforcedVertices() - - ## To set an enforced vertex on a face (or group, compound) given the coordinates of a point. If the point is not on the face, it will projected on it. If there is no projection, no enforced vertex is created. - # @param theFace : GEOM face (or group, compound) on which to define an enforced vertex - # @param x : x coordinate - # @param y : y coordinate - # @param z : z coordinate - # @param vertexName : name of the enforced vertex - # @param groupName : name of the group - def SetEnforcedVertex(self, theFace, x, y, z, vertexName = "", groupName = ""): - AssureGeomPublished( self.mesh, theFace ) - if vertexName == "": - if groupName == "": - return self.Parameters().SetEnforcedVertex(theFace, x, y, z) - else: - return self.Parameters().SetEnforcedVertexWithGroup(theFace, x, y, z, groupName) - pass - else: - if groupName == "": - return self.Parameters().SetEnforcedVertexNamed(theFace, x, y, z, vertexName) - else: - return self.Parameters().SetEnforcedVertexNamedWithGroup(theFace, x, y, z, vertexName, groupName) - pass - pass - - ## To set an enforced vertex on a face (or group, compound) given a GEOM vertex, group or compound. - # @param theFace : GEOM face (or group, compound) on which to define an enforced vertex - # @param theVertex : GEOM vertex (or group, compound) to be projected on theFace. - # @param groupName : name of the group - def SetEnforcedVertexGeom(self, theFace, theVertex, groupName = ""): - AssureGeomPublished( self.mesh, theFace ) - AssureGeomPublished( self.mesh, theVertex ) - if groupName == "": - return self.Parameters().SetEnforcedVertexGeom(theFace, theVertex) - else: - return self.Parameters().SetEnforcedVertexGeomWithGroup(theFace, theVertex,groupName) - pass - - ## To remove an enforced vertex on a given GEOM face (or group, compound) given the coordinates. - # @param theFace : GEOM face (or group, compound) on which to remove the enforced vertex - # @param x : x coordinate - # @param y : y coordinate - # @param z : z coordinate - def UnsetEnforcedVertex(self, theFace, x, y, z): - AssureGeomPublished( self.mesh, theFace ) - return self.Parameters().UnsetEnforcedVertex(theFace, x, y, z) - - ## To remove an enforced vertex on a given GEOM face (or group, compound) given a GEOM vertex, group or compound. - # @param theFace : GEOM face (or group, compound) on which to remove the enforced vertex - # @param theVertex : GEOM vertex (or group, compound) to remove. - def UnsetEnforcedVertexGeom(self, theFace, theVertex): - AssureGeomPublished( self.mesh, theFace ) - AssureGeomPublished( self.mesh, theVertex ) - return self.Parameters().UnsetEnforcedVertexGeom(theFace, theVertex) - - ## To remove all enforced vertices on a given face. - # @param theFace : face (or group/compound of faces) on which to remove all enforced vertices - def UnsetEnforcedVertices(self, theFace): - AssureGeomPublished( self.mesh, theFace ) - return self.Parameters().UnsetEnforcedVertices(theFace) - - ## To tell BLSURF to add a node on internal vertices - # @param toEnforceInternalVertices : boolean; if True the internal vertices are added as enforced vertices - def SetInternalEnforcedVertexAllFaces(self, toEnforceInternalVertices): - return self.Parameters().SetInternalEnforcedVertexAllFaces(toEnforceInternalVertices) - - ## To know if BLSURF will add a node on internal vertices - def GetInternalEnforcedVertexAllFaces(self): - return self.Parameters().GetInternalEnforcedVertexAllFaces() - - ## To define a group for the nodes of internal vertices - # @param groupName : string; name of the group - def SetInternalEnforcedVertexAllFacesGroup(self, groupName): - return self.Parameters().SetInternalEnforcedVertexAllFacesGroup(groupName) - - ## To get the group name of the nodes of internal vertices - def GetInternalEnforcedVertexAllFacesGroup(self): - return self.Parameters().GetInternalEnforcedVertexAllFacesGroup() - - #----------------------------------------- - # Attractors - #----------------------------------------- - - ## Sets an attractor on the chosen face. The mesh size will decrease exponentially with the distance from theAttractor, following the rule h(d) = theEndSize - (theEndSize - theStartSize) * exp [ - ( d / theInfluenceDistance ) ^ 2 ] - # @param theFace : face on which the attractor will be defined - # @param theAttractor : geometrical object from which the mesh size "h" decreases exponentially - # @param theStartSize : mesh size on theAttractor - # @param theEndSize : maximum size that will be reached on theFace - # @param theInfluenceDistance : influence of the attractor ( the size grow slower on theFace if it's high) - # @param theConstantSizeDistance : distance until which the mesh size will be kept constant on theFace - def SetAttractorGeom(self, theFace, theAttractor, theStartSize, theEndSize, theInfluenceDistance, theConstantSizeDistance): - AssureGeomPublished( self.mesh, theFace ) - AssureGeomPublished( self.mesh, theAttractor ) - self.Parameters().SetAttractorGeom(theFace, theAttractor, theStartSize, theEndSize, theInfluenceDistance, theConstantSizeDistance) - pass - - ## Unsets an attractor on the chosen face. - # @param theFace : face on which the attractor has to be removed - def UnsetAttractorGeom(self, theFace): - AssureGeomPublished( self.mesh, theFace ) - self.Parameters().SetAttractorGeom(theFace) - pass - - #----------------------------------------- - # Size maps (BLSURF) - #----------------------------------------- - - ## To set a size map on a face, edge or vertex (or group, compound) given Python function. - # If theObject is a face, the function can be: def f(u,v): return u+v - # If theObject is an edge, the function can be: def f(t): return t/2 - # If theObject is a vertex, the function can be: def f(): return 10 - # @param theObject : GEOM face, edge or vertex (or group, compound) on which to define a size map - # @param theSizeMap : Size map defined as a string - def SetSizeMap(self, theObject, theSizeMap): - AssureGeomPublished( self.mesh, theObject ) - self.Parameters().SetSizeMap(theObject, theSizeMap) - pass - - ## To remove a size map defined on a face, edge or vertex (or group, compound) - # @param theObject : GEOM face, edge or vertex (or group, compound) on which to define a size map - def UnsetSizeMap(self, theObject): - AssureGeomPublished( self.mesh, theObject ) - self.Parameters().UnsetSizeMap(theObject) - pass - - ## To remove all the size maps - def ClearSizeMaps(self): - self.Parameters().ClearSizeMaps() - pass - - ## Sets QuadAllowed flag. - # @param toAllow "allow quadrangles" flag value - def SetQuadAllowed(self, toAllow=True): - self.Parameters().SetQuadAllowed(toAllow) - pass - - ## Defines hypothesis having several parameters - # @return hypothesis object - def Parameters(self): - if not self.params: - self.params = self.Hypothesis("BLSURF_Parameters", [], - "libBLSURFEngine.so", UseExisting=0) - pass - return self.params - - pass # end of BLSURF_Algorithm class + ## name of the dynamic method in smesh.Mesh class + # @internal + meshMethod = "Triangle" + ## type of algorithm used with helper function in smesh.Mesh class + # @internal + algoType = BLSURF + ## doc string of the method + # @internal + docHelper = "Creates triangle 2D algorithm for faces" + + _anisotropic_ratio = 0 + _bad_surface_element_aspect_ratio = 1000 + _geometric_approximation = 22 + _gradation = 1.3 + _metric = "isotropic" + _remove_tiny_edges = 0 + + ## Private constructor. + # @param mesh parent mesh object algorithm is assigned to + # @param geom geometry (shape/sub-shape) algorithm is assigned to; + # if it is @c 0 (default), the algorithm is assigned to the main shape + def __init__(self, mesh, geom=0): + Mesh_Algorithm.__init__(self) + if noBLSURFPlugin: + print "Warning: BLSURFPlugin module unavailable" + self.Create(mesh, geom, BLSURF, "libBLSURFEngine.so") + self.params=None + #self.SetPhysicalMesh() - PAL19680 + pass + + ## Sets a way to define size of mesh elements to generate. + # @param thePhysicalMesh is: DefaultSize, BLSURF_Custom or SizeMap. + def SetPhysicalMesh(self, thePhysicalMesh=DefaultSize): + physical_size_mode = thePhysicalMesh + if self.Parameters().GetGeometricMesh() == DefaultGeom: + if physical_size_mode == DefaultSize: + physical_size_mode = BLSURF_GlobalSize + self.Parameters().SetPhysicalMesh(physical_size_mode) + pass + + ## Sets a way to define maximum angular deflection of mesh from CAD model. + # @param theGeometricMesh is: DefaultGeom (0)) or BLSURF_GlobalSize (1)) + def SetGeometricMesh(self, theGeometricMesh=DefaultGeom): + geometric_size_mode = theGeometricMesh + if self.Parameters().GetPhysicalMesh() == DefaultSize: + if geometric_size_mode == DefaultGeom: + geometric_size_mode = BLSURF_GlobalSize + self.Parameters().SetGeometricMesh(geometric_size_mode) + pass + + ## Sets size of mesh elements to generate. + # @param theVal : constant global size when using a global physical size. + # @param isRelative : if True, the value is relative to the length of the diagonal of the bounding box + def SetPhySize(self, theVal, isRelative = False): + if self.Parameters().GetPhysicalMesh() == DefaultSize: + self.SetPhysicalMesh(BLSURF_GlobalSize) + if isRelative: + self.Parameters().SetPhySizeRel(theVal) + else: + self.Parameters().SetPhySize(theVal) + pass + + ## Sets lower boundary of mesh element size. + # @param theVal : global minimal cell size desired. + # @param isRelative : if True, the value is relative to the length of the diagonal of the bounding box + def SetMinSize(self, theVal=-1, isRelative = False): + if isRelative: + self.Parameters().SetMinSizeRel(theVal) + else: + self.Parameters().SetMinSize(theVal) + pass + + ## Sets upper boundary of mesh element size. + # @param theVal : global maximal cell size desired. + # @param isRelative : if True, the value is relative to the length of the diagonal of the bounding box + def SetMaxSize(self, theVal=-1): + if isRelative: + self.Parameters().SetMaxSizeRel(theVal) + else: + self.Parameters().SetMaxSize(theVal) + pass + + ## Sets angular deflection (in degrees) from CAD surface. + # @param theVal value of angular deflection + def SetAngleMesh(self, theVal=_geometric_approximation): + if self.Parameters().GetGeometricMesh() == DefaultGeom: + self.SetGeometricMesh(BLSURF_GlobalSize) + self.Parameters().SetAngleMesh(theVal) + pass + + ## Sets maximal allowed ratio between the lengths of two adjacent edges. + # @param theVal value of maximal length ratio + def SetGradation(self, theVal=_gradation): + if self.Parameters().GetGeometricMesh() == 0: theVal = self._gradation + self.Parameters().SetGradation(theVal) + pass + + ## Sets topology usage way. + # @param way defines how mesh conformity is assured

    + #
  • FromCAD - mesh conformity is assured by conformity of a shape
  • + #
  • PreProcess or PreProcessPlus - by pre-processing a CAD model (OBSOLETE: FromCAD will be used)
  • + #
  • PreCAD - by pre-processing with PreCAD a CAD model
+ def SetTopology(self, way): + if way != PreCAD: + print "Warning: topology mode %d is no longer supported. Mode FromCAD is used."%way + way = FromCAD + self.Parameters().SetTopology(way) + pass + + ## To respect geometrical edges or not. + # @param toIgnoreEdges "ignore edges" flag value + def SetDecimesh(self, toIgnoreEdges=False): + if toIgnoreEdges: + self.SetOptionValue("respect_geometry","0") + else: + self.SetOptionValue("respect_geometry","1") + pass + + ## Sets verbosity level in the range 0 to 100. + # @param level verbosity level + def SetVerbosity(self, level): + self.Parameters().SetVerbosity(level) + pass + + ## To optimize merges edges. + # @param toMergeEdges "merge edges" flag value + def SetPreCADMergeEdges(self, toMergeEdges=False): + if self.Parameters().GetTopology() != PreCAD: + self.SetTopology(PreCAD) + self.Parameters().SetPreCADMergeEdges(toMergeEdges) + pass + + ## To process 3D topology. + # @param toProcess "PreCAD process 3D" flag value + def SetPreCADProcess3DTopology(self, toProcess=False): + if self.Parameters().GetTopology() != PreCAD: + self.SetTopology(PreCAD) + self.Parameters().SetPreCADProcess3DTopology(toProcess) + pass + + ## To remove nano edges. + # @param toRemoveNanoEdges "remove nano edges" flag value + def SetPreCADRemoveNanoEdges(self, toRemoveNanoEdges=False): + if toRemoveNanoEdges: + self.SetPreCADOptionValue("remove_tiny_edges","1") + else: + self.SetPreCADOptionValue("remove_tiny_edges","0") + pass + + ## To compute topology from scratch + # @param toDiscardInput "discard input" flag value + def SetPreCADDiscardInput(self, toDiscardInput=False): + if self.Parameters().GetTopology() != PreCAD: + self.SetTopology(PreCAD) + self.Parameters().SetPreCADDiscardInput(toDiscardInput) + pass + + ## Sets the length below which an edge is considered as nano + # for the topology processing. + # @param epsNano nano edge length threshold value + def SetPreCADEpsNano(self, epsNano): + self.SetPreCADOptionValue("tiny_edge_length","%f"%epsNano) + pass + + ## Sets advanced option value. + # @param optionName advanced option name + # @param level advanced option value + def SetOptionValue(self, optionName, level): + self.Parameters().SetOptionValue(optionName,level) + pass + + ## Sets advanced PreCAD option value. + # @param optionName name of the option + # @param optionValue value of the option + def SetPreCADOptionValue(self, optionName, optionValue): + if self.Parameters().GetTopology() != PreCAD: + self.SetTopology(PreCAD) + self.Parameters().SetPreCADOptionValue(optionName,optionValue) + pass + + ## Sets GMF file for export at computation + # @param fileName GMF file name + def SetGMFFile(self, fileName): + self.Parameters().SetGMFFile(fileName) + pass + + #----------------------------------------- + # Enforced vertices (BLSURF) + #----------------------------------------- + + ## To get all the enforced vertices + def GetAllEnforcedVertices(self): + return self.Parameters().GetAllEnforcedVertices() + + ## To get all the enforced vertices sorted by face (or group, compound) + def GetAllEnforcedVerticesByFace(self): + return self.Parameters().GetAllEnforcedVerticesByFace() + + ## To get all the enforced vertices sorted by coords of input vertices + def GetAllEnforcedVerticesByCoords(self): + return self.Parameters().GetAllEnforcedVerticesByCoords() + + ## To get all the coords of input vertices sorted by face (or group, compound) + def GetAllCoordsByFace(self): + return self.Parameters().GetAllCoordsByFace() + + ## To get all the enforced vertices on a face (or group, compound) + # @param theFace : GEOM face (or group, compound) on which to define an enforced vertex + def GetEnforcedVertices(self, theFace): + AssureGeomPublished( self.mesh, theFace ) + return self.Parameters().GetEnforcedVertices(theFace) + + ## To clear all the enforced vertices + def ClearAllEnforcedVertices(self): + return self.Parameters().ClearAllEnforcedVertices() + + ## To set an enforced vertex on a face (or group, compound) given the coordinates of a point. If the point is not on the face, it will projected on it. If there is no projection, no enforced vertex is created. + # @param theFace : GEOM face (or group, compound) on which to define an enforced vertex + # @param x : x coordinate + # @param y : y coordinate + # @param z : z coordinate + # @param vertexName : name of the enforced vertex + # @param groupName : name of the group + def SetEnforcedVertex(self, theFace, x, y, z, vertexName = "", groupName = ""): + AssureGeomPublished( self.mesh, theFace ) + if vertexName == "": + if groupName == "": + return self.Parameters().SetEnforcedVertex(theFace, x, y, z) + else: + return self.Parameters().SetEnforcedVertexWithGroup(theFace, x, y, z, groupName) + pass + else: + if groupName == "": + return self.Parameters().SetEnforcedVertexNamed(theFace, x, y, z, vertexName) + else: + return self.Parameters().SetEnforcedVertexNamedWithGroup(theFace, x, y, z, vertexName, groupName) + pass + pass + + ## To set an enforced vertex on a face (or group, compound) given a GEOM vertex, group or compound. + # @param theFace : GEOM face (or group, compound) on which to define an enforced vertex + # @param theVertex : GEOM vertex (or group, compound) to be projected on theFace. + # @param groupName : name of the group + def SetEnforcedVertexGeom(self, theFace, theVertex, groupName = ""): + AssureGeomPublished( self.mesh, theFace ) + AssureGeomPublished( self.mesh, theVertex ) + if groupName == "": + return self.Parameters().SetEnforcedVertexGeom(theFace, theVertex) + else: + return self.Parameters().SetEnforcedVertexGeomWithGroup(theFace, theVertex,groupName) + pass + + ## To remove an enforced vertex on a given GEOM face (or group, compound) given the coordinates. + # @param theFace : GEOM face (or group, compound) on which to remove the enforced vertex + # @param x : x coordinate + # @param y : y coordinate + # @param z : z coordinate + def UnsetEnforcedVertex(self, theFace, x, y, z): + AssureGeomPublished( self.mesh, theFace ) + return self.Parameters().UnsetEnforcedVertex(theFace, x, y, z) + + ## To remove an enforced vertex on a given GEOM face (or group, compound) given a GEOM vertex, group or compound. + # @param theFace : GEOM face (or group, compound) on which to remove the enforced vertex + # @param theVertex : GEOM vertex (or group, compound) to remove. + def UnsetEnforcedVertexGeom(self, theFace, theVertex): + AssureGeomPublished( self.mesh, theFace ) + AssureGeomPublished( self.mesh, theVertex ) + return self.Parameters().UnsetEnforcedVertexGeom(theFace, theVertex) + + ## To remove all enforced vertices on a given face. + # @param theFace : face (or group/compound of faces) on which to remove all enforced vertices + def UnsetEnforcedVertices(self, theFace): + AssureGeomPublished( self.mesh, theFace ) + return self.Parameters().UnsetEnforcedVertices(theFace) + + ## To tell BLSURF to add a node on internal vertices + # @param toEnforceInternalVertices : boolean; if True the internal vertices are added as enforced vertices + def SetInternalEnforcedVertexAllFaces(self, toEnforceInternalVertices): + return self.Parameters().SetInternalEnforcedVertexAllFaces(toEnforceInternalVertices) + + ## To know if BLSURF will add a node on internal vertices + def GetInternalEnforcedVertexAllFaces(self): + return self.Parameters().GetInternalEnforcedVertexAllFaces() + + ## To define a group for the nodes of internal vertices + # @param groupName : string; name of the group + def SetInternalEnforcedVertexAllFacesGroup(self, groupName): + return self.Parameters().SetInternalEnforcedVertexAllFacesGroup(groupName) + + ## To get the group name of the nodes of internal vertices + def GetInternalEnforcedVertexAllFacesGroup(self): + return self.Parameters().GetInternalEnforcedVertexAllFacesGroup() + + #----------------------------------------- + # Attractors + #----------------------------------------- + + ## Sets an attractor on the chosen face. The mesh size will decrease exponentially with the distance from theAttractor, following the rule h(d) = theEndSize - (theEndSize - theStartSize) * exp [ - ( d / theInfluenceDistance ) ^ 2 ] + # @param theFace : face on which the attractor will be defined + # @param theAttractor : geometrical object from which the mesh size "h" decreases exponentially + # @param theStartSize : mesh size on theAttractor + # @param theEndSize : maximum size that will be reached on theFace + # @param theInfluenceDistance : influence of the attractor ( the size grow slower on theFace if it's high) + # @param theConstantSizeDistance : distance until which the mesh size will be kept constant on theFace + def SetAttractorGeom(self, theFace, theAttractor, theStartSize, theEndSize, theInfluenceDistance, theConstantSizeDistance): + AssureGeomPublished( self.mesh, theFace ) + AssureGeomPublished( self.mesh, theAttractor ) + self.Parameters().SetAttractorGeom(theFace, theAttractor, theStartSize, theEndSize, theInfluenceDistance, theConstantSizeDistance) + pass + + ## Unsets an attractor on the chosen face. + # @param theFace : face on which the attractor has to be removed + def UnsetAttractorGeom(self, theFace): + AssureGeomPublished( self.mesh, theFace ) + self.Parameters().SetAttractorGeom(theFace) + pass + + #----------------------------------------- + # Size maps (BLSURF) + #----------------------------------------- + + ## To set a size map on a face, edge or vertex (or group, compound) given Python function. + # If theObject is a face, the function can be: def f(u,v): return u+v + # If theObject is an edge, the function can be: def f(t): return t/2 + # If theObject is a vertex, the function can be: def f(): return 10 + # @param theObject : GEOM face, edge or vertex (or group, compound) on which to define a size map + # @param theSizeMap : Size map defined as a string + def SetSizeMap(self, theObject, theSizeMap): + AssureGeomPublished( self.mesh, theObject ) + self.Parameters().SetSizeMap(theObject, theSizeMap) + pass + + ## To set a constant size map on a face, edge or vertex (or group, compound). + # @param theObject : GEOM face, edge or vertex (or group, compound) on which to define a size map + # @param theSizeMap : Size map defined as a double + def SetConstantSizeMap(self, theObject, theSizeMap): + AssureGeomPublished( self.mesh, theObject ) + self.Parameters().SetConstantSizeMap(theObject, theSizeMap) + + ## To remove a size map defined on a face, edge or vertex (or group, compound) + # @param theObject : GEOM face, edge or vertex (or group, compound) on which to define a size map + def UnsetSizeMap(self, theObject): + AssureGeomPublished( self.mesh, theObject ) + self.Parameters().UnsetSizeMap(theObject) + pass + + ## To remove all the size maps + def ClearSizeMaps(self): + self.Parameters().ClearSizeMaps() + pass + + ## Sets QuadAllowed flag. + # @param toAllow "allow quadrangles" flag value + def SetQuadAllowed(self, toAllow=True): + self.Parameters().SetQuadAllowed(toAllow) + pass + + ## Defines hypothesis having several parameters + # @return hypothesis object + def Parameters(self): + if not self.params: + self.params = self.Hypothesis("BLSURF_Parameters", [], + "libBLSURFEngine.so", UseExisting=0) + pass + return self.params + + #===================== + # Obsolete methods + #===================== + # + # SALOME 6.6.0 + # + + ## Sets lower boundary of mesh element size (PhySize). + def SetPhyMin(self, theVal=-1): + """ + Obsolete function. Use SetMinSize. + """ + print "Warning: SetPhyMin is obsolete. Please use SetMinSize" + self.SetMinSize(theVal) + pass + + ## Sets upper boundary of mesh element size (PhySize). + def SetPhyMax(self, theVal=-1): + """ + Obsolete function. Use SetMaxSize. + """ + print "Warning: SetPhyMax is obsolete. Please use SetMaxSize" + self.SetMaxSize(theVal) + pass + + ## Sets angular deflection (in degrees) of a mesh face from CAD surface. + def SetAngleMeshS(self, theVal=_geometric_approximation): + """ + Obsolete function. Use SetAngleMesh. + """ + print "Warning: SetAngleMeshS is obsolete. Please use SetAngleMesh" + self.SetAngleMesh(theVal) + pass + + ## Sets angular deflection (in degrees) of a mesh edge from CAD curve. + def SetAngleMeshC(self, theVal=_geometric_approximation): + """ + Obsolete function. Use SetAngleMesh. + """ + print "Warning: SetAngleMeshC is obsolete. Please use SetAngleMesh" + self.SetAngleMesh(theVal) + pass + + ## Sets lower boundary of mesh element size computed to respect angular deflection. + def SetGeoMin(self, theVal=-1): + """ + Obsolete function. Use SetMinSize. + """ + print "Warning: SetGeoMin is obsolete. Please use SetMinSize" + self.SetMinSize(theVal) + pass + + ## Sets upper boundary of mesh element size computed to respect angular deflection. + def SetGeoMax(self, theVal=-1): + """ + Obsolete function. Use SetMaxSize. + """ + print "Warning: SetGeoMax is obsolete. Please use SetMaxSize" + self.SetMaxSize(theVal) + pass + + + pass # end of BLSURF_Algorithm class \ No newline at end of file diff --git a/src/BLSURFPlugin/BLSURFPlugin_BLSURF.cxx b/src/BLSURFPlugin/BLSURFPlugin_BLSURF.cxx index 3a8abc7..173a7e1 100644 --- a/src/BLSURFPlugin/BLSURFPlugin_BLSURF.cxx +++ b/src/BLSURFPlugin/BLSURFPlugin_BLSURF.cxx @@ -28,9 +28,9 @@ #include "BLSURFPlugin_Attractor.hxx" extern "C"{ -#include -#include -#include +#include +#include +#include } #include @@ -373,6 +373,14 @@ inline std::string to_string(double d) return o.str(); } +inline std::string to_string_rel(double d) +{ + std::ostringstream o; + o << d; + o << 'r'; + return o.str(); +} + inline std::string to_string(int i) { std::ostringstream o; @@ -380,6 +388,14 @@ inline std::string to_string(int i) return o.str(); } +inline std::string to_string_rel(int i) +{ + std::ostringstream o; + o << i; + o << 'r'; + return o.str(); +} + double _smp_phy_size; // #if BLSURF_VERSION_LONG >= "3.1.1" // // sizemap_t *geo_sizemap_e, *geo_sizemap_f; @@ -391,8 +407,6 @@ status_t size_on_surface(integer face_id, real *uv, real *size, void *user_data) status_t size_on_edge(integer edge_id, real t, real *size, void *user_data); status_t size_on_vertex(integer vertex_id, real *size, void *user_data); -double my_u_min=1e6,my_v_min=1e6,my_u_max=-1e6,my_v_max=-1e6; - typedef struct { gp_XY uv; gp_XYZ xyz; @@ -563,7 +577,7 @@ void BLSURFPlugin_BLSURF::createEnforcedVertexOnFace(TopoDS_Shape faceShape, BLS } ///////////////////////////////////////////////////////// -void createAttractorOnFace(TopoDS_Shape GeomShape, std::string AttractorFunction) +void createAttractorOnFace(TopoDS_Shape GeomShape, std::string AttractorFunction, double defaultSize) { MESSAGE("Attractor function: "<< AttractorFunction); double xa, ya, za; // Coordinates of attractor point @@ -641,7 +655,7 @@ void createAttractorOnFace(TopoDS_Shape GeomShape, std::string AttractorFunction // We construct the python function ostringstream attractorFunctionStream; attractorFunctionStream << "def f(u,v): return "; - attractorFunctionStream << _smp_phy_size << "-(" << _smp_phy_size <<"-" << a << ")"; + attractorFunctionStream << defaultSize << "-(" << defaultSize <<"-" << a << ")"; //attractorFunctionStream << "*exp(-((u-("<GetBoundaryBoxSegmentation(); + int _physicalMesh = BLSURFPlugin_Hypothesis::GetDefaultPhysicalMesh(); + int _geometricMesh = BLSURFPlugin_Hypothesis::GetDefaultGeometricMesh(); + double _phySize = BLSURFPlugin_Hypothesis::GetDefaultPhySize(diagonal, bbSegmentation); + bool _phySizeRel = BLSURFPlugin_Hypothesis::GetDefaultPhySizeRel(); + double _minSize = BLSURFPlugin_Hypothesis::GetDefaultMinSize(diagonal); + bool _minSizeRel = BLSURFPlugin_Hypothesis::GetDefaultMinSizeRel(); + double _maxSize = BLSURFPlugin_Hypothesis::GetDefaultMaxSize(diagonal); + bool _maxSizeRel = BLSURFPlugin_Hypothesis::GetDefaultMaxSizeRel(); + double _gradation = BLSURFPlugin_Hypothesis::GetDefaultGradation(); + bool _quadAllowed = BLSURFPlugin_Hypothesis::GetDefaultQuadAllowed(); + double _angleMesh = BLSURFPlugin_Hypothesis::GetDefaultAngleMesh(); + double _chordalError = BLSURFPlugin_Hypothesis::GetDefaultChordalError(diagonal); + bool _anisotropic = BLSURFPlugin_Hypothesis::GetDefaultAnisotropic(); + double _anisotropicRatio = BLSURFPlugin_Hypothesis::GetDefaultAnisotropicRatio(); + bool _removeTinyEdges = BLSURFPlugin_Hypothesis::GetDefaultRemoveTinyEdges(); + double _tinyEdgeLength = BLSURFPlugin_Hypothesis::GetDefaultTinyEdgeLength(diagonal); + bool _badElementRemoval = BLSURFPlugin_Hypothesis::GetDefaultBadElementRemoval(); + double _badElementAspectRatio = BLSURFPlugin_Hypothesis::GetDefaultBadElementAspectRatio(); + bool _optimizeMesh = BLSURFPlugin_Hypothesis::GetDefaultOptimizeMesh(); + bool _quadraticMesh = BLSURFPlugin_Hypothesis::GetDefaultQuadraticMesh(); + int _verb = BLSURFPlugin_Hypothesis::GetDefaultVerbosity(); + int _topology = BLSURFPlugin_Hypothesis::GetDefaultTopology(); // PreCAD - int _precadMergeEdges = BLSURFPlugin_Hypothesis::GetDefaultPreCADMergeEdges(); - int _precadRemoveNanoEdges = BLSURFPlugin_Hypothesis::GetDefaultPreCADRemoveNanoEdges(); - int _precadDiscardInput = BLSURFPlugin_Hypothesis::GetDefaultPreCADDiscardInput(); - double _precadEpsNano = BLSURFPlugin_Hypothesis::GetDefaultPreCADEpsNano(); + int _precadMergeEdges = BLSURFPlugin_Hypothesis::GetDefaultPreCADMergeEdges(); + int _precadProcess3DTopology = BLSURFPlugin_Hypothesis::GetDefaultPreCADProcess3DTopology(); + int _precadDiscardInput = BLSURFPlugin_Hypothesis::GetDefaultPreCADDiscardInput(); if (hyp) { MESSAGE("BLSURFPlugin_BLSURF::SetParameters"); - _topology = (int) hyp->GetTopology(); _physicalMesh = (int) hyp->GetPhysicalMesh(); - _phySize = hyp->GetPhySize(); _geometricMesh = (int) hyp->GetGeometricMesh(); - _angleMeshS = hyp->GetAngleMeshS(); - _angleMeshC = hyp->GetAngleMeshC(); - _gradation = hyp->GetGradation(); + if (hyp->GetPhySize() > 0) + _phySize = hyp->GetPhySize(); + _phySizeRel = hyp->IsPhySizeRel(); + if (hyp->GetMinSize() > 0) + _minSize = hyp->GetMinSize(); + _minSizeRel = hyp->IsMinSizeRel(); + if (hyp->GetMaxSize() > 0) + _maxSize = hyp->GetMaxSize(); + _maxSizeRel = hyp->IsMaxSizeRel(); + if (hyp->GetGradation() > 0) + _gradation = hyp->GetGradation(); _quadAllowed = hyp->GetQuadAllowed(); - _decimesh = hyp->GetDecimesh(); + if (hyp->GetAngleMesh() > 0) + _angleMesh = hyp->GetAngleMesh(); + if (hyp->GetChordalError() > 0) + _chordalError = hyp->GetChordalError(); + _anisotropic = hyp->GetAnisotropic(); + if (hyp->GetAnisotropicRatio() >= 0) + _anisotropicRatio = hyp->GetAnisotropicRatio(); + _removeTinyEdges = hyp->GetRemoveTinyEdges(); + if (hyp->GetTinyEdgeLength() > 0) + _tinyEdgeLength = hyp->GetTinyEdgeLength(); + _badElementRemoval = hyp->GetBadElementRemoval(); + if (hyp->GetBadElementAspectRatio() >= 0) + _badElementAspectRatio = hyp->GetBadElementAspectRatio(); + _optimizeMesh = hyp->GetOptimizeMesh(); + _quadraticMesh = hyp->GetQuadraticMesh(); _verb = hyp->GetVerbosity(); - if ( hyp->GetPhyMin() != ::BLSURFPlugin_Hypothesis::undefinedDouble() ) - blsurf_set_param(bls, "hphymin", to_string(hyp->GetPhyMin()).c_str()); - if ( hyp->GetPhyMax() != ::BLSURFPlugin_Hypothesis::undefinedDouble() ) - blsurf_set_param(bls, "hphymax", to_string(hyp->GetPhyMax()).c_str()); - if ( hyp->GetGeoMin() != ::BLSURFPlugin_Hypothesis::undefinedDouble() ) - blsurf_set_param(bls, "hgeomin", to_string(hyp->GetGeoMin()).c_str()); - if ( hyp->GetGeoMax() != ::BLSURFPlugin_Hypothesis::undefinedDouble() ) - blsurf_set_param(bls, "hgeomax", to_string(hyp->GetGeoMax()).c_str()); + _topology = (int) hyp->GetTopology(); + // PreCAD + _precadMergeEdges = hyp->GetPreCADMergeEdges(); + _precadProcess3DTopology = hyp->GetPreCADProcess3DTopology(); + _precadDiscardInput = hyp->GetPreCADDiscardInput(); const BLSURFPlugin_Hypothesis::TOptionValues & opts = hyp->GetOptionValues(); BLSURFPlugin_Hypothesis::TOptionValues::const_iterator opIt; for ( opIt = opts.begin(); opIt != opts.end(); ++opIt ) if ( !opIt->second.empty() ) { - MESSAGE("blsurf_set_param(): " << opIt->first << " = " << opIt->second); - blsurf_set_param(bls, opIt->first.c_str(), opIt->second.c_str()); + MESSAGE("cadsurf_set_param(): " << opIt->first << " = " << opIt->second); + cadsurf_set_param(css, opIt->first.c_str(), opIt->second.c_str()); } const BLSURFPlugin_Hypothesis::TOptionValues & preCADopts = hyp->GetPreCADOptionValues(); @@ -751,52 +795,89 @@ void BLSURFPlugin_BLSURF::SetParameters( if ( !opIt->second.empty() ) { if (_topology == BLSURFPlugin_Hypothesis::PreCAD) { MESSAGE("precad_set_param(): " << opIt->first << " = " << opIt->second); - blsurf_set_param(bls, opIt->first.c_str(), opIt->second.c_str()); + precad_set_param(pcs, opIt->first.c_str(), opIt->second.c_str()); } } - - // PreCAD - _precadMergeEdges = hyp->GetPreCADMergeEdges(); - _precadRemoveNanoEdges = hyp->GetPreCADRemoveNanoEdges(); - _precadDiscardInput = hyp->GetPreCADDiscardInput(); - _precadEpsNano = hyp->GetPreCADEpsNano(); - - } else { - //0020968: EDF1545 SMESH: Problem in the creation of a mesh group on geometry - // GetDefaultPhySize() sometimes leads to computation failure - _phySize = mesh.GetShapeDiagonalSize() / _gen->GetBoundaryBoxSegmentation(); - MESSAGE("BLSURFPlugin_BLSURF::SetParameters using defaults"); } +// else { +// //0020968: EDF1545 SMESH: Problem in the creation of a mesh group on geometry +// // GetDefaultPhySize() sometimes leads to computation failure +// // GDD 26/07/2012 From Distene documentation, global physical size default value = diag/100 +// _phySize = BLSURFPlugin_Hypothesis::GetDefaultPhySize(diagonal); +// _minSize = BLSURFPlugin_Hypothesis::GetDefaultMinSize(diagonal); +// _maxSize = BLSURFPlugin_Hypothesis::GetDefaultMaxSize(diagonal); +// _chordalError = BLSURFPlugin_Hypothesis::GetDefaultChordalError(diagonal); +// _tinyEdgeLength = BLSURFPlugin_Hypothesis::GetDefaultTinyEdgeLength(diagonal); +// MESSAGE("BLSURFPlugin_BLSURF::SetParameters using defaults"); +// } // PreCAD if (_topology == BLSURFPlugin_Hypothesis::PreCAD) { *use_precad = true; precad_set_param(pcs, "verbose", to_string(_verb).c_str()); precad_set_param(pcs, "merge_edges", _precadMergeEdges ? "1" : "0"); - precad_set_param(pcs, "remove_nano_edges", _precadRemoveNanoEdges ? "1" : "0"); + precad_set_param(pcs, "process_3d_topology", _precadProcess3DTopology ? "1" : "0"); precad_set_param(pcs, "discard_input_topology", _precadDiscardInput ? "1" : "0"); - if ( _precadEpsNano != ::BLSURFPlugin_Hypothesis::undefinedDouble() ) - precad_set_param(pcs, "eps_nano", to_string(_precadEpsNano).c_str()); } - - _smp_phy_size = _phySize; - blsurf_set_param(bls, "topo_points", _topology == BLSURFPlugin_Hypothesis::Process || _topology == BLSURFPlugin_Hypothesis::Process2 ? "1" : "0"); - blsurf_set_param(bls, "topo_curves", _topology == BLSURFPlugin_Hypothesis::Process || _topology == BLSURFPlugin_Hypothesis::Process2 ? "1" : "0"); - blsurf_set_param(bls, "topo_project", _topology == BLSURFPlugin_Hypothesis::Process || _topology == BLSURFPlugin_Hypothesis::Process2 ? "1" : "0"); - blsurf_set_param(bls, "clean_boundary", _topology == BLSURFPlugin_Hypothesis::Process2 ? "1" : "0"); - blsurf_set_param(bls, "close_boundary", _topology == BLSURFPlugin_Hypothesis::Process2 ? "1" : "0"); - blsurf_set_param(bls, "hphy_flag", to_string(_physicalMesh).c_str()); - blsurf_set_param(bls, "hphydef", to_string(_phySize).c_str()); - blsurf_set_param(bls, "hgeo_flag", to_string(_geometricMesh).c_str()); - blsurf_set_param(bls, "relax_size", _decimesh ? "0": to_string(_geometricMesh).c_str()); - blsurf_set_param(bls, "angle_meshs", to_string(_angleMeshS).c_str()); - blsurf_set_param(bls, "angle_meshc", to_string(_angleMeshC).c_str()); - blsurf_set_param(bls, "gradation", to_string(_gradation).c_str()); - blsurf_set_param(bls, "patch_independent", _decimesh ? "1" : "0"); - blsurf_set_param(bls, "element", _quadAllowed ? "q1.0" : "p1"); - blsurf_set_param(bls, "verb", to_string(_verb).c_str()); - if (_physicalMesh == BLSURFPlugin_Hypothesis::SizeMap){ + bool useGradation = false; + switch (_physicalMesh) + { + case BLSURFPlugin_Hypothesis::PhysicalGlobalSize: + cadsurf_set_param(css, "physical_size_mode", "global"); + cadsurf_set_param(css, "global_physical_size", _phySizeRel ? to_string_rel(_phySize).c_str() : to_string(_phySize).c_str()); + break; + case BLSURFPlugin_Hypothesis::PhysicalLocalSize: + cadsurf_set_param(css, "physical_size_mode", "local"); + cadsurf_set_param(css, "global_physical_size", _phySizeRel ? to_string_rel(_phySize).c_str() : to_string(_phySize).c_str()); + useGradation = true; + break; + default: + cadsurf_set_param(css, "physical_size_mode", "none"); + } + + switch (_geometricMesh) + { + case BLSURFPlugin_Hypothesis::GeometricalGlobalSize: + cadsurf_set_param(css, "geometric_size_mode", "global"); + cadsurf_set_param(css, "geometric_approximation", to_string(_angleMesh).c_str()); + cadsurf_set_param(css, "chordal_error", to_string(_chordalError).c_str()); + useGradation = true; + break; + case BLSURFPlugin_Hypothesis::GeometricalLocalSize: + cadsurf_set_param(css, "geometric_size_mode", "local"); + cadsurf_set_param(css, "geometric_approximation", to_string(_angleMesh).c_str()); + cadsurf_set_param(css, "chordal_error", to_string(_chordalError).c_str()); + useGradation = true; + break; + default: + cadsurf_set_param(css, "geometric_size_mode", "none"); + } + + cadsurf_set_param(css, "minsize", _minSizeRel ? to_string_rel(_minSize).c_str() : to_string(_minSize).c_str()); + cadsurf_set_param(css, "maxsize", _maxSizeRel ? to_string_rel(_maxSize).c_str() : to_string(_maxSize).c_str()); + if ( useGradation ) + cadsurf_set_param(css, "gradation", to_string(_gradation).c_str()); + cadsurf_set_param(css, "element_generation", _quadAllowed ? "quad_dominant" : "triangle"); + + + cadsurf_set_param(css, "metric", _anisotropic ? "anisotropic" : "isotropic"); + if ( _anisotropic ) + cadsurf_set_param(css, "anisotropic_ratio", to_string(_anisotropicRatio).c_str()); + cadsurf_set_param(css, "remove_tiny_edges", _removeTinyEdges ? "1" : "0"); + if ( _removeTinyEdges ) + cadsurf_set_param(css, "tiny_edge_length", to_string(_tinyEdgeLength).c_str()); + cadsurf_set_param(css, "force_bad_surface_element_removal", _badElementRemoval ? "1" : "0"); + if ( _badElementRemoval ) + cadsurf_set_param(css, "bad_surface_element_aspect_ratio", to_string(_badElementAspectRatio).c_str()); + cadsurf_set_param(css, "optimisation", _optimizeMesh ? "yes" : "no"); + cadsurf_set_param(css, "element_order", _quadraticMesh ? "quadratic" : "linear"); + cadsurf_set_param(css, "verbose", to_string(_verb).c_str()); + + _smp_phy_size = _phySizeRel ? _phySize*diagonal : _phySize; + std::cout << "_smp_phy_size = " << _smp_phy_size << std::endl; + + if (_physicalMesh == BLSURFPlugin_Hypothesis::PhysicalLocalSize){ TopoDS_Shape GeomShape; TopoDS_Shape AttShape; TopAbs_ShapeEnum GeomType; @@ -808,7 +889,7 @@ void BLSURFPlugin_BLSURF::SetParameters( BLSURFPlugin_Hypothesis::TSizeMap::const_iterator smIt = sizeMaps.begin(); for ( ; smIt != sizeMaps.end(); ++smIt ) { if ( !smIt->second.empty() ) { - MESSAGE("blsurf_set_sizeMap(): " << smIt->first << " = " << smIt->second); + MESSAGE("cadsurf_set_sizeMap(): " << smIt->first << " = " << smIt->second); GeomShape = entryToShape(smIt->first); GeomType = GeomShape.ShapeType(); MESSAGE("Geomtype is " << GeomType); @@ -906,42 +987,46 @@ void BLSURFPlugin_BLSURF::SetParameters( // // TODO appeler le constructeur des attracteurs directement ici MESSAGE("Setting Attractors"); - const BLSURFPlugin_Hypothesis::TSizeMap attractors = BLSURFPlugin_Hypothesis::GetAttractorEntries(hyp); - BLSURFPlugin_Hypothesis::TSizeMap::const_iterator atIt = attractors.begin(); - for ( ; atIt != attractors.end(); ++atIt ) { - if ( !atIt->second.empty() ) { - MESSAGE("blsurf_set_attractor(): " << atIt->first << " = " << atIt->second); - GeomShape = entryToShape(atIt->first); - GeomType = GeomShape.ShapeType(); - // Group Management - if (GeomType == TopAbs_COMPOUND){ - for (TopoDS_Iterator it (GeomShape); it.More(); it.Next()){ - if (it.Value().ShapeType() == TopAbs_FACE){ - HasSizeMapOnFace = true; - createAttractorOnFace(it.Value(), atIt->second); +// if ( !_phySizeRel ) { + const BLSURFPlugin_Hypothesis::TSizeMap attractors = BLSURFPlugin_Hypothesis::GetAttractorEntries(hyp); + BLSURFPlugin_Hypothesis::TSizeMap::const_iterator atIt = attractors.begin(); + for ( ; atIt != attractors.end(); ++atIt ) { + if ( !atIt->second.empty() ) { + MESSAGE("cadsurf_set_attractor(): " << atIt->first << " = " << atIt->second); + GeomShape = entryToShape(atIt->first); + GeomType = GeomShape.ShapeType(); + // Group Management + if (GeomType == TopAbs_COMPOUND){ + for (TopoDS_Iterator it (GeomShape); it.More(); it.Next()){ + if (it.Value().ShapeType() == TopAbs_FACE){ + HasSizeMapOnFace = true; + createAttractorOnFace(it.Value(), atIt->second, _phySizeRel ? _phySize*diagonal : _phySize); + } } } - } - if (GeomType == TopAbs_FACE){ - HasSizeMapOnFace = true; - createAttractorOnFace(GeomShape, atIt->second); - } -/* - if (GeomType == TopAbs_EDGE){ - HasSizeMapOnEdge = true; - HasSizeMapOnFace = true; - EdgeId2SizeMap[TopoDS::Edge(GeomShape).HashCode(IntegerLast())] = atIt->second; - } - if (GeomType == TopAbs_VERTEX){ - HasSizeMapOnVertex = true; - HasSizeMapOnEdge = true; - HasSizeMapOnFace = true; - VertexId2SizeMap[TopoDS::Vertex(GeomShape).HashCode(IntegerLast())] = atIt->second; + if (GeomType == TopAbs_FACE){ + HasSizeMapOnFace = true; + createAttractorOnFace(GeomShape, atIt->second, _phySizeRel ? _phySize*diagonal : _phySize); + } + /* + if (GeomType == TopAbs_EDGE){ + HasSizeMapOnEdge = true; + HasSizeMapOnFace = true; + EdgeId2SizeMap[TopoDS::Edge(GeomShape).HashCode(IntegerLast())] = atIt->second; + } + if (GeomType == TopAbs_VERTEX){ + HasSizeMapOnVertex = true; + HasSizeMapOnEdge = true; + HasSizeMapOnFace = true; + VertexId2SizeMap[TopoDS::Vertex(GeomShape).HashCode(IntegerLast())] = atIt->second; + } + */ } -*/ } - } +// } +// else +// MESSAGE("Impossible to create the attractors when the physical size is relative"); // Class Attractors // temporary commented out for testing @@ -959,7 +1044,7 @@ void BLSURFPlugin_BLSURF::SetParameters( BLSURFPlugin_Hypothesis::TAttractorMap::const_iterator AtIt = class_attractors.begin(); for ( ; AtIt != class_attractors.end(); ++AtIt ) { if ( !AtIt->second->Empty() ) { - // MESSAGE("blsurf_set_attractor(): " << AtIt->first << " = " << AtIt->second); + // MESSAGE("cadsurf_set_attractor(): " << AtIt->first << " = " << AtIt->second); GeomShape = entryToShape(AtIt->first); AttShape = AtIt->second->GetAttractorShape(); GeomType = GeomShape.ShapeType(); @@ -1060,7 +1145,7 @@ void BLSURFPlugin_BLSURF::SetParameters( MESSAGE("Setting Size Map on FACES "); // #if BLSURF_VERSION_LONG < "3.1.1" - blsurf_data_set_sizemap_iso_cad_face(bls, size_on_surface, &_smp_phy_size); + cadsurf_data_set_sizemap_iso_cad_face(css, size_on_surface, &_smp_phy_size); // #else // if (*use_precad) // iso_sizemap_f = sizemap_new(c, distene_sizemap_type_iso_cad_face, (void *)size_on_surface, NULL); @@ -1071,7 +1156,7 @@ void BLSURFPlugin_BLSURF::SetParameters( if (HasSizeMapOnEdge){ MESSAGE("Setting Size Map on EDGES "); // #if BLSURF_VERSION_LONG < "3.1.1" - blsurf_data_set_sizemap_iso_cad_edge(bls, size_on_edge, &_smp_phy_size); + cadsurf_data_set_sizemap_iso_cad_edge(css, size_on_edge, &_smp_phy_size); // #else // if (*use_precad) // iso_sizemap_e = sizemap_new(c, distene_sizemap_type_iso_cad_edge, (void *)size_on_edge, NULL); @@ -1082,7 +1167,7 @@ void BLSURFPlugin_BLSURF::SetParameters( if (HasSizeMapOnVertex){ MESSAGE("Setting Size Map on VERTICES "); // #if BLSURF_VERSION_LONG < "3.1.1" - blsurf_data_set_sizemap_iso_cad_point(bls, size_on_vertex, &_smp_phy_size); + cadsurf_data_set_sizemap_iso_cad_point(css, size_on_vertex, &_smp_phy_size); // #else // if (*use_precad) // iso_sizemap_p = sizemap_new(c, distene_sizemap_type_iso_cad_point, (void *)size_on_vertex, NULL); @@ -1102,16 +1187,16 @@ namespace class BLSURF_Cleaner { context_t * _ctx; - blsurf_session_t* _bls; + cadsurf_session_t* _css; cad_t * _cad; dcad_t * _dcad; public: BLSURF_Cleaner(context_t * ctx, - blsurf_session_t* bls, + cadsurf_session_t* css, cad_t * cad, dcad_t * dcad) : _ctx ( ctx ), - _bls ( bls ), + _css ( css ), _cad ( cad ), _dcad( dcad ) { @@ -1122,9 +1207,9 @@ namespace } void Clean(const bool exceptContext) { - if ( _bls ) + if ( _css ) { - blsurf_session_delete(_bls); _bls = 0; + cadsurf_session_delete(_css); _css = 0; // #if BLSURF_VERSION_LONG >= "3.1.1" // // if(geo_sizemap_e) @@ -1346,8 +1431,8 @@ bool BLSURFPlugin_BLSURF::Compute(SMESH_Mesh& aMesh, const TopoDS_Shape& aShape) SMESH_MesherHelper helper( aMesh ); // do not call helper.IsQuadraticSubMesh() because sub-meshes // may be cleaned and helper.myTLinkNodeMap gets invalid in such a case - const bool haveQudraticSubMesh = SMESH_MesherHelper( aMesh ).IsQuadraticSubMesh( aShape ); - helper.SetIsQuadratic( haveQudraticSubMesh ); + bool haveQuadraticSubMesh = SMESH_MesherHelper( aMesh ).IsQuadraticSubMesh( aShape ); + bool quadraticSubMeshAndViscousLayer = false; bool needMerge = false; set< SMESHDS_SubMesh* > edgeSubmeshes, proxySubmeshes; set< SMESHDS_SubMesh* >& mergeSubmeshes = edgeSubmeshes; @@ -1402,10 +1487,10 @@ bool BLSURFPlugin_BLSURF::Compute(SMESH_Mesh& aMesh, const TopoDS_Shape& aShape) precad_session_t *pcs = precad_session_new(ctx); precad_data_set_cad(pcs, c); - blsurf_session_t *bls = blsurf_session_new(ctx); + cadsurf_session_t *css = cadsurf_session_new(ctx); - // an object that correctly deletes all blsurf objects at destruction - BLSURF_Cleaner cleaner( ctx,bls,c,dcad ); + // an object that correctly deletes all cadsurf objects at destruction + BLSURF_Cleaner cleaner( ctx,css,c,dcad ); MESSAGE("BEGIN SetParameters"); bool use_precad = false; @@ -1413,9 +1498,22 @@ bool BLSURFPlugin_BLSURF::Compute(SMESH_Mesh& aMesh, const TopoDS_Shape& aShape) // #if BLSURF_VERSION_LONG >= "3.1.1" // c, // #endif - _hypothesis, bls, pcs, aMesh, &use_precad); + _hypothesis, css, pcs, aMesh, &use_precad); MESSAGE("END SetParameters"); + haveQuadraticSubMesh = haveQuadraticSubMesh || (_hypothesis != NULL && _hypothesis->GetQuadraticMesh()); + helper.SetIsQuadratic( haveQuadraticSubMesh ); + + // To remove as soon as quadratic mesh is allowed - BEGIN + // GDD: Viscous layer is not allowed with quadratic mesh + if (_haveViscousLayers && haveQuadraticSubMesh ) { + quadraticSubMeshAndViscousLayer = true; + _haveViscousLayers = !haveQuadraticSubMesh; + _comment += "Warning: Viscous layer is not possible with a quadratic mesh, it is ignored."; + error(COMPERR_WARNING, _comment); + } + // To remove as soon as quadratic mesh is allowed - END + // needed to prevent the opencascade memory managmement from freeing things vector curves; vector surfaces; @@ -1484,10 +1582,10 @@ bool BLSURFPlugin_BLSURF::Compute(SMESH_Mesh& aMesh, const TopoDS_Shape& aShape) surfaces.push_back(BRep_Tool::Surface(f)); - /* create an object representing the face for blsurf */ + /* create an object representing the face for cadsurf */ /* where face_id is an integer identifying the face. * surf_function is the function that defines the surface - * (For this face, it will be called by blsurf with your_face_object_ptr + * (For this face, it will be called by cadsurf with your_face_object_ptr * as last parameter. */ cad_face_t *fce = cad_face_new(c, iface, surf_fun, surfaces.back()); @@ -1541,9 +1639,10 @@ bool BLSURFPlugin_BLSURF::Compute(SMESH_Mesh& aMesh, const TopoDS_Shape& aShape) MESSAGE("Check position of vertex =(" << xyzCoords[0] << "," << xyzCoords[1] << "," << xyzCoords[2] << ")"); gp_Pnt P(xyzCoords[0],xyzCoords[1],xyzCoords[2]); BRepClass_FaceClassifier scl(f,P,1e-7); - // scl.Perform() is bugged. The function was rewritten - // scl.Perform(); - BRepClass_FaceClassifierPerform( &scl, f, P, 1e-7 ); + // OCC 6.3sp6 : scl.Perform() is bugged. The function was rewritten + // BRepClass_FaceClassifierPerform(&scl,f,P,1e-7); + // OCC 6.5.2: scl.Perform() is not bugged anymore + scl.Perform(f, P, 1e-7); TopAbs_State result = scl.State(); MESSAGE("Position of point on face: "<MeshElements( helper.IthVertex( 1, e ))); } nodeData.reset( new StdMeshers_FaceSide( f, e, &aMesh, /*isForwrd = */true, - /*ignoreMedium=*/haveQudraticSubMesh, + /*ignoreMedium=*/haveQuadraticSubMesh, viscousMeshPerFace[ iface ])); if ( nodeData->MissVertexNode() ) return error(COMPERR_BAD_INPUT_MESH,"No node on vertex"); @@ -1744,7 +1843,7 @@ bool BLSURFPlugin_BLSURF::Compute(SMESH_Mesh& aMesh, const TopoDS_Shape& aShape) } } - /* attach the edge to the current blsurf face */ + /* attach the edge to the current cadsurf face */ cad_edge_t *edg = cad_edge_new(fce, ic, tmin, tmax, curv_fun, curves.back()); /* by default an edge has no tag (color). @@ -1879,6 +1978,17 @@ bool BLSURFPlugin_BLSURF::Compute(SMESH_Mesh& aMesh, const TopoDS_Shape& aShape) SMDS_NodeIteratorPtr nIt = smDS->GetNodes(); while ( nIt->more() ) meshDS->RemoveFreeNode( nIt->next(), smDS ); } + if ( proxySubmeshes.count( smDS )) + { + needMerge = true; + } + else + { + SMDS_ElemIteratorPtr eIt = smDS->GetElements(); + while ( eIt->more() ) meshDS->RemoveFreeElement( eIt->next(), smDS ); + SMDS_NodeIteratorPtr nIt = smDS->GetNodes(); + while ( nIt->more() ) meshDS->RemoveFreeNode( nIt->next(), smDS ); + } } if (use_precad) { @@ -1917,22 +2027,16 @@ bool BLSURFPlugin_BLSURF::Compute(SMESH_Mesh& aMesh, const TopoDS_Shape& aShape) precad_session_delete(pcs); } - blsurf_data_set_dcad(bls, dcad); + cadsurf_data_set_dcad(css, dcad); if (cleanc) { // Give the pre-processed CAD object to the current BLSurf session - blsurf_data_set_cad(bls, cleanc); + cadsurf_data_set_cad(css, cleanc); } else { // Use the original one - blsurf_data_set_cad(bls, c); + cadsurf_data_set_cad(css, c); } - // #if BLSURF_VERSION_LONG >= "3.1.1" - // blsurf_data_set_sizemap(bls, clean_iso_sizemap_p); - // blsurf_data_set_sizemap(bls, clean_iso_sizemap_e); - // blsurf_data_set_sizemap(bls, clean_iso_sizemap_f); - // #endif - std::cout << std::endl; std::cout << "Beginning of Surface Mesh generation" << std::endl; std::cout << std::endl; @@ -1940,7 +2044,7 @@ bool BLSURFPlugin_BLSURF::Compute(SMESH_Mesh& aMesh, const TopoDS_Shape& aShape) try { OCC_CATCH_SIGNALS; - status = blsurf_compute_mesh(bls); + status = cadsurf_compute_mesh(css); } catch ( std::exception& exc ) { @@ -1955,7 +2059,7 @@ bool BLSURFPlugin_BLSURF::Compute(SMESH_Mesh& aMesh, const TopoDS_Shape& aShape) } catch (...) { if ( _comment.empty() ) - _comment = "Exception in blsurf_compute_mesh()"; + _comment = "Exception in cadsurf_compute_mesh()"; } if ( status != STATUS_OK) { // There was an error while meshing @@ -1969,10 +2073,10 @@ bool BLSURFPlugin_BLSURF::Compute(SMESH_Mesh& aMesh, const TopoDS_Shape& aShape) std::cout << std::endl; mesh_t *msh = NULL; - blsurf_data_get_mesh(bls, &msh); + cadsurf_data_get_mesh(css, &msh); if(!msh){ /* release the mesh object */ - blsurf_data_regain_mesh(bls, msh); + cadsurf_data_regain_mesh(css, msh); return error(_comment); } @@ -1985,25 +2089,12 @@ bool BLSURFPlugin_BLSURF::Compute(SMESH_Mesh& aMesh, const TopoDS_Shape& aShape) bool binaryFound = (GMFFileName.find(".meshb",GMFFileName.length()-6) != std::string::npos); if (!asciiFound && !binaryFound) GMFFileName.append(".mesh"); - /* - if (GMFFileMode) { - if (!binaryFound) { - if (asciiFound) - GMFFileName.append("b"); - else - GMFFileName.append(".meshb"); - } - } - else { - if (!asciiFound) - GMFFileName.append(".mesh"); - } - */ mesh_write_mesh(msh, GMFFileName.c_str()); } - /* retrieve mesh data (see distene/mesh.h) */ + /* retrieve mesh data (see meshgems/mesh.h) */ integer nv, ne, nt, nq, vtx[4], tag; + integer *evedg, *evtri, *evquad, type; real xyz[3]; mesh_get_vertex_count(msh, &nv); @@ -2011,6 +2102,10 @@ bool BLSURFPlugin_BLSURF::Compute(SMESH_Mesh& aMesh, const TopoDS_Shape& aShape) mesh_get_triangle_count(msh, &nt); mesh_get_quadrangle_count(msh, &nq); + evedg = (integer *)mesh_calloc_generic_buffer(msh); + evtri = (integer *)mesh_calloc_generic_buffer(msh); + evquad = (integer *)mesh_calloc_generic_buffer(msh); + SMDS_MeshNode** nodes = new SMDS_MeshNode*[nv+1]; bool* tags = new bool[nv+1]; @@ -2086,7 +2181,6 @@ bool BLSURFPlugin_BLSURF::Compute(SMESH_Mesh& aMesh, const TopoDS_Shape& aShape) } } - // internal points are tagged to zero if(tag > 0 && tag <= pmap.Extent() ){ meshDS->SetNodeOnVertex(nodes[iv], TopoDS::Vertex(pmap(tag))); @@ -2098,8 +2192,9 @@ bool BLSURFPlugin_BLSURF::Compute(SMESH_Mesh& aMesh, const TopoDS_Shape& aShape) /* enumerate edges */ for(int it=1;it<=ne;it++) { - + SMDS_MeshEdge* edg; mesh_get_edge_vertices(msh, it, vtx); + mesh_get_edge_extra_vertices(msh, it, &type, evedg); mesh_get_edge_tag(msh, it, &tag); if (tags[vtx[0]]) { Set_NodeOnEdge(meshDS, nodes[vtx[0]], emap(tag)); @@ -2109,16 +2204,26 @@ bool BLSURFPlugin_BLSURF::Compute(SMESH_Mesh& aMesh, const TopoDS_Shape& aShape) Set_NodeOnEdge(meshDS, nodes[vtx[1]], emap(tag)); tags[vtx[1]] = false; }; - SMDS_MeshEdge* edg = helper.AddEdge(nodes[vtx[0]], nodes[vtx[1]]); + if (type == MESHGEMS_MESH_ELEMENT_TYPE_EDGE3) { + // QUADRATIC EDGE + if (tags[evedg[0]]) { + Set_NodeOnEdge(meshDS, nodes[evedg[0]], emap(tag)); + tags[evedg[0]] = false; + } + edg = meshDS->AddEdge(nodes[vtx[0]], nodes[vtx[1]], nodes[evedg[0]]); + } + else { + edg = helper.AddEdge(nodes[vtx[0]], nodes[vtx[1]]); + } meshDS->SetMeshElementOnShape(edg, TopoDS::Edge(emap(tag))); } /* enumerate triangles */ for(int it=1;it<=nt;it++) { + SMDS_MeshFace* tri; mesh_get_triangle_vertices(msh, it, vtx); - SMDS_MeshFace* tri = helper.AddFace(nodes[vtx[0]], nodes[vtx[1]], nodes[vtx[2]]); + mesh_get_triangle_extra_vertices(msh, it, &type, evtri); mesh_get_triangle_tag(msh, it, &tag); - meshDS->SetMeshElementOnShape(tri, TopoDS::Face(fmap(tag))); if (tags[vtx[0]]) { meshDS->SetNodeOnFace(nodes[vtx[0]], TopoDS::Face(fmap(tag))); tags[vtx[0]] = false; @@ -2131,14 +2236,35 @@ bool BLSURFPlugin_BLSURF::Compute(SMESH_Mesh& aMesh, const TopoDS_Shape& aShape) meshDS->SetNodeOnFace(nodes[vtx[2]], TopoDS::Face(fmap(tag))); tags[vtx[2]] = false; }; + if (type == MESHGEMS_MESH_ELEMENT_TYPE_TRIA6) { + // QUADRATIC TRIANGLE + if (tags[evtri[0]]) { + meshDS->SetNodeOnFace(nodes[evtri[0]], TopoDS::Face(fmap(tag))); + tags[evtri[0]] = false; + } + if (tags[evtri[1]]) { + meshDS->SetNodeOnFace(nodes[evtri[1]], TopoDS::Face(fmap(tag))); + tags[evtri[1]] = false; + } + if (tags[evtri[2]]) { + meshDS->SetNodeOnFace(nodes[evtri[2]], TopoDS::Face(fmap(tag))); + tags[evtri[2]] = false; + } + tri = meshDS->AddFace(nodes[vtx[0]], nodes[vtx[1]], nodes[vtx[2]], + nodes[evtri[0]], nodes[evtri[1]], nodes[evtri[2]]); + } + else { + tri = helper.AddFace(nodes[vtx[0]], nodes[vtx[1]], nodes[vtx[2]]); + } + meshDS->SetMeshElementOnShape(tri, TopoDS::Face(fmap(tag))); } /* enumerate quadrangles */ for(int it=1;it<=nq;it++) { + SMDS_MeshFace* quad; mesh_get_quadrangle_vertices(msh, it, vtx); - SMDS_MeshFace* quad = helper.AddFace(nodes[vtx[0]], nodes[vtx[1]], nodes[vtx[2]], nodes[vtx[3]]); + mesh_get_quadrangle_extra_vertices(msh, it, &type, evquad); mesh_get_quadrangle_tag(msh, it, &tag); - meshDS->SetMeshElementOnShape(quad, TopoDS::Face(fmap(tag))); if (tags[vtx[0]]) { meshDS->SetNodeOnFace(nodes[vtx[0]], TopoDS::Face(fmap(tag))); tags[vtx[0]] = false; @@ -2155,10 +2281,41 @@ bool BLSURFPlugin_BLSURF::Compute(SMESH_Mesh& aMesh, const TopoDS_Shape& aShape) meshDS->SetNodeOnFace(nodes[vtx[3]], TopoDS::Face(fmap(tag))); tags[vtx[3]] = false; }; + if (type == MESHGEMS_MESH_ELEMENT_TYPE_QUAD9) { + // QUADRATIC QUADRANGLE + std::cout << "This is a quadratic quadrangle" << std::endl; + if (tags[evquad[0]]) { + meshDS->SetNodeOnFace(nodes[evquad[0]], TopoDS::Face(fmap(tag))); + tags[evquad[0]] = false; + } + if (tags[evquad[1]]) { + meshDS->SetNodeOnFace(nodes[evquad[1]], TopoDS::Face(fmap(tag))); + tags[evquad[1]] = false; + } + if (tags[evquad[2]]) { + meshDS->SetNodeOnFace(nodes[evquad[2]], TopoDS::Face(fmap(tag))); + tags[evquad[2]] = false; + } + if (tags[evquad[3]]) { + meshDS->SetNodeOnFace(nodes[evquad[3]], TopoDS::Face(fmap(tag))); + tags[evquad[3]] = false; + } + if (tags[evquad[4]]) { + meshDS->SetNodeOnFace(nodes[evquad[4]], TopoDS::Face(fmap(tag))); + tags[evquad[4]] = false; + } + quad = meshDS->AddFace(nodes[vtx[0]], nodes[vtx[1]], nodes[vtx[2]], nodes[vtx[3]], + nodes[evquad[0]], nodes[evquad[1]], nodes[evquad[2]], nodes[evquad[3]], + nodes[evquad[4]]); + } + else { + quad = helper.AddFace(nodes[vtx[0]], nodes[vtx[1]], nodes[vtx[2]], nodes[vtx[3]]); + } + meshDS->SetMeshElementOnShape(quad, TopoDS::Face(fmap(tag))); } /* release the mesh object, the rest is released by cleaner */ - blsurf_data_regain_mesh(bls, msh); + cadsurf_data_regain_mesh(css, msh); delete [] nodes; delete [] tags; @@ -2265,7 +2422,7 @@ bool BLSURFPlugin_BLSURF::Compute(SMESH_Mesh& aMesh, const TopoDS_Shape& aShape) */ MESSAGE("END OF BLSURFPlugin_BLSURF::Compute()"); - return ( status == STATUS_OK ); + return ( status == STATUS_OK && !quadraticSubMeshAndViscousLayer ); } //================================================================================ @@ -2321,7 +2478,7 @@ void BLSURFPlugin_BLSURF::Set_NodeOnEdge(SMESHDS_Mesh* meshDS, SMDS_MeshNode* no meshDS->SetNodeOnEdge(node, edge, pa); } -/* Curve definition function See cad_curv_t in file distene/cad.h for +/* Curve definition function See cad_curv_t in file meshgems/cad.h for * more information. * NOTE : if when your CAD systems evaluates second * order derivatives it also computes first order derivatives and @@ -2362,7 +2519,7 @@ status_t curv_fun(real t, real *uv, real *dt, real *dtt, void *user_data) } /* Surface definition function. - * See cad_surf_t in file distene/cad.h for more information. + * See cad_surf_t in file meshgems/cad.h for more information. * NOTE : if when your CAD systems evaluates second order derivatives it also * computes first order derivatives and function evaluation, you can optimize * this example by making only one CAD call and filling the necessary xyz, du, dv, etc.. @@ -2411,20 +2568,6 @@ status_t surf_fun(real *uv, real *xyz, real*du, real *dv, status_t size_on_surface(integer face_id, real *uv, real *size, void *user_data) { - if (face_id == 1) { - if (my_u_min > uv[0]) { - my_u_min = uv[0]; - } - if (my_v_min > uv[1]) { - my_v_min = uv[1]; - } - if (my_u_max < uv[0]) { - my_u_max = uv[0]; - } - if (my_v_max < uv[1]) { - my_v_max = uv[1]; - } - } //MESSAGE("size_on_surface") if (FaceId2PythonSmp.count(face_id) != 0){ //MESSAGE("A size map is used to calculate size on face : "<Empty()) - double result = FaceIndex2ClassAttractor[face_id]->GetSize(uv[0],uv[1]); + real result = FaceIndex2ClassAttractor[face_id]->GetSize(uv[0],uv[1]); *size = result; - // MESSAGE("f(" << uv[0] << "," << uv[1] << ")" << " = " << result); } else { // MESSAGE("List of attractor is empty !!!") - *size = *((double*)user_data); + *size = *((real*)user_data); } +// std::cout << "Size_on_surface sur la face " << face_id << " donne une size de: " << *size << std::endl; return STATUS_OK; } @@ -2478,8 +2621,13 @@ status_t size_on_edge(integer edge_id, real t, real *size, void *user_data) PyGILState_STATE gstate; gstate = PyGILState_Ensure(); pyresult = PyObject_CallFunction(EdgeId2PythonSmp[edge_id],(char*)"(f)",t); - double result; - if ( pyresult == NULL){ + real result; + if ( pyresult != NULL) { + result = PyFloat_AsDouble(pyresult); + Py_DECREF(pyresult); +// *size = result; + } + else{ fflush(stderr); string err_description=""; new_stderr = newPyStdOut(err_description); @@ -2488,17 +2636,13 @@ status_t size_on_edge(integer edge_id, real t, real *size, void *user_data) PySys_SetObject((char*)"stderr", PySys_GetObject((char*)"__stderr__")); Py_DECREF(new_stderr); MESSAGE("Can't evaluate f(" << t << ")" << " error is " << err_description); - result = *((double*)user_data); - } - else { - result = PyFloat_AsDouble(pyresult); - Py_DECREF(pyresult); + result = *((real*)user_data); } *size = result; PyGILState_Release(gstate); } else { - *size = *((double*)user_data); + *size = *((real*)user_data); } return STATUS_OK; } @@ -2512,8 +2656,13 @@ status_t size_on_vertex(integer point_id, real *size, void *user_data) PyGILState_STATE gstate; gstate = PyGILState_Ensure(); pyresult = PyObject_CallFunction(VertexId2PythonSmp[point_id],(char*)""); - double result; - if ( pyresult == NULL){ + real result; + if ( pyresult != NULL) { + result = PyFloat_AsDouble(pyresult); + Py_DECREF(pyresult); +// *size = result; + } + else { fflush(stderr); string err_description=""; new_stderr = newPyStdOut(err_description); @@ -2522,17 +2671,13 @@ status_t size_on_vertex(integer point_id, real *size, void *user_data) PySys_SetObject((char*)"stderr", PySys_GetObject((char*)"__stderr__")); Py_DECREF(new_stderr); MESSAGE("Can't evaluate f()" << " error is " << err_description); - result = *((double*)user_data); - } - else { - result = PyFloat_AsDouble(pyresult); - Py_DECREF(pyresult); + result = *((real*)user_data); } *size = result; PyGILState_Release(gstate); } else { - *size = *((double*)user_data); + *size = *((real*)user_data); } return STATUS_OK; } @@ -2566,7 +2711,7 @@ status_t message_cb(message_t *msg, void *user_data) } /* This is the interrupt callback. PreCAD/BLSurf will call this - * function regularily. See the file distene/interrupt.h + * function regularily. See the file meshgems/interrupt.h */ status_t interrupt_cb(integer *interrupt_status, void *user_data) { @@ -2597,22 +2742,31 @@ bool BLSURFPlugin_BLSURF::Evaluate(SMESH_Mesh& aMesh, const TopoDS_Shape& aShape, MapShapeNbElems& aResMap) { + double diagonal = aMesh.GetShapeDiagonalSize(); + double bbSegmentation = _gen->GetBoundaryBoxSegmentation(); int _physicalMesh = BLSURFPlugin_Hypothesis::GetDefaultPhysicalMesh(); - double _phySize = BLSURFPlugin_Hypothesis::GetDefaultPhySize(); + double _phySize = BLSURFPlugin_Hypothesis::GetDefaultPhySize(diagonal, bbSegmentation); + bool _phySizeRel = BLSURFPlugin_Hypothesis::GetDefaultPhySizeRel(); //int _geometricMesh = BLSURFPlugin_Hypothesis::GetDefaultGeometricMesh(); - //double _angleMeshS = BLSURFPlugin_Hypothesis::GetDefaultAngleMeshS(); - double _angleMeshC = BLSURFPlugin_Hypothesis::GetDefaultAngleMeshC(); + double _angleMesh = BLSURFPlugin_Hypothesis::GetDefaultAngleMesh(); bool _quadAllowed = BLSURFPlugin_Hypothesis::GetDefaultQuadAllowed(); if(_hypothesis) { _physicalMesh = (int) _hypothesis->GetPhysicalMesh(); - _phySize = _hypothesis->GetPhySize(); + _phySizeRel = _hypothesis->IsPhySizeRel(); + if ( _hypothesis->GetPhySize() > 0) + _phySize = _phySizeRel ? diagonal*_hypothesis->GetPhySize() : _hypothesis->GetPhySize(); //_geometricMesh = (int) hyp->GetGeometricMesh(); - //_angleMeshS = hyp->GetAngleMeshS(); - _angleMeshC = _hypothesis->GetAngleMeshC(); - _quadAllowed = _hypothesis->GetQuadAllowed(); + if (_hypothesis->GetAngleMesh() > 0) + _angleMesh = _hypothesis->GetAngleMesh(); + _quadAllowed = _hypothesis->GetQuadAllowed(); + } else { + //0020968: EDF1545 SMESH: Problem in the creation of a mesh group on geometry + // GetDefaultPhySize() sometimes leads to computation failure + _phySize = aMesh.GetShapeDiagonalSize() / _gen->GetBoundaryBoxSegmentation(); + MESSAGE("BLSURFPlugin_BLSURF::SetParameters using defaults"); } - bool IsQuadratic = false; + bool IsQuadratic = _quadraticMesh; // ---------------- // evaluate 1D @@ -2648,7 +2802,7 @@ bool BLSURFPlugin_BLSURF::Evaluate(SMESH_Mesh& aMesh, V1 = V2; P2 = P3; } - nb1d = (int)( fullAng/_angleMeshC + 1 ); + nb1d = (int)( fullAng/_angleMesh + 1 ); } fullNbSeg += nb1d; std::vector aVec(SMDSEntity_Last); @@ -2738,56 +2892,3 @@ bool BLSURFPlugin_BLSURF::Evaluate(SMESH_Mesh& aMesh, return true; } - -//============================================================================= -/*! - * Rewritting of the BRepClass_FaceClassifier::Perform function which is bugged (CAS 6.3sp6) - * Following line was added: - * myExtrem.Perform(P); - */ -//============================================================================= -void BLSURFPlugin_BLSURF::BRepClass_FaceClassifierPerform(BRepClass_FaceClassifier* fc, - const TopoDS_Face& face, - const gp_Pnt& P, - const Standard_Real Tol) -{ - //-- Voir BRepExtrema_ExtPF.cxx - BRepAdaptor_Surface Surf(face); - Standard_Real U1, U2, V1, V2; - BRepTools::UVBounds(face, U1, U2, V1, V2); - Extrema_ExtPS myExtrem; - myExtrem.Initialize(Surf, U1, U2, V1, V2, Tol, Tol); - myExtrem.Perform(P); - //---------------------------------------------------------- - //-- On cherche le point le plus proche , PUIS - //-- On le classifie. - Standard_Integer nbv = 0; // xpu - Standard_Real MaxDist = RealLast(); - Standard_Integer indice = 0; - if (myExtrem.IsDone()) { - nbv = myExtrem.NbExt(); - for (Standard_Integer i = 1; i <= nbv; i++) { -#if OCC_VERSION_LARGE > 0x06040000 // Porting to OCCT6.5.1 - Standard_Real d = myExtrem.SquareDistance(i); -#else - Standard_Real d = myExtrem.Value(i); - d = Abs(d); -#endif - if (d <= MaxDist) { - MaxDist = d; - indice = i; - } - } - } - if (indice) { - gp_Pnt2d Puv; - Standard_Real U1,U2; - myExtrem.Point(indice).Parameter(U1, U2); - Puv.SetCoord(U1, U2); - fc->Perform(face, Puv, Tol); - } - else { - fc->Perform(face, gp_Pnt2d(U1-1.0,V1 - 1.0), Tol); //-- NYI etc BUG PAS BEAU En attendant l acces a rejected - //-- le resultat est TopAbs_OUT; - } -} diff --git a/src/BLSURFPlugin/BLSURFPlugin_BLSURF.hxx b/src/BLSURFPlugin/BLSURFPlugin_BLSURF.hxx index 5ad471b..8ac0a45 100644 --- a/src/BLSURFPlugin/BLSURFPlugin_BLSURF.hxx +++ b/src/BLSURFPlugin/BLSURFPlugin_BLSURF.hxx @@ -59,9 +59,9 @@ #include "Utils_SALOME_Exception.hxx" extern "C"{ -#include "distene/blsurf.h" -#include "distene/api.h" -#include "distene/precad.h" +#include +#include +#include } #include diff --git a/src/BLSURFPlugin/BLSURFPlugin_Hypothesis.cxx b/src/BLSURFPlugin/BLSURFPlugin_Hypothesis.cxx index f934918..ada8a38 100644 --- a/src/BLSURFPlugin/BLSURFPlugin_Hypothesis.cxx +++ b/src/BLSURFPlugin/BLSURFPlugin_Hypothesis.cxx @@ -41,24 +41,32 @@ //============================================================================= BLSURFPlugin_Hypothesis::BLSURFPlugin_Hypothesis(int hypId, int studyId, SMESH_Gen * gen) : - SMESH_Hypothesis(hypId, studyId, gen), _topology(GetDefaultTopology()), + SMESH_Hypothesis(hypId, studyId, gen), _physicalMesh(GetDefaultPhysicalMesh()), - _phySize(GetDefaultPhySize()), - _phyMax(GetDefaultMaxSize()), - _phyMin(GetDefaultMinSize()), - _hgeoMax(GetDefaultMaxSize()), - _hgeoMin(GetDefaultMinSize()), _geometricMesh(GetDefaultGeometricMesh()), - _angleMeshS(GetDefaultAngleMeshS()), - _angleMeshC(GetDefaultAngleMeshC()), + _phySize(GetDefaultPhySize()), + _phySizeRel(GetDefaultPhySizeRel()), + _minSize(GetDefaultMinSize()), + _minSizeRel(GetDefaultMinSizeRel()), + _maxSize(GetDefaultMaxSize()), + _maxSizeRel(GetDefaultMaxSizeRel()), _gradation(GetDefaultGradation()), _quadAllowed(GetDefaultQuadAllowed()), - _decimesh(GetDefaultDecimesh()), + _angleMesh(GetDefaultAngleMesh()), + _chordalError(GetDefaultChordalError()), + _anisotropic(GetDefaultAnisotropic()), + _anisotropicRatio(GetDefaultAnisotropicRatio()), + _removeTinyEdges(GetDefaultRemoveTinyEdges()), + _tinyEdgeLength(GetDefaultTinyEdgeLength()), + _badElementRemoval(GetDefaultBadElementRemoval()), + _badElementAspectRatio(GetDefaultBadElementAspectRatio()), + _optimizeMesh(GetDefaultOptimizeMesh()), + _quadraticMesh(GetDefaultQuadraticMesh()), _verb(GetDefaultVerbosity()), + _topology(GetDefaultTopology()), _preCADMergeEdges(GetDefaultPreCADMergeEdges()), - _preCADRemoveNanoEdges(GetDefaultPreCADRemoveNanoEdges()), + _preCADProcess3DTopology(GetDefaultPreCADProcess3DTopology()), _preCADDiscardInput(GetDefaultPreCADDiscardInput()), - _preCADEpsNano(GetDefaultPreCADEpsNano()), _sizeMap(GetDefaultSizeMap()), _attractors(GetDefaultSizeMap()), _classAttractors(GetDefaultAttractorMap()), @@ -76,33 +84,64 @@ BLSURFPlugin_Hypothesis::BLSURFPlugin_Hypothesis(int hypId, int studyId, SMESH_G _param_algo_dim = 2; // _GMFFileMode = false; // GMF ascii mode - - // to disable writing boundaries - //_phyMin = _phyMax = _hgeoMin = _hgeoMax = undefinedDouble(); + const char* boolOptionNames[] = { "correct_surface_intersections", // default = 1 + "create_tag_on_collision", // default = 1 + "debug", // default = 0 + "enforce_cad_edge_sizes", // default = 0 + "frontal", // ok default = 1 + "jacobian_rectification_respect_geometry", // default = 1 + "proximity", // default = 0 + "rectify_jacobian", // default = 1 + "respect_geometry", // default = 1 + "" // mark of end + }; - const char* intOptionNames[] = { "addsurf_ivertex", "anisotropic", "background", "CheckAdjacentEdges", "CheckCloseEdges", - "CheckWellDefined", "coiter", "communication", "debug", "decim", "export_flag", "file_h", "frontal", "gridnu", "gridnv", - "hinterpol_flag", "hmean_flag", "intermedfile", "memory", "normals", "optim", "pardom_flag", "pinch", "refs", - "rigid", "surforient", "tconf", "topo_collapse", - "proximity", "prox_nb_layer", "prox_ratio", // detects the volumic proximity of surfaces - "" // mark of end + const char* intOptionNames[] = { "hinterpol_flag", // ok default = 0 + "hmean_flag", // ok default = 0 + "max_number_of_points_per_patch", // default = 100000 + "prox_nb_layer", // detects the volumic proximity of surfaces + "" // mark of end }; - const char* doubleOptionNames[] = { "addsurf_angle", "addsurf_R", "addsurf_H", "addsurf_FG", "addsurf_r", - "addsurf_PA", "angle_compcurv", "angle_ridge", "anisotropic_ratio", "CoefRectangle", "eps_collapse", "eps_ends", "eps_pardom", "LSS", - "topo_eps1", "topo_eps2", "" // mark of end + const char* doubleOptionNames[] = { "surface_intersections_processing_max_cost",// default = 15 + "periodic_tolerance", // default = diag/100 + "prox_ratio", + "" // mark of end }; - const char* charOptionNames[] = { "export_format", "export_option", "import_option", "prefix", "" // mark of end + const char* charOptionNames[] = { "required_entities", // default = "respect" + "tags", // default = "respect" + "" // mark of end }; // PreCAD advanced options - const char* preCADintOptionNames[] = { "closed_geometry", "debug", "manifold_geometry", "create_tag_on_collision","" // mark of end + const char* preCADboolOptionNames[] = { "closed_geometry", // default = 0 + "create_tag_on_collision", // default = 1 + "debug", // default = 0 + "remove_tiny_edges", // default = 0 + "" // mark of end }; - const char* preCADdoubleOptionNames[] = { "eps_nano_relative", "eps_sewing", "eps_sewing_relative", "periodic_tolerance", - "periodic_tolerance_relative", "periodic_split_tolerance", "periodic_split_tolerance_relative", "" // mark of end + const char* preCADintOptionNames[] = { "manifold_geometry", // default = 0 + "" // mark of end + }; + const char* preCADdoubleOptionNames[] = { "periodic_tolerance", // default = diag * 1e-5 + "sewing_tolerance", // default = diag * 5e-4 + "tiny_edge_length", // default = diag * 1e-5 + "" // mark of end + }; + const char* preCADcharOptionNames[] = { "required_entities", // default = "respect" + "tags", // default = "respect" + "" // mark of end }; int i = 0; + while (boolOptionNames[i][0]) + _option2value[boolOptionNames[i++]].clear(); + + i = 0; + while (preCADboolOptionNames[i][0]) + _preCADoption2value[preCADboolOptionNames[i++]].clear(); + + i = 0; while (intOptionNames[i][0]) _option2value[intOptionNames[i++]].clear(); @@ -125,6 +164,11 @@ BLSURFPlugin_Hypothesis::BLSURFPlugin_Hypothesis(int hypId, int studyId, SMESH_G _charOptions.insert(charOptionNames[i]); _option2value[charOptionNames[i++]].clear(); } + i = 0; + while (preCADcharOptionNames[i][0]) { + _preCADdoubleOptions.insert(preCADcharOptionNames[i]); + _preCADoption2value[preCADdoubleOptionNames[i++]].clear(); + } @@ -167,26 +211,34 @@ TopoDS_Shape BLSURFPlugin_Hypothesis::entryToShape(std::string entry) } //============================================================================= -void BLSURFPlugin_Hypothesis::SetTopology(Topology theTopology) { - if (theTopology != _topology) { - _topology = theTopology; +void BLSURFPlugin_Hypothesis::SetPhysicalMesh(PhysicalMesh thePhysicalMesh) { + if (thePhysicalMesh != _physicalMesh) { + _physicalMesh = thePhysicalMesh; NotifySubMeshesHypothesisModification(); } } //============================================================================= -void BLSURFPlugin_Hypothesis::SetPhysicalMesh(PhysicalMesh thePhysicalMesh) { - if (thePhysicalMesh != _physicalMesh) { - _physicalMesh = thePhysicalMesh; +void BLSURFPlugin_Hypothesis::SetGeometricMesh(GeometricMesh theGeometricMesh) { + if (theGeometricMesh != _geometricMesh) { + _geometricMesh = theGeometricMesh; +// switch (_geometricMesh) { +// case DefaultGeom: +// default: +// _angleMesh = GetDefaultAngleMesh(); +// _gradation = GetDefaultGradation(); +// break; +// } NotifySubMeshesHypothesisModification(); } } //============================================================================= -void BLSURFPlugin_Hypothesis::SetPhySize(double theVal) { - if (theVal != _phySize) { +void BLSURFPlugin_Hypothesis::SetPhySize(double theVal, bool isRelative) { + if ((theVal != _phySize) || (isRelative != _phySizeRel)) { + _phySizeRel = isRelative; if (theVal == 0) { - _phySize = GetPhyMax(); + _phySize = GetMaxSize(); MESSAGE("Warning: nul physical size is not allowed"); } else @@ -196,88 +248,123 @@ void BLSURFPlugin_Hypothesis::SetPhySize(double theVal) { } //============================================================================= -void BLSURFPlugin_Hypothesis::SetPhyMin(double theMinSize) { - if (theMinSize != _phyMin) { - _phyMin = theMinSize; +void BLSURFPlugin_Hypothesis::SetMinSize(double theMinSize, bool isRelative) { + if ((theMinSize != _minSize) || (isRelative != _minSizeRel)) { + _minSizeRel = isRelative; + _minSize = theMinSize; NotifySubMeshesHypothesisModification(); } } //============================================================================= -void BLSURFPlugin_Hypothesis::SetPhyMax(double theMaxSize) { - if (theMaxSize != _phyMax) { - _phyMax = theMaxSize; +void BLSURFPlugin_Hypothesis::SetMaxSize(double theMaxSize, bool isRelative) { + if ((theMaxSize != _maxSize) || (isRelative != _maxSizeRel)) { + _maxSizeRel = isRelative; + _maxSize = theMaxSize; NotifySubMeshesHypothesisModification(); } } //============================================================================= -void BLSURFPlugin_Hypothesis::SetGeoMin(double theMinSize) { - if (theMinSize != _hgeoMin) { - _hgeoMin = theMinSize; +void BLSURFPlugin_Hypothesis::SetGradation(double theVal) { + if (theVal != _gradation) { + _gradation = theVal; NotifySubMeshesHypothesisModification(); } } //============================================================================= -void BLSURFPlugin_Hypothesis::SetGeoMax(double theMaxSize) { - if (theMaxSize != _hgeoMax) { - _hgeoMax = theMaxSize; +void BLSURFPlugin_Hypothesis::SetQuadAllowed(bool theVal) { + if (theVal != _quadAllowed) { + _quadAllowed = theVal; NotifySubMeshesHypothesisModification(); } } //============================================================================= -void BLSURFPlugin_Hypothesis::SetGeometricMesh(GeometricMesh theGeometricMesh) { - if (theGeometricMesh != _geometricMesh) { - _geometricMesh = theGeometricMesh; - switch (_geometricMesh) { - case DefaultGeom: - default: - _angleMeshS = GetDefaultAngleMeshS(); - _gradation = GetDefaultGradation(); - break; - } +void BLSURFPlugin_Hypothesis::SetAngleMesh(double theVal) { + if (theVal != _angleMesh) { + _angleMesh = theVal; NotifySubMeshesHypothesisModification(); } } //============================================================================= -void BLSURFPlugin_Hypothesis::SetAngleMeshS(double theVal) { - if (theVal != _angleMeshS) { - _angleMeshS = theVal; +void BLSURFPlugin_Hypothesis::SetChordalError(double theDistance) { + if (theDistance != _chordalError) { + _chordalError = theDistance; NotifySubMeshesHypothesisModification(); } } //============================================================================= -void BLSURFPlugin_Hypothesis::SetAngleMeshC(double theVal) { - if (theVal != _angleMeshC) { - _angleMeshC = theVal; +void BLSURFPlugin_Hypothesis::SetAnisotropic(bool theVal) { + if (theVal != _anisotropic) { + _anisotropic = theVal; NotifySubMeshesHypothesisModification(); } } //============================================================================= -void BLSURFPlugin_Hypothesis::SetGradation(double theVal) { - if (theVal != _gradation) { - _gradation = theVal; +void BLSURFPlugin_Hypothesis::SetAnisotropicRatio(double theVal) { + if (theVal != _anisotropicRatio) { + _anisotropicRatio = theVal; NotifySubMeshesHypothesisModification(); } } //============================================================================= -void BLSURFPlugin_Hypothesis::SetQuadAllowed(bool theVal) { - if (theVal != _quadAllowed) { - _quadAllowed = theVal; +void BLSURFPlugin_Hypothesis::SetRemoveTinyEdges(bool theVal) { + if (theVal != _removeTinyEdges) { + _removeTinyEdges = theVal; + NotifySubMeshesHypothesisModification(); + } +} + +//============================================================================= +void BLSURFPlugin_Hypothesis::SetTinyEdgeLength(double theVal) { + if (theVal != _tinyEdgeLength) { + _tinyEdgeLength = theVal; NotifySubMeshesHypothesisModification(); } } //============================================================================= -void BLSURFPlugin_Hypothesis::SetDecimesh(bool theVal) { - if (theVal != _decimesh) { - _decimesh = theVal; +void BLSURFPlugin_Hypothesis::SetBadElementRemoval(bool theVal) { + if (theVal != _badElementRemoval) { + _badElementRemoval = theVal; + NotifySubMeshesHypothesisModification(); + } +} + +//============================================================================= +void BLSURFPlugin_Hypothesis::SetBadElementAspectRatio(double theVal) { + if (theVal != _badElementAspectRatio) { + _badElementAspectRatio = theVal; + NotifySubMeshesHypothesisModification(); + } +} + +//============================================================================= +void BLSURFPlugin_Hypothesis::SetOptimizeMesh(bool theVal) { + if (theVal != _optimizeMesh) { + _optimizeMesh = theVal; + NotifySubMeshesHypothesisModification(); + } +} + +//============================================================================= +void BLSURFPlugin_Hypothesis::SetQuadraticMesh(bool theVal) { + if (theVal != _quadraticMesh) { + _quadraticMesh = theVal; + NotifySubMeshesHypothesisModification(); + } +} + +//============================================================================= +void BLSURFPlugin_Hypothesis::SetTopology(Topology theTopology) { + if (theTopology != _topology) { + _topology = theTopology; NotifySubMeshesHypothesisModification(); } } @@ -293,17 +380,17 @@ void BLSURFPlugin_Hypothesis::SetVerbosity(int theVal) { //============================================================================= void BLSURFPlugin_Hypothesis::SetPreCADMergeEdges(bool theVal) { if (theVal != _preCADMergeEdges) { - SetTopology(PreCAD); +// SetTopology(PreCAD); _preCADMergeEdges = theVal; NotifySubMeshesHypothesisModification(); } } //============================================================================= -void BLSURFPlugin_Hypothesis::SetPreCADRemoveNanoEdges(bool theVal) { - if (theVal != _preCADRemoveNanoEdges) { - SetTopology(PreCAD); - _preCADRemoveNanoEdges = theVal; +void BLSURFPlugin_Hypothesis::SetPreCADProcess3DTopology(bool theVal) { + if (theVal != _preCADProcess3DTopology) { +// SetTopology(PreCAD); + _preCADProcess3DTopology = theVal; NotifySubMeshesHypothesisModification(); } } @@ -311,21 +398,12 @@ void BLSURFPlugin_Hypothesis::SetPreCADRemoveNanoEdges(bool theVal) { //============================================================================= void BLSURFPlugin_Hypothesis::SetPreCADDiscardInput(bool theVal) { if (theVal != _preCADDiscardInput) { - SetTopology(PreCAD); +// SetTopology(PreCAD); _preCADDiscardInput = theVal; NotifySubMeshesHypothesisModification(); } } -//============================================================================= -void BLSURFPlugin_Hypothesis::SetPreCADEpsNano(double theVal) { - if (theVal != _preCADEpsNano) { - SetTopology(PreCAD); - _preCADEpsNano = theVal; - NotifySubMeshesHypothesisModification(); - } -} - //============================================================================= // void BLSURFPlugin_Hypothesis::SetGMFFile(const std::string& theFileName, bool isBinary) void BLSURFPlugin_Hypothesis::SetGMFFile(const std::string& theFileName) @@ -464,7 +542,7 @@ void BLSURFPlugin_Hypothesis::ClearPreCADOption(const std::string& optionName) { //======================================================================= void BLSURFPlugin_Hypothesis::SetSizeMapEntry(const std::string& entry, const std::string& sizeMap) { if (_sizeMap[entry].compare(sizeMap) != 0) { - SetPhysicalMesh(SizeMap); + SetPhysicalMesh(PhysicalLocalSize); _sizeMap[entry] = sizeMap; NotifySubMeshesHypothesisModification(); } @@ -493,7 +571,7 @@ BLSURFPlugin_Hypothesis::TSizeMap BLSURFPlugin_Hypothesis::GetSizeMapEntries(con //======================================================================= void BLSURFPlugin_Hypothesis::SetAttractorEntry(const std::string& entry, const std::string& attractor) { if (_attractors[entry].compare(attractor) != 0) { - SetPhysicalMesh(SizeMap); + SetPhysicalMesh(PhysicalLocalSize); _attractors[entry] = attractor; NotifySubMeshesHypothesisModification(); } @@ -522,7 +600,7 @@ BLSURFPlugin_Hypothesis::TSizeMap BLSURFPlugin_Hypothesis::GetAttractorEntries(c //======================================================================= void BLSURFPlugin_Hypothesis::SetClassAttractorEntry(const std::string& entry, const std::string& attEntry, double StartSize, double EndSize, double ActionRadius, double ConstantRadius) { - SetPhysicalMesh(SizeMap); + SetPhysicalMesh(PhysicalLocalSize); // The new attractor can't be defined on the same face as another sizemap TSizeMap::iterator it = _sizeMap.find( entry ); @@ -676,7 +754,7 @@ bool BLSURFPlugin_Hypothesis::SetEnforcedVertex(TEntry theFaceEntry, TEnfName th MESSAGE("BLSURFPlugin_Hypothesis::SetEnforcedVertex("<< theFaceEntry << ", " << x << ", " << y << ", " << z << ", " << theVertexName << ", " << theVertexEntry << ", " << theGroupName << ")"); - SetPhysicalMesh(SizeMap); + SetPhysicalMesh(PhysicalLocalSize); // TEnfVertexList::iterator it; bool toNotify = false; @@ -1114,7 +1192,7 @@ void BLSURFPlugin_Hypothesis::SetInternalEnforcedVertexAllFaces(bool toEnforceIn if (toEnforceInternalVertices != _enforcedInternalVerticesAllFaces) { _enforcedInternalVerticesAllFaces = toEnforceInternalVertices; if (toEnforceInternalVertices) - SetPhysicalMesh(SizeMap); + SetPhysicalMesh(PhysicalLocalSize); NotifySubMeshesHypothesisModification(); } } @@ -1130,13 +1208,45 @@ void BLSURFPlugin_Hypothesis::SetInternalEnforcedVertexAllFacesGroup(BLSURFPlugi //============================================================================= std::ostream & BLSURFPlugin_Hypothesis::SaveTo(std::ostream & save) { + // We must keep at least the same number of arguments when increasing the SALOME version + // When BLSURF becomes CADMESH, some parameters were fused into a single one. Thus the same + // parameter can be written several times to keep the old global number of parameters. + + // Treat old options which are now in the advanced options + TOptionValues::iterator op_val; + int _decimesh = -1; + int _preCADRemoveNanoEdges = -1; + double _preCADEpsNano = -1.0; + op_val = _option2value.find("respect_geometry"); + if (op_val != _option2value.end()) { + std::string value = op_val->second; + if (!value.empty()) + _decimesh = value.compare("1") == 0 ? 1 : 0; + } + op_val = _preCADoption2value.find("remove_tiny_edges"); + if (op_val != _preCADoption2value.end()) { + std::string value = op_val->second; + if (!value.empty()) + _preCADRemoveNanoEdges = value.compare("1") == 0 ? 1 : 0; + } + op_val = _preCADoption2value.find("tiny_edge_length"); + if (op_val != _preCADoption2value.end()) { + std::string value = op_val->second; + if (!value.empty()) + _preCADEpsNano = strtod(value.c_str(), NULL); + } + save << " " << (int) _topology << " " << (int) _physicalMesh << " " << (int) _geometricMesh << " " << _phySize << " " - << _angleMeshS << " " << _gradation << " " << (int) _quadAllowed << " " << (int) _decimesh; - save << " " << _phyMin << " " << _phyMax << " " << _angleMeshC << " " << _hgeoMin << " " << _hgeoMax << " " << _verb; - save << " " << (int) _preCADMergeEdges << " " << (int) _preCADRemoveNanoEdges << " " << (int) _preCADDiscardInput << " " << _preCADEpsNano ; + << _angleMesh << " " << _gradation << " " << (int) _quadAllowed << " " << _decimesh; + save << " " << _minSize << " " << _maxSize << " " << _angleMesh << " " << _minSize << " " << _maxSize << " " << _verb; + save << " " << (int) _preCADMergeEdges << " " << _preCADRemoveNanoEdges << " " << (int) _preCADDiscardInput << " " << _preCADEpsNano ; save << " " << (int) _enforcedInternalVerticesAllFaces; + save << " " << (int) _phySizeRel << " " << (int) _minSizeRel << " " << (int) _maxSizeRel << " " << _chordalError ; + save << " " << (int) _anisotropic << " " << _anisotropicRatio << " " << (int) _removeTinyEdges << " " << _tinyEdgeLength ; + save << " " << (int) _badElementRemoval << " " << _badElementAspectRatio << " " << (int) _optimizeMesh << " " << (int) _quadraticMesh ; + save << " " << (int) _preCADProcess3DTopology; - TOptionValues::iterator op_val = _option2value.begin(); + op_val = _option2value.begin(); if (op_val != _option2value.end()) { save << " " << "__OPTIONS_BEGIN__"; for (; op_val != _option2value.end(); ++op_val) { @@ -1247,6 +1357,7 @@ std::istream & BLSURFPlugin_Hypothesis::LoadFrom(std::istream & load) { bool isOK = true; int i; double val; + std::string option_or_sm; isOK = (load >> i); if (isOK) @@ -1274,7 +1385,7 @@ std::istream & BLSURFPlugin_Hypothesis::LoadFrom(std::istream & load) { isOK = (load >> val); if (isOK) - _angleMeshS = val; + _angleMesh = val; else load.clear(std::ios::badbit | load.rdstate()); @@ -1291,38 +1402,46 @@ std::istream & BLSURFPlugin_Hypothesis::LoadFrom(std::istream & load) { load.clear(std::ios::badbit | load.rdstate()); isOK = (load >> i); - if (isOK) - _decimesh = (bool) i; + if (isOK) { + if ( i != -1) { // if value is -1, then this is no longer a standard option + std::string & value = _option2value["respect_geometry"]; + bool _decimesh = (bool) i; + value = _decimesh ? "1" : "0"; + } + } else load.clear(std::ios::badbit | load.rdstate()); isOK = (load >> val); if (isOK) - _phyMin = val; + _minSize = val; else load.clear(std::ios::badbit | load.rdstate()); isOK = (load >> val); if (isOK) - _phyMax = val; + _maxSize = val; else load.clear(std::ios::badbit | load.rdstate()); isOK = (load >> val); if (isOK) - _angleMeshC = val; + // former parameter: get min value + _angleMesh = min(val,_angleMesh); else load.clear(std::ios::badbit | load.rdstate()); isOK = (load >> val); if (isOK) - _hgeoMin = val; + // former parameter: get min value + _minSize = min(val,_minSize); else load.clear(std::ios::badbit | load.rdstate()); isOK = (load >> val); if (isOK) - _hgeoMax = val; + // former parameter: get max value + _maxSize = max(val,_maxSize); else load.clear(std::ios::badbit | load.rdstate()); @@ -1339,8 +1458,13 @@ std::istream & BLSURFPlugin_Hypothesis::LoadFrom(std::istream & load) { load.clear(std::ios::badbit | load.rdstate()); isOK = (load >> i); - if (isOK) - _preCADRemoveNanoEdges = (bool) i; + if (isOK) { + if ( i != -1) { // if value is -1, then this is no longer a standard option + std::string & value = _preCADoption2value["remove_tiny_edges"]; + bool _preCADRemoveNanoEdges = (bool) i; + value = _preCADRemoveNanoEdges ? "1" : "0"; + } + } else load.clear(std::ios::badbit | load.rdstate()); @@ -1351,8 +1475,14 @@ std::istream & BLSURFPlugin_Hypothesis::LoadFrom(std::istream & load) { load.clear(std::ios::badbit | load.rdstate()); isOK = (load >> val); - if (isOK) - _preCADEpsNano = val; + if (isOK) { // _preCADEpsNano + if ( (i + 1.0) < 1e-6 ) { // if value is -1, then this is no longer a standard option: get optional value "tiny_edge_length" instead + std::string & value = _preCADoption2value["tiny_edge_length"]; + std::ostringstream oss; + oss << i; + value = oss.str(); + } + } else load.clear(std::ios::badbit | load.rdstate()); @@ -1362,7 +1492,9 @@ std::istream & BLSURFPlugin_Hypothesis::LoadFrom(std::istream & load) { else load.clear(std::ios::badbit | load.rdstate()); - std::string option_or_sm; + // New options with MeshGems-CADSurf + + bool hasCADSurfOptions = false; bool hasOptions = false; bool hasPreCADOptions = false; bool hasSizeMap = false; @@ -1372,6 +1504,11 @@ std::istream & BLSURFPlugin_Hypothesis::LoadFrom(std::istream & load) { isOK = (load >> option_or_sm); if (isOK) + if ( (option_or_sm == "1")||(option_or_sm == "0") ) { + i = atoi(option_or_sm.c_str()); + hasCADSurfOptions = true; + _phySizeRel = (bool) i; + } if (option_or_sm == "__OPTIONS_BEGIN__") hasOptions = true; else if (option_or_sm == "__PRECAD_OPTIONS_BEGIN__") @@ -1385,6 +1522,99 @@ std::istream & BLSURFPlugin_Hypothesis::LoadFrom(std::istream & load) { else if (option_or_sm == "__ENFORCED_VERTICES_BEGIN__") hasEnforcedVertex = true; + if (isOK && hasCADSurfOptions) { + isOK = (load >> i); + if (isOK) + _minSizeRel = (bool) i; + else + load.clear(std::ios::badbit | load.rdstate()); + + isOK = (load >> i); + if (isOK) + _maxSizeRel = (bool) i; + else + load.clear(std::ios::badbit | load.rdstate()); + + isOK = (load >> val); + if (isOK) + _chordalError = val; + else + load.clear(std::ios::badbit | load.rdstate()); + + isOK = (load >> i); + if (isOK) + _anisotropic = (bool) i; + else + load.clear(std::ios::badbit | load.rdstate()); + + isOK = (load >> val); + if (isOK) + _anisotropicRatio = val; + else + load.clear(std::ios::badbit | load.rdstate()); + + isOK = (load >> i); + if (isOK) + _removeTinyEdges = (bool) i; + else + load.clear(std::ios::badbit | load.rdstate()); + + isOK = (load >> val); + if (isOK) + _tinyEdgeLength = val; + else + load.clear(std::ios::badbit | load.rdstate()); + + isOK = (load >> i); + if (isOK) + _badElementRemoval = (bool) i; + else + load.clear(std::ios::badbit | load.rdstate()); + + isOK = (load >> val); + if (isOK) + _badElementAspectRatio = val; + else + load.clear(std::ios::badbit | load.rdstate()); + + isOK = (load >> i); + if (isOK) + _optimizeMesh = (bool) i; + else + load.clear(std::ios::badbit | load.rdstate()); + + isOK = (load >> i); + if (isOK) + _quadraticMesh = (bool) i; + else + load.clear(std::ios::badbit | load.rdstate()); + + isOK = (load >> i); + if (isOK) + _preCADProcess3DTopology = (bool) i; + else + load.clear(std::ios::badbit | load.rdstate()); + + } + + + if (hasCADSurfOptions) { + isOK = (load >> option_or_sm); + if (isOK) + if (option_or_sm == "__OPTIONS_BEGIN__") + hasOptions = true; + else if (option_or_sm == "__PRECAD_OPTIONS_BEGIN__") + hasPreCADOptions = true; + else if (option_or_sm == "__SIZEMAP_BEGIN__") + hasSizeMap = true; + else if (option_or_sm == "__ATTRACTORS_BEGIN__") + hasAttractor = true; + else if (option_or_sm == "__NEW_ATTRACTORS_BEGIN__") + hasNewAttractor = true; + else if (option_or_sm == "__ENFORCED_VERTICES_BEGIN__") + hasEnforcedVertex = true; + } + std::string optName, optValue; while (isOK && hasOptions) { isOK = (load >> optName); @@ -1731,79 +1961,81 @@ bool BLSURFPlugin_Hypothesis::SetParametersByMesh(const SMESH_Mesh* theMesh, con return false; } -//============================================================================= +//================================================================================ /*! - * \brief Initialize my parameter values by default parameters. - * \retval bool - true if parameter values have been successfully defined + * \brief Returns default global constant physical size given a default value of element length ratio */ -//============================================================================= +//================================================================================ -bool BLSURFPlugin_Hypothesis::SetParametersByDefaults(const TDefaults& dflts, const SMESH_Mesh* theMesh) { - return bool(_phySize = dflts._elemLength); +double BLSURFPlugin_Hypothesis::GetDefaultPhySize(double diagonal, double bbSegmentation) { + if (bbSegmentation != 0 && diagonal != 0) + return diagonal / bbSegmentation ; + return 10; } -//============================================================================= -BLSURFPlugin_Hypothesis::Topology BLSURFPlugin_Hypothesis::GetDefaultTopology() { - return FromCAD; -} +//================================================================================ +/*! + * \brief Returns default min size given a default value of element length ratio + */ +//================================================================================ -//============================================================================= -BLSURFPlugin_Hypothesis::PhysicalMesh BLSURFPlugin_Hypothesis::GetDefaultPhysicalMesh() { - return PhysicalUserDefined; +double BLSURFPlugin_Hypothesis::GetDefaultMinSize(double diagonal) { + if (diagonal != 0) + return diagonal / 1000.0 ; + return undefinedDouble(); } -//============================================================================= -double BLSURFPlugin_Hypothesis::GetDefaultPhySize() { - return 10; -} +//================================================================================ +/*! + * \brief Returns default max size given a default value of element length ratio + */ +//================================================================================ -//====================================================================== -double BLSURFPlugin_Hypothesis::GetDefaultMaxSize() { - return undefinedDouble(); // 1e+4; +double BLSURFPlugin_Hypothesis::GetDefaultMaxSize(double diagonal) { + if (diagonal != 0) + return diagonal / 5.0 ; + return undefinedDouble(); } -//====================================================================== -double BLSURFPlugin_Hypothesis::GetDefaultMinSize() { - return undefinedDouble(); //1e-4; -} +//================================================================================ +/*! + * \brief Returns default chordal error given a default value of element length ratio + */ +//================================================================================ -//====================================================================== -BLSURFPlugin_Hypothesis::GeometricMesh BLSURFPlugin_Hypothesis::GetDefaultGeometricMesh() { - return DefaultGeom; +double BLSURFPlugin_Hypothesis::GetDefaultChordalError(double diagonal) { + if (diagonal != 0) + return diagonal; + return undefinedDouble(); } -//============================================================================= -double BLSURFPlugin_Hypothesis::GetDefaultAngleMeshS() { - return 8; -} +//================================================================================ +/*! + * \brief Returns default tiny edge length given a default value of element length ratio + */ +//================================================================================ -//============================================================================= -double BLSURFPlugin_Hypothesis::GetDefaultGradation() { - return 1.1; +double BLSURFPlugin_Hypothesis::GetDefaultTinyEdgeLength(double diagonal) { + if (diagonal != 0) + return diagonal * 1e-6 ; + return undefinedDouble(); } //============================================================================= -bool BLSURFPlugin_Hypothesis::GetDefaultQuadAllowed() { - return false; -} - +/*! + * \brief Initialize my parameter values by default parameters. + * \retval bool - true if parameter values have been successfully defined + */ //============================================================================= -bool BLSURFPlugin_Hypothesis::GetDefaultDecimesh() { - return false; -} - -//====================================================================== -double BLSURFPlugin_Hypothesis::GetDefaultPreCADEpsNano() { - return undefinedDouble(); //1e-4; -} -//====================================================================== -std::string BLSURFPlugin_Hypothesis::GetDefaultGMFFile() { - return ""; -} +bool BLSURFPlugin_Hypothesis::SetParametersByDefaults(const TDefaults& dflts, const SMESH_Mesh* theMesh) { + double diagonal = dflts._elemLength*_gen->GetBoundaryBoxSegmentation(); + _phySize = GetDefaultPhySize(diagonal, _gen->GetBoundaryBoxSegmentation()); + _minSize = GetDefaultMinSize(diagonal); + _maxSize = GetDefaultMaxSize(diagonal); + _chordalError = GetDefaultChordalError(diagonal); + _tinyEdgeLength = GetDefaultTinyEdgeLength(diagonal); -//============================================================================= -bool BLSURFPlugin_Hypothesis::GetDefaultInternalEnforcedVertex() { - return false; + return true; +// return bool(_phySize = dflts._elemLength); } - diff --git a/src/BLSURFPlugin/BLSURFPlugin_Hypothesis.hxx b/src/BLSURFPlugin/BLSURFPlugin_Hypothesis.hxx index 2b014b0..7475444 100644 --- a/src/BLSURFPlugin/BLSURFPlugin_Hypothesis.hxx +++ b/src/BLSURFPlugin/BLSURFPlugin_Hypothesis.hxx @@ -54,48 +54,37 @@ public: enum PhysicalMesh { DefaultSize, - PhysicalUserDefined, - SizeMap + PhysicalGlobalSize, + PhysicalLocalSize }; enum GeometricMesh { DefaultGeom, - UserDefined + GeometricalGlobalSize, + GeometricalLocalSize }; static const char* GetHypType() { return "BLSURF_Parameters"; } TopoDS_Shape entryToShape(std::string entry); - void SetTopology(Topology theTopology); - Topology GetTopology() const { return _topology; } - void SetPhysicalMesh(PhysicalMesh thePhysicalMesh); PhysicalMesh GetPhysicalMesh() const { return _physicalMesh; } - void SetPhySize(double thePhySize); - double GetPhySize() const { return _phySize; } - - void SetPhyMin(double theMinSize); - double GetPhyMin() const { return _phyMin; } - - void SetPhyMax(double theMaxSize); - double GetPhyMax() const { return _phyMax; } - void SetGeometricMesh(GeometricMesh theGeometricMesh); GeometricMesh GetGeometricMesh() const { return _geometricMesh; } - void SetAngleMeshS(double theAngle); - double GetAngleMeshS() const { return _angleMeshS; } - - void SetAngleMeshC(double theAngle); - double GetAngleMeshC() const { return _angleMeshC; } + void SetPhySize(double thePhySize, bool isRelative = false); + double GetPhySize() const { return _phySize; } + bool IsPhySizeRel() const { return _phySizeRel; } - void SetGeoMin(double theMinSize); - double GetGeoMin() const { return _hgeoMin; } + void SetMinSize(double theMinSize, bool isRelative = false); + double GetMinSize() const { return _minSize; } + bool IsMinSizeRel() const { return _minSizeRel; } - void SetGeoMax(double theMaxSize); - double GetGeoMax() const { return _hgeoMax; } + void SetMaxSize(double theMaxSize, bool isRelative = false); + double GetMaxSize() const { return _maxSize; } + bool IsMaxSizeRel() const { return _maxSizeRel; } void SetGradation(double theGradation); double GetGradation() const { return _gradation; } @@ -103,8 +92,38 @@ public: void SetQuadAllowed(bool theVal); bool GetQuadAllowed() const { return _quadAllowed; } - void SetDecimesh(bool theVal); - bool GetDecimesh() const { return _decimesh; } + void SetAngleMesh(double theAngle); + double GetAngleMesh() const { return _angleMesh; } + + void SetChordalError(double theDistance); + double GetChordalError() const { return _chordalError; } + + void SetAnisotropic(bool theVal); + bool GetAnisotropic() const { return _anisotropic; } + + void SetAnisotropicRatio(double theVal); + double GetAnisotropicRatio() const { return _anisotropicRatio; } + + void SetRemoveTinyEdges(bool theVal); + bool GetRemoveTinyEdges() const { return _removeTinyEdges; } + + void SetTinyEdgeLength(double theVal); + double GetTinyEdgeLength() const { return _tinyEdgeLength; } + + void SetBadElementRemoval(bool theVal); + bool GetBadElementRemoval() const { return _badElementRemoval; } + + void SetBadElementAspectRatio(double theVal); + double GetBadElementAspectRatio() const { return _badElementAspectRatio; } + + void SetOptimizeMesh(bool theVal); + bool GetOptimizeMesh() const { return _optimizeMesh; } + + void SetQuadraticMesh(bool theVal); + bool GetQuadraticMesh() const { return _quadraticMesh; } + + void SetTopology(Topology theTopology); + Topology GetTopology() const { return _topology; } void SetVerbosity(int theVal); int GetVerbosity() const { return _verb; } @@ -115,14 +134,11 @@ public: void SetPreCADMergeEdges(bool theVal); bool GetPreCADMergeEdges() const { return _preCADMergeEdges; } - void SetPreCADRemoveNanoEdges(bool theVal); - bool GetPreCADRemoveNanoEdges() const { return _preCADRemoveNanoEdges; } + void SetPreCADProcess3DTopology(bool theVal); + bool GetPreCADProcess3DTopology() const { return _preCADProcess3DTopology; } void SetPreCADDiscardInput(bool theVal); bool GetPreCADDiscardInput() const { return _preCADDiscardInput; } - - void SetPreCADEpsNano(double theVal); - double GetPreCADEpsNano() const { return _preCADEpsNano; } typedef std::map TSizeMap; @@ -286,23 +302,39 @@ public: // void SetInternalEnforcedVertex(TEntry theFaceEntry, bool toEnforceInternalVertices, TEnfGroupName theGroupName); // bool GetInternalEnforcedVertex(const TEntry& theFaceEntry); - static Topology GetDefaultTopology(); - static PhysicalMesh GetDefaultPhysicalMesh(); - static double GetDefaultPhySize(); - static double GetDefaultMaxSize(); - static double GetDefaultMinSize(); - static GeometricMesh GetDefaultGeometricMesh(); - static double GetDefaultAngleMeshS(); - static double GetDefaultAngleMeshC() { return GetDefaultAngleMeshS(); } - static double GetDefaultGradation(); - static bool GetDefaultQuadAllowed(); - static bool GetDefaultDecimesh(); - static int GetDefaultVerbosity() { return 10; } + static PhysicalMesh GetDefaultPhysicalMesh() { return PhysicalGlobalSize; } + static GeometricMesh GetDefaultGeometricMesh() { return DefaultGeom; } + static double GetDefaultPhySize(double diagonal, double bbSegmentation); + static double GetDefaultPhySize() { return undefinedDouble(); } + static bool GetDefaultPhySizeRel() { return false; } + static double GetDefaultMinSize(double diagonal); + static double GetDefaultMinSize() { return undefinedDouble(); } + static bool GetDefaultMinSizeRel() { return false; } + static double GetDefaultMaxSize(double diagonal); + static double GetDefaultMaxSize() { return undefinedDouble(); } + static bool GetDefaultMaxSizeRel() { return false; } + static double GetDefaultGradation() { return 1.3; } + static bool GetDefaultQuadAllowed() { return false; } + static double GetDefaultAngleMesh() { return 22.0; } + + static double GetDefaultChordalError(double diagonal); + static double GetDefaultChordalError() { return undefinedDouble(); } + static bool GetDefaultAnisotropic() { return false; } + static double GetDefaultAnisotropicRatio() { return 0.0; } + static bool GetDefaultRemoveTinyEdges() { return false; } + static double GetDefaultTinyEdgeLength(double diagonal); + static double GetDefaultTinyEdgeLength() { return undefinedDouble(); } + static bool GetDefaultBadElementRemoval() { return false; } + static double GetDefaultBadElementAspectRatio() {return 1000.0; } + static bool GetDefaultOptimizeMesh() { return true; } + static bool GetDefaultQuadraticMesh() { return false; } + + static int GetDefaultVerbosity() { return 3; } + static Topology GetDefaultTopology() { return FromCAD; } // PreCAD - static bool GetDefaultPreCADMergeEdges() { return false; } - static bool GetDefaultPreCADRemoveNanoEdges() { return false; } + static bool GetDefaultPreCADMergeEdges() { return true; } + static bool GetDefaultPreCADProcess3DTopology() { return true; } static bool GetDefaultPreCADDiscardInput() { return false; } - static double GetDefaultPreCADEpsNano(); static TSizeMap GetDefaultSizeMap() { return TSizeMap();} static TAttractorMap GetDefaultAttractorMap() { return TAttractorMap(); } @@ -315,7 +347,7 @@ public: static TEnfVertexEntryEnfVertexMap GetDefaultEnfVertexEntryEnfVertexMap() { return TEnfVertexEntryEnfVertexMap(); } static TGroupNameNodeIDMap GetDefaultGroupNameNodeIDMap() { return TGroupNameNodeIDMap(); } - static bool GetDefaultInternalEnforcedVertex(); + static bool GetDefaultInternalEnforcedVertex() { return false; } /* TODO GROUPS static TGroupNameEnfVertexListMap GetDefaultGroupNameEnfVertexListMap() { return TGroupNameEnfVertexListMap(); } @@ -344,7 +376,7 @@ public: // void SetGMFFile(const std::string& theFileName, bool isBinary); void SetGMFFile(const std::string& theFileName); std::string GetGMFFile() const { return _GMFFileName; } - static std::string GetDefaultGMFFile(); + static std::string GetDefaultGMFFile() { return "";} // bool GetGMFFileMode() const { return _GMFFileMode; } // Persistence @@ -369,23 +401,35 @@ public: private: - Topology _topology; PhysicalMesh _physicalMesh; - double _phySize, _phyMin, _phyMax; GeometricMesh _geometricMesh; - double _angleMeshS, _angleMeshC, _hgeoMin, _hgeoMax; + double _phySize; + bool _phySizeRel; + double _minSize, _maxSize; + bool _minSizeRel, _maxSizeRel; double _gradation; bool _quadAllowed; - bool _decimesh; + double _angleMesh; + double _chordalError; + bool _anisotropic; + double _anisotropicRatio; + bool _removeTinyEdges; + double _tinyEdgeLength; + bool _badElementRemoval; + double _badElementAspectRatio; + bool _optimizeMesh; + bool _quadraticMesh; int _verb; + Topology _topology; bool _preCADMergeEdges; - bool _preCADRemoveNanoEdges; + bool _preCADProcess3DTopology; bool _preCADDiscardInput; double _preCADEpsNano; TOptionValues _option2value, _preCADoption2value; - TOptionNames _doubleOptions, _charOptions, _preCADdoubleOptions, _preCADcharOptions; + TOptionNames _doubleOptions, _charOptions; + TOptionNames _preCADdoubleOptions, _preCADcharOptions; TSizeMap _sizeMap; TSizeMap _attractors; TAttractorMap _classAttractors; diff --git a/src/BLSURFPlugin/BLSURFPlugin_Hypothesis_i.cxx b/src/BLSURFPlugin/BLSURFPlugin_Hypothesis_i.cxx index 0190ed0..3625fa5 100644 --- a/src/BLSURFPlugin/BLSURFPlugin_Hypothesis_i.cxx +++ b/src/BLSURFPlugin/BLSURFPlugin_Hypothesis_i.cxx @@ -61,61 +61,62 @@ BLSURFPlugin_Hypothesis_i::~BLSURFPlugin_Hypothesis_i() { MESSAGE( "BLSURFPlugin_Hypothesis_i::~BLSURFPlugin_Hypothesis_i" ); } +//============================================================================= + +//============================================================================= /*! - * BLSURFPlugin_Hypothesis_i::SetTopology + * BLSURFPlugin_Hypothesis_i::SetPhysicalMesh * - * Set topology + * Set PhysicalMesh */ //============================================================================= -void BLSURFPlugin_Hypothesis_i::SetTopology(CORBA::Long theValue) { - // MESSAGE("BLSURFPlugin_Hypothesis_i::SetTopology"); +void BLSURFPlugin_Hypothesis_i::SetPhysicalMesh(CORBA::Long theValue) { + // MESSAGE("BLSURFPlugin_Hypothesis_i::SetPhysicalMesh"); ASSERT(myBaseImpl); - this->GetImpl()->SetTopology((::BLSURFPlugin_Hypothesis::Topology) theValue); - SMESH::TPythonDump() << _this() << ".SetTopology( " << theValue << " )"; + this->GetImpl()->SetPhysicalMesh((::BLSURFPlugin_Hypothesis::PhysicalMesh) theValue); + SMESH::TPythonDump() << _this() << ".SetPhysicalMesh( " << theValue << " )"; } //============================================================================= /*! - * BLSURFPlugin_Hypothesis_i::GetTopology + * BLSURFPlugin_Hypothesis_i::GetPhysicalMesh * - * Get Topology + * Get PhysicalMesh */ //============================================================================= -CORBA::Long BLSURFPlugin_Hypothesis_i::GetTopology() { - // MESSAGE("BLSURFPlugin_Hypothesis_i::GetTopology"); +CORBA::Long BLSURFPlugin_Hypothesis_i::GetPhysicalMesh() { + // MESSAGE("BLSURFPlugin_Hypothesis_i::GetPhysicalMesh"); ASSERT(myBaseImpl); - return this->GetImpl()->GetTopology(); + return this->GetImpl()->GetPhysicalMesh(); } -//============================================================================= - //============================================================================= /*! - * BLSURFPlugin_Hypothesis_i::SetPhysicalMesh + * BLSURFPlugin_Hypothesis_i::SetGeometricMesh * - * Set PhysicalMesh + * Set GeometricMesh */ //============================================================================= -void BLSURFPlugin_Hypothesis_i::SetPhysicalMesh(CORBA::Long theValue) { - // MESSAGE("BLSURFPlugin_Hypothesis_i::SetPhysicalMesh"); +void BLSURFPlugin_Hypothesis_i::SetGeometricMesh(CORBA::Long theValue) { + // MESSAGE("BLSURFPlugin_Hypothesis_i::SetGeometricMesh"); ASSERT(myBaseImpl); - this->GetImpl()->SetPhysicalMesh((::BLSURFPlugin_Hypothesis::PhysicalMesh) theValue); - SMESH::TPythonDump() << _this() << ".SetPhysicalMesh( " << theValue << " )"; + this->GetImpl()->SetGeometricMesh((::BLSURFPlugin_Hypothesis::GeometricMesh) theValue); + SMESH::TPythonDump() << _this() << ".SetGeometricMesh( " << theValue << " )"; } //============================================================================= /*! - * BLSURFPlugin_Hypothesis_i::GetPhysicalMesh + * BLSURFPlugin_Hypothesis_i::GetGeometricMesh * - * Get PhysicalMesh + * Get GeometricMesh */ //============================================================================= -CORBA::Long BLSURFPlugin_Hypothesis_i::GetPhysicalMesh() { - // MESSAGE("BLSURFPlugin_Hypothesis_i::GetPhysicalMesh"); +CORBA::Long BLSURFPlugin_Hypothesis_i::GetGeometricMesh() { + // MESSAGE("BLSURFPlugin_Hypothesis_i::GetGeometricMesh"); ASSERT(myBaseImpl); - return this->GetImpl()->GetPhysicalMesh(); + return this->GetImpl()->GetGeometricMesh(); } //============================================================================= @@ -128,10 +129,24 @@ CORBA::Long BLSURFPlugin_Hypothesis_i::GetPhysicalMesh() { void BLSURFPlugin_Hypothesis_i::SetPhySize(CORBA::Double theValue) { // MESSAGE("BLSURFPlugin_Hypothesis_i::SetPhySize"); ASSERT(myBaseImpl); - this->GetImpl()->SetPhySize(theValue); + this->GetImpl()->SetPhySize(theValue, false); SMESH::TPythonDump() << _this() << ".SetPhySize( " << theValue << " )"; } +//============================================================================= +/*! + * BLSURFPlugin_Hypothesis_i::SetPhySizeRel + * + * Set Relative PhySize + */ +//============================================================================= +void BLSURFPlugin_Hypothesis_i::SetPhySizeRel(CORBA::Double theValue) { +// MESSAGE("BLSURFPlugin_Hypothesis_i::SetPhySizeRel"); + ASSERT(myBaseImpl); + this->GetImpl()->SetPhySize(theValue, true); + SMESH::TPythonDump() << _this() << ".SetPhySize( " << theValue << ", isRelative = True )"; +} + //============================================================================= /*! * BLSURFPlugin_Hypothesis_i::GetPhySize @@ -146,214 +161,440 @@ CORBA::Double BLSURFPlugin_Hypothesis_i::GetPhySize() { } //============================================================================= -void BLSURFPlugin_Hypothesis_i::SetPhyMin(CORBA::Double theMinSize) { +/*! + * BLSURFPlugin_Hypothesis_i::IsPhySizeRel + * + * Returns True if PhySize is relative + */ +//============================================================================= +CORBA::Boolean BLSURFPlugin_Hypothesis_i::IsPhySizeRel() { +// MESSAGE("BLSURFPlugin_Hypothesis_i::IsPhySizeRel"); + ASSERT(myBaseImpl); + return this->GetImpl()->IsPhySizeRel(); +} + +//============================================================================= +void BLSURFPlugin_Hypothesis_i::SetMinSize(CORBA::Double theMinSize) { ASSERT(myBaseImpl); - if (GetPhyMin() != theMinSize) { - this->GetImpl()->SetPhyMin(theMinSize); - SMESH::TPythonDump() << _this() << ".SetPhyMin( " << theMinSize << " )"; + if (GetMinSize() != theMinSize) { + this->GetImpl()->SetMinSize(theMinSize, false); + SMESH::TPythonDump() << _this() << ".SetMinSize( " << theMinSize << " )"; } } //============================================================================= -CORBA::Double BLSURFPlugin_Hypothesis_i::GetPhyMin() { +void BLSURFPlugin_Hypothesis_i::SetMinSizeRel(CORBA::Double theMinSize) { + ASSERT(myBaseImpl); + if ( IsMinSizeRel() && (GetMinSize() != theMinSize) ) { + this->GetImpl()->SetMinSize(theMinSize, true); + SMESH::TPythonDump() << _this() << ".SetMinSize( " << theMinSize << ", isRelative = True )"; + } +} + +//============================================================================= +CORBA::Double BLSURFPlugin_Hypothesis_i::GetMinSize() { + ASSERT(myBaseImpl); + return this->GetImpl()->GetMinSize(); +} + +//============================================================================= +CORBA::Boolean BLSURFPlugin_Hypothesis_i::IsMinSizeRel() { +// MESSAGE("BLSURFPlugin_Hypothesis_i::IsMinSizeRel"); + ASSERT(myBaseImpl); + return this->GetImpl()->IsMinSizeRel(); +} + +//============================================================================= +void BLSURFPlugin_Hypothesis_i::SetMaxSize(CORBA::Double theMaxSize) { ASSERT(myBaseImpl); - return this->GetImpl()->GetPhyMin(); + if (GetMaxSize() != theMaxSize) { + this->GetImpl()->SetMaxSize(theMaxSize, false); + SMESH::TPythonDump() << _this() << ".SetMaxSize( " << theMaxSize << " )"; + } } //============================================================================= -void BLSURFPlugin_Hypothesis_i::SetPhyMax(CORBA::Double theMaxSize) { +void BLSURFPlugin_Hypothesis_i::SetMaxSizeRel(CORBA::Double theMaxSize) { ASSERT(myBaseImpl); - if (GetPhyMax() != theMaxSize) { - this->GetImpl()->SetPhyMax(theMaxSize); - SMESH::TPythonDump() << _this() << ".SetPhyMax( " << theMaxSize << " )"; + if ( IsMaxSizeRel() && (GetMaxSize() != theMaxSize) ) { + this->GetImpl()->SetMaxSize(theMaxSize, true); + SMESH::TPythonDump() << _this() << ".SetMaxSize( " << theMaxSize << ", isRelative = True )"; } } //============================================================================= -CORBA::Double BLSURFPlugin_Hypothesis_i::GetPhyMax() { +CORBA::Double BLSURFPlugin_Hypothesis_i::GetMaxSize() { + ASSERT(myBaseImpl); + return this->GetImpl()->GetMaxSize(); +} + +//============================================================================= +CORBA::Boolean BLSURFPlugin_Hypothesis_i::IsMaxSizeRel() { +// MESSAGE("BLSURFPlugin_Hypothesis_i::IsMaxSizeRel"); ASSERT(myBaseImpl); - return this->GetImpl()->GetPhyMax(); + return this->GetImpl()->IsMaxSizeRel(); } //============================================================================= /*! - * BLSURFPlugin_Hypothesis_i::SetGeometricMesh + * BLSURFPlugin_Hypothesis_i::SetGradation * - * Set GeometricMesh + * Set Gradation */ +//============================================================================= +void BLSURFPlugin_Hypothesis_i::SetGradation(CORBA::Double theValue) { + // MESSAGE("BLSURFPlugin_Hypothesis_i::SetGradation"); + ASSERT(myBaseImpl); + this->GetImpl()->SetGradation(theValue); + SMESH::TPythonDump() << _this() << ".SetGradation( " << theValue << " )"; +} //============================================================================= -void BLSURFPlugin_Hypothesis_i::SetGeometricMesh(CORBA::Long theValue) { - // MESSAGE("BLSURFPlugin_Hypothesis_i::SetGeometricMesh"); +/*! + * BLSURFPlugin_Hypothesis_i::GetGradation + * + * Get Gradation + */ +//============================================================================= +CORBA::Double BLSURFPlugin_Hypothesis_i::GetGradation() { + // MESSAGE("BLSURFPlugin_Hypothesis_i::GetGradation"); ASSERT(myBaseImpl); - this->GetImpl()->SetGeometricMesh((::BLSURFPlugin_Hypothesis::GeometricMesh) theValue); - SMESH::TPythonDump() << _this() << ".SetGeometricMesh( " << theValue << " )"; + return this->GetImpl()->GetGradation(); } //============================================================================= /*! - * BLSURFPlugin_Hypothesis_i::GetGeometricMesh + * BLSURFPlugin_Hypothesis_i::SetQuadAllowed * - * Get GeometricMesh + * Set true or false */ //============================================================================= -CORBA::Long BLSURFPlugin_Hypothesis_i::GetGeometricMesh() { - // MESSAGE("BLSURFPlugin_Hypothesis_i::GetGeometricMesh"); +void BLSURFPlugin_Hypothesis_i::SetQuadAllowed(CORBA::Boolean theValue) { + // MESSAGE("BLSURFPlugin_Hypothesis_i::SetQuadAllowed"); ASSERT(myBaseImpl); - return this->GetImpl()->GetGeometricMesh(); + this->GetImpl()->SetQuadAllowed(theValue); + std::string theValueStr = theValue ? "True" : "False"; + SMESH::TPythonDump() << _this() << ".SetQuadAllowed( " << theValueStr.c_str() << " )"; } //============================================================================= /*! - * BLSURFPlugin_Hypothesis_i::SetAngleMeshS + * BLSURFPlugin_Hypothesis_i::GetQuadAllowed * - * Set AngleMeshS + * Get true or false */ //============================================================================= -void BLSURFPlugin_Hypothesis_i::SetAngleMeshS(CORBA::Double theValue) { - // MESSAGE("BLSURFPlugin_Hypothesis_i::SetAngleMeshS"); +CORBA::Boolean BLSURFPlugin_Hypothesis_i::GetQuadAllowed() { + // MESSAGE("BLSURFPlugin_Hypothesis_i::GetQuadAllowed"); ASSERT(myBaseImpl); - this->GetImpl()->SetAngleMeshS(theValue); - SMESH::TPythonDump() << _this() << ".SetAngleMeshS( " << theValue << " )"; + return this->GetImpl()->GetQuadAllowed(); } //============================================================================= /*! - * BLSURFPlugin_Hypothesis_i::GetAngleMeshS + * BLSURFPlugin_Hypothesis_i::SetAngleMesh * - * Get AngleMeshS + * Set AngleMesh */ //============================================================================= -CORBA::Double BLSURFPlugin_Hypothesis_i::GetAngleMeshS() { - // MESSAGE("BLSURFPlugin_Hypothesis_i::GetAngleMeshS"); +void BLSURFPlugin_Hypothesis_i::SetAngleMesh(CORBA::Double theValue) { + // MESSAGE("BLSURFPlugin_Hypothesis_i::SetAngleMesh"); ASSERT(myBaseImpl); - return this->GetImpl()->GetAngleMeshS(); + this->GetImpl()->SetAngleMesh(theValue); + SMESH::TPythonDump() << _this() << ".SetAngleMesh( " << theValue << " )"; } //============================================================================= -void BLSURFPlugin_Hypothesis_i::SetAngleMeshC(CORBA::Double angle) { +/*! + * BLSURFPlugin_Hypothesis_i::GetAngleMesh + * + * Get AngleMesh + */ +//============================================================================= +CORBA::Double BLSURFPlugin_Hypothesis_i::GetAngleMesh() { + // MESSAGE("BLSURFPlugin_Hypothesis_i::GetAngleMesh"); ASSERT(myBaseImpl); - this->GetImpl()->SetAngleMeshC(angle); - SMESH::TPythonDump() << _this() << ".SetAngleMeshC( " << angle << " )"; + return this->GetImpl()->GetAngleMesh(); } //============================================================================= -CORBA::Double BLSURFPlugin_Hypothesis_i::GetAngleMeshC() { +/*! + * BLSURFPlugin_Hypothesis_i::SetChordalError + * + * Set Chordal Error + */ +//============================================================================= +void BLSURFPlugin_Hypothesis_i::SetChordalError(CORBA::Double theValue) { + // MESSAGE("BLSURFPlugin_Hypothesis_i::SetChordalError"); ASSERT(myBaseImpl); - return this->GetImpl()->GetAngleMeshC(); + this->GetImpl()->SetChordalError(theValue); + SMESH::TPythonDump() << _this() << ".SetChordalError( " << theValue << " )"; } //============================================================================= -void BLSURFPlugin_Hypothesis_i::SetGeoMin(CORBA::Double theMinSize) { +/*! + * BLSURFPlugin_Hypothesis_i::GetChordalError + * + * Get Chordal Error + */ +//============================================================================= +CORBA::Double BLSURFPlugin_Hypothesis_i::GetChordalError() { + // MESSAGE("BLSURFPlugin_Hypothesis_i::GetChordalError"); ASSERT(myBaseImpl); - if (GetGeoMin() != theMinSize) { - this->GetImpl()->SetGeoMin(theMinSize); - SMESH::TPythonDump() << _this() << ".SetGeoMin( " << theMinSize << " )"; - } + return this->GetImpl()->GetChordalError(); } //============================================================================= -CORBA::Double BLSURFPlugin_Hypothesis_i::GetGeoMin() { +/*! + * BLSURFPlugin_Hypothesis_i::SetAnisotropic + * + * Set true or false + */ +//============================================================================= +void BLSURFPlugin_Hypothesis_i::SetAnisotropic(CORBA::Boolean theValue) { + // MESSAGE("BLSURFPlugin_Hypothesis_i::SetAnisotropic"); ASSERT(myBaseImpl); - return this->GetImpl()->GetGeoMin(); + this->GetImpl()->SetAnisotropic(theValue); + std::string theValueStr = theValue ? "True" : "False"; + SMESH::TPythonDump() << _this() << ".SetAnisotropic( " << theValueStr.c_str() << " )"; } //============================================================================= -void BLSURFPlugin_Hypothesis_i::SetGeoMax(CORBA::Double theMaxSize) { +/*! + * BLSURFPlugin_Hypothesis_i::GetAnisotropic + * + * Get true or false + */ +//============================================================================= +CORBA::Boolean BLSURFPlugin_Hypothesis_i::GetAnisotropic() { + // MESSAGE("BLSURFPlugin_Hypothesis_i::GetAnisotropic"); ASSERT(myBaseImpl); - if (GetGeoMax() != theMaxSize) { - this->GetImpl()->SetGeoMax(theMaxSize); - SMESH::TPythonDump() << _this() << ".SetGeoMax( " << theMaxSize << " )"; - } + return this->GetImpl()->GetAnisotropic(); } //============================================================================= -CORBA::Double BLSURFPlugin_Hypothesis_i::GetGeoMax() { +/*! + * BLSURFPlugin_Hypothesis_i::SetAnisotropicRatio + * + * Set Anisotropic Ratio + */ +//============================================================================= +void BLSURFPlugin_Hypothesis_i::SetAnisotropicRatio(CORBA::Double theValue) { + // MESSAGE("BLSURFPlugin_Hypothesis_i::SetAnisotropicRatio"); ASSERT(myBaseImpl); - return this->GetImpl()->GetGeoMax(); + this->GetImpl()->SetAnisotropicRatio(theValue); + SMESH::TPythonDump() << _this() << ".SetAnisotropicRatio( " << theValue << " )"; } //============================================================================= /*! - * BLSURFPlugin_Hypothesis_i::SetGradation + * BLSURFPlugin_Hypothesis_i::GetAnisotropicRatio * - * Set Gradation + * Get Anisotropic Ratio */ //============================================================================= -void BLSURFPlugin_Hypothesis_i::SetGradation(CORBA::Double theValue) { - // MESSAGE("BLSURFPlugin_Hypothesis_i::SetGradation"); +CORBA::Double BLSURFPlugin_Hypothesis_i::GetAnisotropicRatio() { + // MESSAGE("BLSURFPlugin_Hypothesis_i::GetAnisotropicRatio"); ASSERT(myBaseImpl); - this->GetImpl()->SetGradation(theValue); - SMESH::TPythonDump() << _this() << ".SetGradation( " << theValue << " )"; + return this->GetImpl()->GetAnisotropicRatio(); } + //============================================================================= /*! - * BLSURFPlugin_Hypothesis_i::GetGradation + * BLSURFPlugin_Hypothesis_i::SetRemoveTinyEdges * - * Get Gradation + * Set true or false */ //============================================================================= -CORBA::Double BLSURFPlugin_Hypothesis_i::GetGradation() { - // MESSAGE("BLSURFPlugin_Hypothesis_i::GetGradation"); +void BLSURFPlugin_Hypothesis_i::SetRemoveTinyEdges(CORBA::Boolean theValue) { + // MESSAGE("BLSURFPlugin_Hypothesis_i::SetRemoveTinyEdges"); ASSERT(myBaseImpl); - return this->GetImpl()->GetGradation(); + this->GetImpl()->SetRemoveTinyEdges(theValue); + std::string theValueStr = theValue ? "True" : "False"; + SMESH::TPythonDump() << _this() << ".SetRemoveTinyEdges( " << theValueStr.c_str() << " )"; } //============================================================================= /*! - * BLSURFPlugin_Hypothesis_i::SetQuadAllowed + * BLSURFPlugin_Hypothesis_i::GetRemoveTinyEdges + * + * Get true or false + */ +//============================================================================= +CORBA::Boolean BLSURFPlugin_Hypothesis_i::GetRemoveTinyEdges() { + // MESSAGE("BLSURFPlugin_Hypothesis_i::GetRemoveTinyEdges"); + ASSERT(myBaseImpl); + return this->GetImpl()->GetRemoveTinyEdges(); +} + +//============================================================================= +/*! + * BLSURFPlugin_Hypothesis_i::SetTinyEdgeLength + * + * Set Tiny Edge Length + */ +//============================================================================= +void BLSURFPlugin_Hypothesis_i::SetTinyEdgeLength(CORBA::Double theValue) { + // MESSAGE("BLSURFPlugin_Hypothesis_i::SetTinyEdgeLength"); + ASSERT(myBaseImpl); + this->GetImpl()->SetTinyEdgeLength(theValue); + SMESH::TPythonDump() << _this() << ".SetTinyEdgeLength( " << theValue << " )"; +} + +//============================================================================= +/*! + * BLSURFPlugin_Hypothesis_i::GetTinyEdgeLength + * + * Get Tiny Edge Length + */ +//============================================================================= +CORBA::Double BLSURFPlugin_Hypothesis_i::GetTinyEdgeLength() { + // MESSAGE("BLSURFPlugin_Hypothesis_i::GetTinyEdgeLength"); + ASSERT(myBaseImpl); + return this->GetImpl()->GetTinyEdgeLength(); +} + +//============================================================================= +/*! + * BLSURFPlugin_Hypothesis_i::SetBadElementRemoval * * Set true or false */ //============================================================================= -void BLSURFPlugin_Hypothesis_i::SetQuadAllowed(CORBA::Boolean theValue) { - // MESSAGE("BLSURFPlugin_Hypothesis_i::SetQuadAllowed"); +void BLSURFPlugin_Hypothesis_i::SetBadElementRemoval(CORBA::Boolean theValue) { + // MESSAGE("BLSURFPlugin_Hypothesis_i::SetBadElementRemoval"); ASSERT(myBaseImpl); - this->GetImpl()->SetQuadAllowed(theValue); + this->GetImpl()->SetBadElementRemoval(theValue); std::string theValueStr = theValue ? "True" : "False"; - SMESH::TPythonDump() << _this() << ".SetQuadAllowed( " << theValueStr.c_str() << " )"; + SMESH::TPythonDump() << _this() << ".SetBadElementRemoval( " << theValueStr.c_str() << " )"; } //============================================================================= /*! - * BLSURFPlugin_Hypothesis_i::GetQuadAllowed + * BLSURFPlugin_Hypothesis_i::GetBadElementRemoval * * Get true or false */ //============================================================================= -CORBA::Boolean BLSURFPlugin_Hypothesis_i::GetQuadAllowed() { - // MESSAGE("BLSURFPlugin_Hypothesis_i::GetQuadAllowed"); +CORBA::Boolean BLSURFPlugin_Hypothesis_i::GetBadElementRemoval() { + // MESSAGE("BLSURFPlugin_Hypothesis_i::GetBadElementRemoval"); ASSERT(myBaseImpl); - return this->GetImpl()->GetQuadAllowed(); + return this->GetImpl()->GetBadElementRemoval(); +} + +//============================================================================= +/*! + * BLSURFPlugin_Hypothesis_i::SetBadElementAspectRatio + * + * Set Bad Surface Element Aspect Ratio + */ +//============================================================================= +void BLSURFPlugin_Hypothesis_i::SetBadElementAspectRatio(CORBA::Double theValue) { + // MESSAGE("BLSURFPlugin_Hypothesis_i::SetBadElementAspectRatio"); + ASSERT(myBaseImpl); + this->GetImpl()->SetBadElementAspectRatio(theValue); + SMESH::TPythonDump() << _this() << ".SetBadElementAspectRatio( " << theValue << " )"; +} + +//============================================================================= +/*! + * BLSURFPlugin_Hypothesis_i::GetBadElementAspectRatio + * + * Get Bad Surface Element Aspect Ratio + */ +//============================================================================= +CORBA::Double BLSURFPlugin_Hypothesis_i::GetBadElementAspectRatio() { + // MESSAGE("BLSURFPlugin_Hypothesis_i::GetBadElementAspectRatio"); + ASSERT(myBaseImpl); + return this->GetImpl()->GetBadElementAspectRatio(); +} + +//============================================================================= +/*! + * BLSURFPlugin_Hypothesis_i::SetOptimizeMesh + * + * Set true or false + */ +//============================================================================= +void BLSURFPlugin_Hypothesis_i::SetOptimizeMesh(CORBA::Boolean theValue) { + // MESSAGE("BLSURFPlugin_Hypothesis_i::SetOptimizeMesh"); + ASSERT(myBaseImpl); + this->GetImpl()->SetOptimizeMesh(theValue); + std::string theValueStr = theValue ? "True" : "False"; + SMESH::TPythonDump() << _this() << ".SetOptimizeMesh( " << theValueStr.c_str() << " )"; +} + +//============================================================================= +/*! + * BLSURFPlugin_Hypothesis_i::GetOptimizeMesh + * + * Get true or false + */ +//============================================================================= +CORBA::Boolean BLSURFPlugin_Hypothesis_i::GetOptimizeMesh() { + // MESSAGE("BLSURFPlugin_Hypothesis_i::GetOptimizeMesh"); + ASSERT(myBaseImpl); + return this->GetImpl()->GetOptimizeMesh(); } //============================================================================= /*! - * BLSURFPlugin_Hypothesis_i::SetDecimesh + * BLSURFPlugin_Hypothesis_i::SetQuadraticMesh * * Set true or false */ //============================================================================= -void BLSURFPlugin_Hypothesis_i::SetDecimesh(CORBA::Boolean theValue) { - // MESSAGE("BLSURFPlugin_Hypothesis_i::SetDecimesh"); +void BLSURFPlugin_Hypothesis_i::SetQuadraticMesh(CORBA::Boolean theValue) { + // MESSAGE("BLSURFPlugin_Hypothesis_i::SetQuadraticMesh"); ASSERT(myBaseImpl); - this->GetImpl()->SetDecimesh(theValue); + this->GetImpl()->SetQuadraticMesh(theValue); std::string theValueStr = theValue ? "True" : "False"; - SMESH::TPythonDump() << _this() << ".SetDecimesh( " << theValueStr.c_str() << " )"; + SMESH::TPythonDump() << _this() << ".SetQuadraticMesh( " << theValueStr.c_str() << " )"; } //============================================================================= /*! - * BLSURFPlugin_Hypothesis_i::GetDecimesh + * BLSURFPlugin_Hypothesis_i::GetQuadraticMesh * * Get true or false */ //============================================================================= -CORBA::Boolean BLSURFPlugin_Hypothesis_i::GetDecimesh() { - // MESSAGE("BLSURFPlugin_Hypothesis_i::GetDecimesh"); +CORBA::Boolean BLSURFPlugin_Hypothesis_i::GetQuadraticMesh() { + // MESSAGE("BLSURFPlugin_Hypothesis_i::GetQuadraticMesh"); + ASSERT(myBaseImpl); + return this->GetImpl()->GetQuadraticMesh(); +} + + + + + +/*! + * BLSURFPlugin_Hypothesis_i::SetTopology + * + * Set topology + */ + +//============================================================================= +void BLSURFPlugin_Hypothesis_i::SetTopology(CORBA::Long theValue) { + // MESSAGE("BLSURFPlugin_Hypothesis_i::SetTopology"); ASSERT(myBaseImpl); - return this->GetImpl()->GetDecimesh(); + this->GetImpl()->SetTopology((::BLSURFPlugin_Hypothesis::Topology) theValue); + SMESH::TPythonDump() << _this() << ".SetTopology( " << theValue << " )"; +} + +//============================================================================= +/*! + * BLSURFPlugin_Hypothesis_i::GetTopology + * + * Get Topology + */ +//============================================================================= +CORBA::Long BLSURFPlugin_Hypothesis_i::GetTopology() { + // MESSAGE("BLSURFPlugin_Hypothesis_i::GetTopology"); + ASSERT(myBaseImpl); + return this->GetImpl()->GetTopology(); } //============================================================================= @@ -402,30 +643,30 @@ CORBA::Boolean BLSURFPlugin_Hypothesis_i::GetPreCADMergeEdges() { //============================================================================= /*! - * BLSURFPlugin_Hypothesis_i::SetPreCADRemoveNanoEdges + * BLSURFPlugin_Hypothesis_i::SetPreCADProcess3DTopology * * Set true or false */ //============================================================================= -void BLSURFPlugin_Hypothesis_i::SetPreCADRemoveNanoEdges(CORBA::Boolean theValue) { - // MESSAGE("BLSURFPlugin_Hypothesis_i::SetPreCADRemoveNanoEdges"); +void BLSURFPlugin_Hypothesis_i::SetPreCADProcess3DTopology(CORBA::Boolean theValue) { + // MESSAGE("BLSURFPlugin_Hypothesis_i::SetPreCADProcess3DTopology"); ASSERT(myBaseImpl); - this->GetImpl()->SetPreCADRemoveNanoEdges(theValue); + this->GetImpl()->SetPreCADProcess3DTopology(theValue); std::string theValueStr = theValue ? "True" : "False"; - SMESH::TPythonDump() << _this() << ".SetPreCADRemoveNanoEdges( " << theValueStr.c_str() << " )"; + SMESH::TPythonDump() << _this() << ".SetPreCADProcess3DTopology( " << theValueStr.c_str() << " )"; } //============================================================================= /*! - * BLSURFPlugin_Hypothesis_i::GetPreCADRemoveNanoEdges + * BLSURFPlugin_Hypothesis_i::GetPreCADProcess3DTopology * * Get true or false */ //============================================================================= -CORBA::Boolean BLSURFPlugin_Hypothesis_i::GetPreCADRemoveNanoEdges() { - // MESSAGE("BLSURFPlugin_Hypothesis_i::GetPreCADRemoveNanoEdges"); +CORBA::Boolean BLSURFPlugin_Hypothesis_i::GetPreCADProcess3DTopology() { + // MESSAGE("BLSURFPlugin_Hypothesis_i::GetPreCADProcess3DTopology"); ASSERT(myBaseImpl); - return this->GetImpl()->GetPreCADRemoveNanoEdges(); + return this->GetImpl()->GetPreCADProcess3DTopology(); } //============================================================================= @@ -456,32 +697,6 @@ CORBA::Boolean BLSURFPlugin_Hypothesis_i::GetPreCADDiscardInput() { return this->GetImpl()->GetPreCADDiscardInput(); } -//============================================================================= -/*! - * BLSURFPlugin_Hypothesis_i::SetPreCADEpsNano - * - * Set length for nano edges - */ -//============================================================================= -void BLSURFPlugin_Hypothesis_i::SetPreCADEpsNano(CORBA::Double theValue) { - // MESSAGE("BLSURFPlugin_Hypothesis_i::SetPreCADEpsNano"); - ASSERT(myBaseImpl); - this->GetImpl()->SetPreCADEpsNano(theValue); - SMESH::TPythonDump() << _this() << ".SetPreCADEpsNano( " << theValue << " )"; -} - -//============================================================================= -/*! - * BLSURFPlugin_Hypothesis_i::GetPreCADEpsNano - * - * Get length of nano edges - */ -//============================================================================= -CORBA::Double BLSURFPlugin_Hypothesis_i::GetPreCADEpsNano() { - // MESSAGE("BLSURFPlugin_Hypothesis_i::GetPreCADEpsNano"); - ASSERT(myBaseImpl); - return this->GetImpl()->GetPreCADEpsNano(); -} //============================================================================= @@ -695,6 +910,38 @@ void BLSURFPlugin_Hypothesis_i::SetSizeMapEntry(const char* entry, const char* s //============================================================================= +void BLSURFPlugin_Hypothesis_i::SetConstantSizeMapEntry(const char* entry, GEOM::shape_type shapeType, CORBA::Double sizeMap) + throw (SALOME::SALOME_Exception) { + ASSERT(myBaseImpl); + MESSAGE("ENGINE : SETSIZEMAP START ENTRY : " << entry); + bool valueChanged = false; + std::ostringstream sizeMapFunction; + switch (shapeType) { + case GEOM::FACE: sizeMapFunction << "def f(u,v): return " << sizeMap ; break; + case GEOM::EDGE: sizeMapFunction << "def f(t): return " << sizeMap ; break; + case GEOM::VERTEX: sizeMapFunction << "def f(): return " << sizeMap ; break; + } + try { + valueChanged = (this->GetImpl()->GetSizeMapEntry(entry) != sizeMapFunction.str()); + if (valueChanged) + this->GetImpl()->SetSizeMapEntry(entry, sizeMapFunction.str()); + } catch (const std::invalid_argument& ex) { + SALOME::ExceptionStruct ExDescription; + ExDescription.text = ex.what(); + ExDescription.type = SALOME::BAD_PARAM; + ExDescription.sourceFile = "BLSURFPlugin_Hypothesis::SetSizeMapEntry(entry,sizemap)"; + ExDescription.lineNumber = 0; + throw SALOME::SALOME_Exception(ExDescription); + } catch (SALOME_Exception& ex) { + THROW_SALOME_CORBA_EXCEPTION( ex.what() ,SALOME::BAD_PARAM ); + } + MESSAGE("ENGINE : SETSIZEMAP END ENTRY : " << entry); + if (valueChanged) + SMESH::TPythonDump() << _this() << ".SetConstantSizeMap(" << entry << ", '" << sizeMap << "' )"; +} + +//============================================================================= + void BLSURFPlugin_Hypothesis_i::SetAttractorEntry(const char* entry, const char* attractor) throw (SALOME::SALOME_Exception) { ASSERT(myBaseImpl); @@ -725,7 +972,7 @@ void BLSURFPlugin_Hypothesis_i::SetAttractorEntry(const char* entry, const char* //============================================================================= -void BLSURFPlugin_Hypothesis_i::SetClassAttractorEntry(const char* entry, const char* att_entry, double StartSize, double EndSize, double ActionRadius, double ConstantRadius) //TODO à finir +void BLSURFPlugin_Hypothesis_i::SetClassAttractorEntry(const char* entry, const char* att_entry, CORBA::Double StartSize, CORBA::Double EndSize, CORBA::Double ActionRadius, CORBA::Double ConstantRadius) //TODO à finir throw (SALOME::SALOME_Exception) { ASSERT(myBaseImpl); @@ -937,6 +1184,19 @@ void BLSURFPlugin_Hypothesis_i::SetSizeMap(const GEOM::GEOM_Object_ptr GeomObj, SetSizeMapEntry(entry.c_str(), sizeMap); } +//============================================================================= + +void BLSURFPlugin_Hypothesis_i::SetConstantSizeMap(const GEOM::GEOM_Object_ptr GeomObj, CORBA::Double sizeMap) { + ASSERT(myBaseImpl); + string entry = GeomObj->GetStudyEntry(); + GEOM::shape_type shapeType = GeomObj->GetShapeType(); + if (shapeType == GEOM::COMPOUND) + shapeType = GeomObj->GetMaxShapeType(); + MESSAGE("IDL : GetName : " << GeomObj->GetName()); + MESSAGE("IDL : SETSIZEMAP ( "<< entry << " , " << sizeMap << ")"); + SetConstantSizeMapEntry(entry.c_str(), shapeType, sizeMap); +} + //============================================================================= void BLSURFPlugin_Hypothesis_i::UnsetSizeMap(const GEOM::GEOM_Object_ptr GeomObj) { ASSERT(myBaseImpl); @@ -967,7 +1227,7 @@ void BLSURFPlugin_Hypothesis_i::UnsetAttractor(GEOM::GEOM_Object_ptr GeomObj) { SMESH::TPythonDump() << _this() << ".UnsetAttractor( " << entry.c_str() << " )"; } -void BLSURFPlugin_Hypothesis_i::SetAttractorGeom(GEOM::GEOM_Object_ptr theFace, GEOM::GEOM_Object_ptr theAttractor, double StartSize, double EndSize, double ActionRadius, double ConstantRadius) +void BLSURFPlugin_Hypothesis_i::SetAttractorGeom(GEOM::GEOM_Object_ptr theFace, GEOM::GEOM_Object_ptr theAttractor, CORBA::Double StartSize, CORBA::Double EndSize, CORBA::Double ActionRadius, CORBA::Double ConstantRadius) { ASSERT(myBaseImpl); string theFaceEntry; diff --git a/src/BLSURFPlugin/BLSURFPlugin_Hypothesis_i.hxx b/src/BLSURFPlugin/BLSURFPlugin_Hypothesis_i.hxx index 2c96546..fb7c33e 100644 --- a/src/BLSURFPlugin/BLSURFPlugin_Hypothesis_i.hxx +++ b/src/BLSURFPlugin/BLSURFPlugin_Hypothesis_i.hxx @@ -45,35 +45,26 @@ public: // Destructor virtual ~BLSURFPlugin_Hypothesis_i(); - void SetTopology(CORBA::Long theValue); - CORBA::Long GetTopology(); - void SetPhysicalMesh(CORBA::Long theValue); CORBA::Long GetPhysicalMesh(); - void SetPhySize(CORBA::Double theValue); - CORBA::Double GetPhySize(); - - void SetPhyMin(CORBA::Double theMinSize); - CORBA::Double GetPhyMin(); - - void SetPhyMax(CORBA::Double theMaxSize); - CORBA::Double GetPhyMax(); - void SetGeometricMesh(CORBA::Long theValue); CORBA::Long GetGeometricMesh(); - void SetAngleMeshS(CORBA::Double theValue); - CORBA::Double GetAngleMeshS(); - - void SetAngleMeshC(CORBA::Double angle); - CORBA::Double GetAngleMeshC(); + void SetPhySize(CORBA::Double theValue); + void SetPhySizeRel(CORBA::Double theValue); + CORBA::Double GetPhySize(); + CORBA::Boolean IsPhySizeRel(); - void SetGeoMin(CORBA::Double theMinSize); - CORBA::Double GetGeoMin(); + void SetMinSize(CORBA::Double theMinSize); + void SetMinSizeRel(CORBA::Double theMinSize); + CORBA::Double GetMinSize(); + CORBA::Boolean IsMinSizeRel(); - void SetGeoMax(CORBA::Double theMaxSize); - CORBA::Double GetGeoMax(); + void SetMaxSize(CORBA::Double theMaxSize); + void SetMaxSizeRel(CORBA::Double theMaxSize); + CORBA::Double GetMaxSize(); + CORBA::Boolean IsMaxSizeRel(); void SetGradation(CORBA::Double theValue); CORBA::Double GetGradation(); @@ -81,8 +72,38 @@ public: void SetQuadAllowed(CORBA::Boolean theValue); CORBA::Boolean GetQuadAllowed(); - void SetDecimesh(CORBA::Boolean theValue); - CORBA::Boolean GetDecimesh(); + void SetAngleMesh(CORBA::Double theValue); + CORBA::Double GetAngleMesh(); + + void SetChordalError(CORBA::Double distance); + CORBA::Double GetChordalError(); + + void SetAnisotropic(CORBA::Boolean anisotropic); + CORBA::Boolean GetAnisotropic(); + + void SetAnisotropicRatio(CORBA::Double ratio); + CORBA::Double GetAnisotropicRatio(); + + void SetRemoveTinyEdges(CORBA::Boolean remove); + CORBA::Boolean GetRemoveTinyEdges(); + + void SetTinyEdgeLength(CORBA::Double length); + CORBA::Double GetTinyEdgeLength(); + + void SetBadElementRemoval(CORBA::Boolean remove); + CORBA::Boolean GetBadElementRemoval(); + + void SetBadElementAspectRatio(CORBA::Double ratio); + CORBA::Double GetBadElementAspectRatio(); + + void SetOptimizeMesh(CORBA::Boolean optimize); + CORBA::Boolean GetOptimizeMesh(); + + void SetQuadraticMesh(CORBA::Boolean quadratic); + CORBA::Boolean GetQuadraticMesh(); + + void SetTopology(CORBA::Long theValue); + CORBA::Long GetTopology(); void SetVerbosity(CORBA::Short theVal) throw (SALOME::SALOME_Exception); CORBA::Short GetVerbosity(); @@ -90,15 +111,12 @@ public: void SetPreCADMergeEdges(CORBA::Boolean theValue); CORBA::Boolean GetPreCADMergeEdges(); - void SetPreCADRemoveNanoEdges(CORBA::Boolean theValue); - CORBA::Boolean GetPreCADRemoveNanoEdges(); + void SetPreCADProcess3DTopology(CORBA::Boolean theValue); + CORBA::Boolean GetPreCADProcess3DTopology(); void SetPreCADDiscardInput(CORBA::Boolean theValue); CORBA::Boolean GetPreCADDiscardInput(); - void SetPreCADEpsNano(CORBA::Double theValue); - CORBA::Double GetPreCADEpsNano(); - void SetOptionValue(const char* optionName, const char* optionValue) throw (SALOME::SALOME_Exception); void SetPreCADOptionValue(const char* optionName, const char* optionValue) throw (SALOME::SALOME_Exception); char* GetOptionValue(const char* optionName) throw (SALOME::SALOME_Exception); @@ -115,6 +133,8 @@ public: void SetSizeMapEntry(const char* entry, const char* sizeMap) throw (SALOME::SALOME_Exception); + void SetConstantSizeMapEntry(const char* entry, GEOM::shape_type shapeType, CORBA::Double sizeMap) throw (SALOME::SALOME_Exception); + char* GetSizeMapEntry(const char* entry) throw (SALOME::SALOME_Exception); void UnsetEntry(const char* entry); @@ -125,6 +145,8 @@ public: void SetSizeMap(GEOM::GEOM_Object_ptr GeomObj, const char* sizeMap); + void SetConstantSizeMap(GEOM::GEOM_Object_ptr GeomObj, CORBA::Double sizeMap); + void UnsetSizeMap(GEOM::GEOM_Object_ptr GeomObj); void ClearSizeMaps(); @@ -144,11 +166,11 @@ public: * Set/get/unset an attractor on a face */ - void SetAttractorGeom(GEOM::GEOM_Object_ptr GeomObj, GEOM::GEOM_Object_ptr Attractor, double StartSize, double EndSize, double ActionRadius, double ConstantRadius ); + void SetAttractorGeom(GEOM::GEOM_Object_ptr GeomObj, GEOM::GEOM_Object_ptr Attractor, CORBA::Double StartSize, CORBA::Double EndSize, CORBA::Double ActionRadius, CORBA::Double ConstantRadius ); void UnsetAttractorGeom(GEOM::GEOM_Object_ptr GeomObj); - void SetClassAttractorEntry(const char* entry, const char* att_entry, double StartSize, double EndSize, double ActionRadius, double ConstantRadius) throw (SALOME::SALOME_Exception); + void SetClassAttractorEntry(const char* entry, const char* att_entry, CORBA::Double StartSize, CORBA::Double EndSize, CORBA::Double ActionRadius, CORBA::Double ConstantRadius) throw (SALOME::SALOME_Exception); BLSURFPlugin::TAttParamsMap* GetAttractorParams(); diff --git a/src/BLSURFPlugin/Makefile.am b/src/BLSURFPlugin/Makefile.am index 2d9cab3..6b0ad88 100644 --- a/src/BLSURFPlugin/Makefile.am +++ b/src/BLSURFPlugin/Makefile.am @@ -43,20 +43,20 @@ dist_libBLSURFEngine_la_SOURCES = \ BLSURFPlugin_i.cxx \ BLSURFPlugin_Attractor.cxx -libBLSURFEngine_la_CPPFLAGS = \ - $(QT_INCLUDES) \ - $(PYTHON_INCLUDES) \ - $(KERNEL_CXXFLAGS) \ - $(GUI_CXXFLAGS) \ - $(MED_CXXFLAGS) \ - $(GEOM_CXXFLAGS) \ - $(CAS_CPPFLAGS) \ - $(VTK_INCLUDES) \ - $(BLSURF_INCLUDES) \ - $(SMESH_CXXFLAGS) \ - $(CORBA_CXXFLAGS) \ - $(CORBA_INCLUDES) \ - $(BOOST_CPPFLAGS) \ +libBLSURFEngine_la_CPPFLAGS = \ + $(QT_INCLUDES) \ + $(PYTHON_INCLUDES) \ + $(KERNEL_CXXFLAGS) \ + $(GUI_CXXFLAGS) \ + $(MED_CXXFLAGS) \ + $(GEOM_CXXFLAGS) \ + $(CAS_CPPFLAGS) \ + $(VTK_INCLUDES) \ + $(MESHGEMS_CADSURF_INCLUDES) \ + $(SMESH_CXXFLAGS) \ + $(CORBA_CXXFLAGS) \ + $(CORBA_INCLUDES) \ + $(BOOST_CPPFLAGS) \ -I$(top_builddir)/idl #Qt uniquement necessaire pour le getActiveStudyDocument de SMeshGuiUtils.h @@ -65,7 +65,7 @@ libBLSURFEngine_la_LDFLAGS = \ ../../idl/libSalomeIDLBLSURFPLUGIN.la \ $(PYTHON_LIBS) \ $(CAS_KERNEL) -lTKBRep -lTKGeomBase -lTKGeomAlgo -lTKTopAlgo -lTKLCAF -lTKXSBase -lTKG2d -lTKG3d -lTKShHealing \ - $(BLSURF_LIBS) \ + $(MESHGEMS_CADSURF_LIBS) \ $(SMESH_LDFLAGS) -lSMESHimpl -lSMESHEngine -lStdMeshers -lStdMeshersEngine -lSMDS -lSMESHDS \ $(GEOM_LDFLAGS) -lGEOMbasic \ $(MED_LDFLAGS) -lSalomeIDLMED \ diff --git a/src/GUI/BLSURFPluginGUI_AdvWidget.cxx b/src/GUI/BLSURFPluginGUI_AdvWidget.cxx new file mode 100644 index 0000000..314f492 --- /dev/null +++ b/src/GUI/BLSURFPluginGUI_AdvWidget.cxx @@ -0,0 +1,56 @@ +// 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 : BLSURFPluginGUI_Dlg.cxx +// Authors : Gilles DAVID (OCC) +// --- +// + +#include "BLSURFPluginGUI_Dlg.h" + +#include + +#include + + +////////////////////////////////////////// +// BLSURFPluginGUI_AdvWidget +////////////////////////////////////////// + +BLSURFPluginGUI_AdvWidget::BLSURFPluginGUI_AdvWidget( QWidget* parent, Qt::WindowFlags f ) +: QWidget( parent, f ) +{ + setupUi( this ); + myOptionTable->horizontalHeader()->hideSection( OPTION_ID_COLUMN ); +} + +BLSURFPluginGUI_AdvWidget::~BLSURFPluginGUI_AdvWidget() +{ +} + +void BLSURFPluginGUI_AdvWidget::onChooseGMFFile() { + QString fileName = QFileDialog::getSaveFileName(0, tr("BLSURF_GMF_FILE_DIALOG"), myGMFFileName->text(), tr("BLSURF_GMF_FILE_FORMAT")); + std::cout << "fileName: " << fileName.toStdString() << std::endl; + if (!fileName.endsWith(".mesh") && !fileName.endsWith(".meshb")) + fileName.append(".mesh"); + myGMFFileName->setText(fileName); +} + + diff --git a/src/GUI/BLSURFPluginGUI_AdvWidget_QTD.ui b/src/GUI/BLSURFPluginGUI_AdvWidget_QTD.ui new file mode 100644 index 0000000..b9580bf --- /dev/null +++ b/src/GUI/BLSURFPluginGUI_AdvWidget_QTD.ui @@ -0,0 +1,202 @@ + + + BLSURFPluginGUI_AdvWidget_QTD + + + + 0 + 0 + 567 + 226 + + + + + 0 + + + + + + + true + + + true + + + true + + + false + + + false + + + true + + + + OPTION_ID_COLUMN + + + + + OPTION_TYPE_COLUMN + + + + + OPTION_NAME_COLUMN + + + + + OPTION_VALUE_COLUMN + + + + + + + + BLSURF_ADD_OPTION + + + + + + + BLSURF_REMOVE_OPTION + + + + + + + + + 0 + + + + + BLSURF_PRECAD_GROUP + + + true + + + false + + + + + + BLSURF_PRECAD_MERGE_EDGES + + + true + + + + + + + BLSURF_PRECAD_PROCESS_3D_TOPOLOGY + + + true + + + + + + + BLSURF_PRECAD_DISCARD_INPUT + + + + + + + + + + BLSURF_GMF_FILE + + + + + + + + + + Qt::Vertical + + + + 20 + 53 + + + + + + + + BLSURF_VERBOSITY + + + + + + + 100 + + + 5 + + + + + + + + + myOptionTable + addBtn + rmBtn + myPreCADGroupBox + myPreCADMergeEdges + myPreCADProcess3DTopology + myPreCADDiscardInput + myVerbosity + chooseGMFBtn + myGMFFileName + + + + + chooseGMFBtn + clicked() + BLSURFPluginGUI_AdvWidget_QTD + onChooseGMFFile() + + + 371 + 136 + + + 328 + 194 + + + + + + onChooseGMFFile() + + diff --git a/src/GUI/BLSURFPluginGUI_Dlg.h b/src/GUI/BLSURFPluginGUI_Dlg.h new file mode 100644 index 0000000..1f3e470 --- /dev/null +++ b/src/GUI/BLSURFPluginGUI_Dlg.h @@ -0,0 +1,106 @@ +// 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 +// + +// File : DlgRef.h +// Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com) + +#ifndef BLSURFPLUGINGUI_H +#define BLSURFPLUGINGUI_H + +#ifdef WIN32 + #if defined BLSURFPLUGIN_GUI_DLG_EXPORTS || defined BLSURFPluginGUI_Dlg_EXPORTS + #define BLSURFPLUGIN_GUI_DLG_EXPORT __declspec( dllexport ) + #else + #define BLSURFPLUGIN_GUI_DLG_EXPORT __declspec( dllimport ) + #endif +#else + #define BLSURFPLUGIN_GUI_DLG_EXPORT +#endif + +enum PhysicalMesh + { + DefaultSize = 0, + PhysicalGlobalSize, + PhysicalLocalSize + }; + +enum GeometricMesh + { + DefaultGeom = 0, + GeometricalGlobalSize, + GeometricalLocalSize + }; + +enum Topology { + FromCAD = 0, + Process, + Process2, + PreCAD + } ; + +enum { + OPTION_ID_COLUMN = 0, + OPTION_TYPE_COLUMN, + OPTION_NAME_COLUMN, + OPTION_VALUE_COLUMN, + NB_COLUMNS, +}; + +////////////////////////////////////////// +// BLSURFPluginGUI_StdWidget +////////////////////////////////////////// + +#include "ui_BLSURFPluginGUI_StdWidget_QTD.h" + +class BLSURFPLUGIN_GUI_DLG_EXPORT BLSURFPluginGUI_StdWidget : public QWidget, + public Ui::BLSURFPluginGUI_StdWidget_QTD +{ + Q_OBJECT + +public: + BLSURFPluginGUI_StdWidget( QWidget* = 0, Qt::WindowFlags = 0 ); + ~BLSURFPluginGUI_StdWidget(); + +public slots: + void onPhysicalMeshChanged(); + void onGeometricMeshChanged(); + void onEditingFinished(); + void resizeWidgets(); +}; + +////////////////////////////////////////// +// BLSURFPluginGUI_AdvWidget +////////////////////////////////////////// + +#include "ui_BLSURFPluginGUI_AdvWidget_QTD.h" + +class BLSURFPLUGIN_GUI_DLG_EXPORT BLSURFPluginGUI_AdvWidget : public QWidget, + public Ui::BLSURFPluginGUI_AdvWidget_QTD +{ + Q_OBJECT + +public: + BLSURFPluginGUI_AdvWidget( QWidget* = 0, Qt::WindowFlags = 0 ); + ~BLSURFPluginGUI_AdvWidget(); + +public slots: + void onChooseGMFFile(); +}; + +#endif \ No newline at end of file diff --git a/src/GUI/BLSURFPluginGUI_HypothesisCreator.cxx b/src/GUI/BLSURFPluginGUI_HypothesisCreator.cxx index 981bada..daee40e 100644 --- a/src/GUI/BLSURFPluginGUI_HypothesisCreator.cxx +++ b/src/GUI/BLSURFPluginGUI_HypothesisCreator.cxx @@ -25,7 +25,7 @@ // --- // #include "BLSURFPluginGUI_HypothesisCreator.h" -// #include +#include "BLSURFPluginGUI_Dlg.h" #include "GeometryGUI.h" @@ -40,25 +40,24 @@ #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 +#include +#include +#include +#include #include #include @@ -81,38 +80,12 @@ #include #include -#define WITH_SIZE_BOUNDARIES - -enum Topology { - FromCAD, - Process, - Process2, - PreCAD - } ; - -enum PhysicalMesh - { - DefaultSize = 0, - PhysicalUserDefined, - SizeMap - }; - -enum GeometricMesh - { - DefaultGeom = 0, - UserDefined - }; enum { STD_TAB = 0, ADV_TAB, SMP_TAB, ENF_TAB, - OPTION_ID_COLUMN = 0, - OPTION_TYPE_COLUMN, - OPTION_NAME_COLUMN, - OPTION_VALUE_COLUMN, - NB_COLUMNS, SMP_NAME_COLUMN =0, SMP_SIZEMAP_COLUMN, SMP_ENTRY_COLUMN, @@ -426,75 +399,6 @@ bool EnforcedTreeWidgetDelegate::vertexExists(QAbstractItemModel *model, // END EnforcedTreeWidgetDelegate // -// -// BEGIN BLSURFPluginGUI_ObjectReferenceParamWdg -// -//================================================================================ - -// BLSURFPluginGUI_ObjectReferenceParamWdg::BLSURFPluginGUI_ObjectReferenceParamWdg -// ( SUIT_SelectionFilter* f, QWidget* parent, bool multiSelection) -// : StdMeshersGUI_ObjectReferenceParamWdg(f, parent, multiSelection) -// { -// init(); -// } -// -// -// BLSURFPluginGUI_ObjectReferenceParamWdg::BLSURFPluginGUI_ObjectReferenceParamWdg -// ( SMESH::MeshObjectType objType, QWidget* parent, bool multiSelection ) -// : StdMeshersGUI_ObjectReferenceParamWdg( objType, parent, multiSelection ) -// { -// init(); -// } -// -// BLSURFPluginGUI_ObjectReferenceParamWdg::~BLSURFPluginGUI_ObjectReferenceParamWdg() -// { -// if ( myFilter ) -// { -// mySelectionMgr->removeFilter( myFilter ); -// delete myFilter; -// } -// } -// -// void BLSURFPluginGUI_ObjectReferenceParamWdg::init() -// { -// StdMeshersGUI_ObjectReferenceParamWdg::init(); -// disconnect( mySelButton, SIGNAL(clicked()), SLOT(activateSelection())); -// connect( mySelButton, SIGNAL(toggled(bool)), SLOT(setActivationStatus(bool))); -// } -// -// void BLSURFPluginGUI_ObjectReferenceParamWdg::setActivationStatus(bool status) -// { -// if (status) -// activateSelection(); -// else -// deactivateSelection(); -// } -// -// void BLSURFPluginGUI_ObjectReferenceParamWdg::activateSelectionOnly() -// { -// if ( !mySelectionActivated && mySelectionMgr ) -// { -// mySelectionActivated = true; -// mySelectionMgr->clearFilters(); -// if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI )) -// aViewWindow->SetSelectionMode(ActorSelection); -// if ( myFilter ) -// mySelectionMgr->installFilter( myFilter ); -// connect(mySelectionMgr, SIGNAL(currentSelectionChanged()), SLOT(onSelectionDone())); -// } -// emit selectionActivated(); -// } -// -// void BLSURFPluginGUI_ObjectReferenceParamWdg::deactivateSelectionOnly() -// { -// mySelectionActivated = false; -// disconnect(mySelectionMgr, 0, this, 0 ); -// mySelectionMgr->removeFilter( myFilter ); -// } -// -// -// END BLSURFPluginGUI_ObjectReferenceParamWdg -// /** * \brief {BLSURFPluginGUI_HypothesisCreator constructor} @@ -562,17 +466,17 @@ bool BLSURFPluginGUI_HypothesisCreator::checkParams(QString& msg) const if ( ok ) { - myOptionTable->setFocus(); + myAdvWidget->myOptionTable->setFocus(); QApplication::instance()->processEvents(); - int row = 0, nbRows = myOptionTable->rowCount(); + int row = 0, nbRows = myAdvWidget->myOptionTable->rowCount(); for ( ; row < nbRows; ++row ) { - QString name = myOptionTable->item( row, OPTION_NAME_COLUMN )->text(); - QString value = myOptionTable->item( row, OPTION_VALUE_COLUMN )->text().trimmed(); + QString name = myAdvWidget->myOptionTable->item( row, OPTION_NAME_COLUMN )->text(); + QString value = myAdvWidget->myOptionTable->item( row, OPTION_VALUE_COLUMN )->text().trimmed(); if ( !value.isEmpty() ) { try { - QString optionType = myOptionTable->item( row, OPTION_TYPE_COLUMN )->text().trimmed(); + QString optionType = myAdvWidget->myOptionTable->item( row, OPTION_TYPE_COLUMN )->text().trimmed(); if (optionType == "PRECAD") h->SetPreCADOptionValue( name.toLatin1().constData(), value.toLatin1().constData() ); else if (optionType == "BLSURF") @@ -656,169 +560,43 @@ QFrame* BLSURFPluginGUI_HypothesisCreator::buildFrame() tab->setTabPosition( QTabWidget::North ); lay->addWidget( tab ); + myName = 0; + // basic parameters myStdGroup = new QWidget(); QGridLayout* aStdLayout = new QGridLayout( myStdGroup ); aStdLayout->setSpacing( 6 ); aStdLayout->setMargin( 11 ); - - myName = 0; + if( isCreation() ) myName = new QLineEdit( myStdGroup ); - - myGradation = new SMESHGUI_SpinBox( myStdGroup ); - myGradation->RangeStepAndValidator(1.1, 2.5, 0.1, "length_precision"); - - myPhysicalMesh = new QComboBox( myStdGroup ); - QStringList physicalTypes; - physicalTypes << tr( "BLSURF_DEFAULT_USER" ) << tr( "BLSURF_CUSTOM_USER" ) << tr( "BLSURF_SIZE_MAP"); - myPhysicalMesh->addItems( physicalTypes ); - - myPhySize = new SMESHGUI_SpinBox( myStdGroup ); - myPhySize->RangeStepAndValidator(0, COORD_MAX, 10.0, "length_precision"); - -#ifdef WITH_SIZE_BOUNDARIES - myPhyMin = new SMESHGUI_SpinBox( myStdGroup ); - myPhyMin->RangeStepAndValidator(0, COORD_MAX, 10.0, "length_precision"); - myPhyMin->setText(""); - myPhyMax = new SMESHGUI_SpinBox( myStdGroup ); - myPhyMax->RangeStepAndValidator(0, COORD_MAX, 10.0, "length_precision"); - myPhyMax->setText(""); -#endif - - myGeometricMesh = new QComboBox( myStdGroup ); - QStringList types; - types << tr( "BLSURF_DEFAULT_GEOM" ) << tr( "BLSURF_CUSTOM_GEOM" ); - myGeometricMesh->addItems( types ); - - myAngleMeshS = new SMESHGUI_SpinBox( myStdGroup ); - myAngleMeshS->RangeStepAndValidator(0, 16, 0.5, "angular_precision"); - - myAngleMeshC = new SMESHGUI_SpinBox( myStdGroup ); - myAngleMeshC->RangeStepAndValidator(0, 16, 0.5, "angular_precision"); - -#ifdef WITH_SIZE_BOUNDARIES - myGeoMin = new SMESHGUI_SpinBox( myStdGroup ); - myGeoMin->RangeStepAndValidator(0, COORD_MAX, 10.0, "length_precision"); - myGeoMin->setText(""); - myGeoMax = new SMESHGUI_SpinBox( myStdGroup ); - myGeoMax->RangeStepAndValidator(0, COORD_MAX, 10.0, "length_precision"); - myGeoMax->setText(""); -#endif - myAllowQuadrangles = new QCheckBox( tr( "BLSURF_ALLOW_QUADRANGLES" ), myStdGroup ); - myDecimesh = new QCheckBox( tr( "BLSURF_DECIMESH" ), myStdGroup ); - - // ADD WIDGETS (STANDARD TAB) + myStdWidget = new BLSURFPluginGUI_StdWidget(myStdGroup); + int row = 0; if( isCreation() ) { - aStdLayout->addWidget( new QLabel( tr( "SMESH_NAME" ), myStdGroup ), row, 0, 1, 1 ); - aStdLayout->addWidget( myName, row++, 1, 1, 3 ); - } - aStdLayout->addWidget( new QLabel( tr( "BLSURF_PHY_MESH" ), myStdGroup ), row, 0, 1, 1 ); - aStdLayout->addWidget( myPhysicalMesh, row++, 1, 1, 1 ); - aStdLayout->addWidget( new QLabel( tr( "BLSURF_HPHYDEF" ), myStdGroup), row, 0, 1, 1 ); - aStdLayout->addWidget( myPhySize, row++, 1, 1, 1 ); - aStdLayout->addWidget( new QLabel( tr( "BLSURF_GRADATION" ), myStdGroup ), row, 0, 1, 1 ); - aStdLayout->addWidget( myGradation, row++, 1, 1, 1 ); -#ifdef WITH_SIZE_BOUNDARIES - aStdLayout->addWidget( new QLabel( tr( "BLSURF_HPHYMIN" ), myStdGroup ), row, 0, 1, 1 ); - aStdLayout->addWidget( myPhyMin, row++, 1, 1, 1 ); - aStdLayout->addWidget( new QLabel( tr( "BLSURF_HPHYMAX" ), myStdGroup ), row, 0, 1, 1 ); - aStdLayout->addWidget( myPhyMax, row++, 1, 1, 1 ); -#endif + aStdLayout->addWidget( new QLabel( tr( "SMESH_NAME" ), myStdGroup ), 0, 0, 1, 1 ); + aStdLayout->addWidget( myName, row++, 1, 1, 3 ); + } + aStdLayout->addWidget( myStdWidget, row++, 0, 1, 4 ); + int maxrow = row; + row = 0; if( isCreation() ) row = 1; - else - row = 0; - aStdLayout->addWidget( new QLabel( tr( "BLSURF_GEOM_MESH" ), myStdGroup ), row, 2, 1, 1 ); - aStdLayout->addWidget( myGeometricMesh, row++, 3, 1, 1 ); - aStdLayout->addWidget( new QLabel( tr( "BLSURF_ANGLE_MESH_S" ), myStdGroup ), row, 2, 1, 1 ); - aStdLayout->addWidget( myAngleMeshS, row++, 3, 1, 1 ); - aStdLayout->addWidget( new QLabel( tr( "BLSURF_ANGLE_MESH_C" ), myStdGroup ), row, 2, 1, 1 ); - aStdLayout->addWidget( myAngleMeshC, row++, 3, 1, 1 ); -#ifdef WITH_SIZE_BOUNDARIES - aStdLayout->addWidget( new QLabel( tr( "BLSURF_HGEOMIN" ), myStdGroup ), row, 2, 1, 1 ); - aStdLayout->addWidget( myGeoMin, row++, 3, 1, 1 ); - aStdLayout->addWidget( new QLabel( tr( "BLSURF_HGEOMAX" ), myStdGroup ), row, 2, 1, 1 ); - aStdLayout->addWidget( myGeoMax, row++, 3, 1, 1 ); -#endif - row = max(row,maxrow)+1; - aStdLayout->addWidget( myAllowQuadrangles, row, 0, 1, 2 ); - aStdLayout->addWidget( myDecimesh, row++, 2, 1, 2 ); +// row = max(row,maxrow)+1; aStdLayout->setRowStretch(row,1); + aStdLayout->setColumnStretch(1,1); maxrow = row; + // advanced parameters myAdvGroup = new QWidget(); QGridLayout* anAdvLayout = new QGridLayout( myAdvGroup ); anAdvLayout->setSpacing( 6 ); - anAdvLayout->setMargin( 11 ); - anAdvLayout->setRowStretch( 4, 5 ); - anAdvLayout->setColumnStretch( 1, 5 ); - - myTopology = new QComboBox( myAdvGroup ); - QStringList topologyTypes; - topologyTypes << tr( "BLSURF_TOPOLOGY_CAD" ) - << tr( "BLSURF_TOPOLOGY_PROCESS" ) - << tr( "BLSURF_TOPOLOGY_PROCESS2" ) - << tr( "BLSURF_TOPOLOGY_PRECAD" ); - myTopology->addItems( topologyTypes ); - - myVerbosity = new QSpinBox( myAdvGroup ); - myVerbosity->setMinimum( 0 ); - myVerbosity->setMaximum( 100 ); - myVerbosity->setSingleStep( 5 ); - - myOptionTable = new QTableWidget( 0, NB_COLUMNS, myAdvGroup ); - QStringList headers; - headers << tr( "OPTION_ID_COLUMN" )<< tr( "OPTION_TYPE_COLUMN" ) << tr( "OPTION_NAME_COLUMN" ) << tr( "OPTION_VALUE_COLUMN" ); - myOptionTable->setHorizontalHeaderLabels( headers ); - myOptionTable->horizontalHeader()->hideSection( OPTION_ID_COLUMN ); -// myOptionTable->horizontalHeader()->hideSection( OPTION_TYPE_COLUMN ); - myOptionTable->horizontalHeader()->setStretchLastSection(true); - myOptionTable->horizontalHeader()->setDefaultAlignment(Qt::AlignLeft); - //myOptionTable->setColumnReadOnly( OPTION_NAME_COLUMN, TRUE );////// - //myOptionTable->setColumnReadOnly( OPTION_VALUE_COLUMN, FALSE );///// - myOptionTable->verticalHeader()->hide(); - //myOptionTable->setSelectionBehavior( QAbstractItemView::SelectRows ); - - QPushButton* addBtn = new QPushButton( tr( "ADD_OPTION"), myAdvGroup ); - addBtn->setMenu( new QMenu() ); - QPushButton* rmBtn = new QPushButton( tr( "REMOVE_OPTION"), myAdvGroup ); - - myPreCADGroupBox = new QGroupBox(tr("BLSURF_PRECAD_GROUP"), myAdvGroup ); - myPreCADGroupBox->setEnabled(false); - QGridLayout* aPreCADGroupLayout = new QGridLayout(myPreCADGroupBox); - myPreCADMergeEdges = new QCheckBox(tr("BLSURF_PRECAD_MERGE_EDGES"),myPreCADGroupBox); - aPreCADGroupLayout->addWidget(myPreCADMergeEdges,0,0,1,2); - myPreCADRemoveNanoEdges = new QCheckBox(tr("BLSURF_PRECAD_REMOVE_NANO_EDGES"),myPreCADGroupBox); - aPreCADGroupLayout->addWidget(myPreCADRemoveNanoEdges,1,0,1,2); - myPreCADEpsNano = new SMESHGUI_SpinBox(myPreCADGroupBox); - myPreCADEpsNano->RangeStepAndValidator(0, COORD_MAX, 10.0, "length_precision"); - myPreCADEpsNano->setText(""); - aPreCADGroupLayout->addWidget( new QLabel( tr( "BLSURF_PRECAD_EPS_NANO" ), myPreCADGroupBox ), 2, 0, 1, 1 ); - aPreCADGroupLayout->addWidget(myPreCADEpsNano, 2, 1, 1, 1 ); - myPreCADDiscardInput = new QCheckBox(tr("BLSURF_PRECAD_DISCARD_INPUT"),myPreCADGroupBox); - aPreCADGroupLayout->addWidget(myPreCADDiscardInput, 3, 0, 1, 2); - - QPushButton* chooseGMFBtn = new QPushButton( tr( "BLSURF_GMF_FILE" ), myAdvGroup ); - myGMFFileName = new QLineEdit(myAdvGroup); -// myGMFFileMode = new QCheckBox(tr("BLSURF_GMF_MODE"),myAdvGroup); - - // ADD WIDGETS (ADVANCED TAB) - anAdvLayout->addWidget( new QLabel( tr( "BLSURF_VERBOSITY" ), myAdvGroup ), 0, 0, 1, 1 ); - anAdvLayout->addWidget( myVerbosity, 0, 1, 1, 1 ); - anAdvLayout->addWidget( new QLabel( tr( "BLSURF_TOPOLOGY" ), myAdvGroup ), 1, 0, 1, 1 ); - anAdvLayout->addWidget( myTopology, 1, 1, 1, 1 ); - anAdvLayout->addWidget( myPreCADGroupBox , 2, 0, 1, 2 ); - anAdvLayout->addWidget( addBtn, 0, 2, 1, 1 ); - anAdvLayout->addWidget( rmBtn, 0, 3, 1, 1 ); - anAdvLayout->addWidget( myOptionTable, 1, 2, 3, 2 ); - anAdvLayout->addWidget( chooseGMFBtn, 3, 0, 1, 1 ); - anAdvLayout->addWidget( myGMFFileName, 3, 1, 1, 1 ); -// anAdvLayout->addWidget( myGMFFileMode, 4, 0, 1, 2 ); - anAdvLayout->setRowStretch(4,1); + anAdvLayout->setMargin( 11 ); + myAdvWidget = new BLSURFPluginGUI_AdvWidget(myAdvGroup); + myAdvWidget->addBtn->setMenu( new QMenu() ); + anAdvLayout->addWidget( myAdvWidget); // Size Maps parameters @@ -1057,19 +835,14 @@ QFrame* BLSURFPluginGUI_HypothesisCreator::buildFrame() // --- tab->insertTab( STD_TAB, myStdGroup, tr( "SMESH_ARGUMENTS" ) ); tab->insertTab( ADV_TAB, myAdvGroup, tr( "BLSURF_ADV_ARGS" ) ); - tab->insertTab( SMP_TAB, mySmpGroup, tr( "BLSURF_SIZE_MAP" ) ); + tab->insertTab( SMP_TAB, mySmpGroup, tr( "LOCAL_SIZE" ) ); tab->insertTab( ENF_TAB, myEnfGroup, tr( "BLSURF_ENF_VER" ) ); tab->setCurrentIndex( STD_TAB ); - // --- - connect( myGeometricMesh, SIGNAL( activated( int ) ), this, SLOT( onGeometricMeshChanged() ) ); - connect( myPhysicalMesh, SIGNAL( activated( int ) ), this, SLOT( onPhysicalMeshChanged() ) ); - connect( myTopology, SIGNAL( activated( int ) ), this, SLOT( onTopologyChanged( int ) ) ); - connect( addBtn->menu(), SIGNAL( aboutToShow() ), this, SLOT( onAddOption() ) ); - connect( addBtn->menu(), SIGNAL( triggered( QAction* ) ), this, SLOT( onOptionChosenInPopup( QAction* ) ) ); - connect( rmBtn, SIGNAL( clicked()), this, SLOT( onDeleteOption() ) ); - connect( chooseGMFBtn, SIGNAL( clicked()), this, SLOT( onChooseGMFFile() ) ); + connect( myAdvWidget->addBtn->menu(), SIGNAL( aboutToShow() ), this, SLOT( onAddOption() ) ); + connect( myAdvWidget->addBtn->menu(), SIGNAL( triggered( QAction* ) ), this, SLOT( onOptionChosenInPopup( QAction* ) ) ); + connect( myAdvWidget->rmBtn, SIGNAL( clicked()), this, SLOT( onDeleteOption() ) ); // Size Maps connect( addMapButton, SIGNAL( clicked()), this, SLOT( onAddMap() ) ); @@ -1430,9 +1203,9 @@ void BLSURFPluginGUI_HypothesisCreator::onAddEnforcedVertices() { for (int column = 0; column < myEnforcedTreeWidget->columnCount(); ++column) myEnforcedTreeWidget->resizeColumnToContents(column); - if ( myPhysicalMesh->currentIndex() != SizeMap ) { - myPhysicalMesh->setCurrentIndex( SizeMap ); - onPhysicalMeshChanged(); + if ( myStdWidget->myPhysicalMesh->currentIndex() != PhysicalLocalSize ) { + myStdWidget->myPhysicalMesh->setCurrentIndex( PhysicalLocalSize ); + myStdWidget->onPhysicalMeshChanged(); } } @@ -1482,12 +1255,7 @@ void BLSURFPluginGUI_HypothesisCreator::onRemoveEnforcedVertex() { void BLSURFPluginGUI_HypothesisCreator::onInternalVerticesClicked(int state) { - if (state == Qt::Checked) { - myInternalEnforcedVerticesAllFacesGroup->setEnabled(true); - } - if (state == Qt::Unchecked) { - myInternalEnforcedVerticesAllFacesGroup->setEnabled(false); - } + myInternalEnforcedVerticesAllFacesGroup->setEnabled(state == Qt::Checked); } /** BLSURFPluginGUI_HypothesisCreator::retrieveParams() @@ -1506,47 +1274,62 @@ void BLSURFPluginGUI_HypothesisCreator::retrieveParams() const QFontMetrics metrics( myName->font() ); myName->setMinimumWidth( metrics.width( data.myName )+5 ); } - myTopology->setCurrentIndex( data.myTopology ); - myPreCADGroupBox->setEnabled(data.myTopology == PreCAD); - myPreCADMergeEdges->setChecked( data.myPreCADMergeEdges ); - myPreCADRemoveNanoEdges->setChecked( data.myPreCADRemoveNanoEdges ); - myPreCADDiscardInput->setChecked( data.myPreCADDiscardInput ); - MESSAGE("data.myPreCADEpsNano: "<setText(""); + myStdWidget->myPhysicalMesh->setCurrentIndex( data.myPhysicalMesh ); + myStdWidget->myGeometricMesh->setCurrentIndex( data.myGeometricMesh ); + if (data.myPhySize <= 0) + myStdWidget->myPhySize->setText(""); else - myPreCADEpsNano->SetValue( data.myPreCADEpsNano ); - myPhysicalMesh->setCurrentIndex( data.myPhysicalMesh ); - myPhySize->SetValue( data.myPhySize ); -#ifdef WITH_SIZE_BOUNDARIES - MESSAGE("data.myPhyMin: "<setText(""); + myStdWidget->myPhySize->SetValue( data.myPhySize ); + myStdWidget->myPhySizeRel->setChecked( data.myPhySizeRel ); + if (data.myMinSize < 0) + myStdWidget->myMinSize->setText(""); else - myPhyMin->SetValue( data.myPhyMin ); - MESSAGE("data.myPhyMax: "<setText(""); + myStdWidget->myMinSize->SetValue( data.myMinSize ); + myStdWidget->myMinSizeRel->setChecked( data.myMinSizeRel ); + if (data.myMaxSize < 0) + myStdWidget->myMaxSize->setText(""); else - myPhyMax->SetValue( data.myPhyMax ); - MESSAGE("data.myGeoMin: "<setText(""); + myStdWidget->myMaxSize->SetValue( data.myMaxSize ); + myStdWidget->myMaxSizeRel->setChecked( data.myMaxSizeRel ); + if (data.myGradation <= 0) + myStdWidget->myGradation->setText(""); else - myGeoMin->SetValue( data.myGeoMin ); - MESSAGE("data.myGeoMax: "<setText(""); + myStdWidget->myGradation->SetValue( data.myGradation ); + myStdWidget->myAllowQuadrangles->setChecked( data.myAllowQuadrangles ); + + if (data.myAngleMesh < 0) + myStdWidget->myAngleMesh->setText(""); else - myGeoMax->SetValue( data.myGeoMax ); -#endif - myGeometricMesh->setCurrentIndex( data.myGeometricMesh ); - myAngleMeshS->SetValue( data.myAngleMeshS ); - myAngleMeshC->SetValue( data.myAngleMeshC ); - myGradation->SetValue( data.myGradation ); - myAllowQuadrangles->setChecked( data.myAllowQuadrangles ); - myDecimesh->setChecked( data.myDecimesh ); - myVerbosity->setValue( data.myVerbosity ); + myStdWidget->myAngleMesh->SetValue( data.myAngleMesh ); + if (data.myChordalError <= 0) + myStdWidget->myChordalError->setText(""); + else + myStdWidget->myChordalError->SetValue( data.myChordalError ); + myStdWidget->myAnisotropic->setChecked( data.myAnisotropic ); + if (data.myAnisotropicRatio <= 0) + myStdWidget->myAnisotropicRatio->setText(""); + else + myStdWidget->myAnisotropicRatio->SetValue( data.myAnisotropicRatio ); + myStdWidget->myRemoveTinyEdges->setChecked( data.myRemoveTinyEdges ); + if (data.myTinyEdgeLength <= 0) + myStdWidget->myTinyEdgeLength->setText(""); + else + myStdWidget->myTinyEdgeLength->SetValue( data.myTinyEdgeLength ); + myStdWidget->myForceBadElementRemoval->setChecked( data.myForceBadElementRemoval ); + if (data.myBadElementAspectRatio <= 0) + myStdWidget->myBadElementAspectRatio->setText(""); + else + myStdWidget->myBadElementAspectRatio->SetValue( data.myBadElementAspectRatio ); + myStdWidget->myOptimizeMesh->setChecked( data.myOptimizeMesh ); + myStdWidget->myQuadraticMesh->setChecked( data.myQuadraticMesh ); + + myStdWidget->resizeWidgets(); + + myAdvWidget->myVerbosity->setValue( data.myVerbosity ); + myAdvWidget->myPreCADGroupBox->setChecked(data.myTopology == PreCAD); + myAdvWidget->myPreCADMergeEdges->setChecked( data.myPreCADMergeEdges ); + myAdvWidget->myPreCADProcess3DTopology->setChecked( data.myPreCADProcess3DTopology ); + myAdvWidget->myPreCADDiscardInput->setChecked( data.myPreCADDiscardInput ); if ( myOptions.operator->() ) { // MESSAGE("retrieveParams():myOptions->length() = " << myOptions->length()); @@ -1555,18 +1338,18 @@ void BLSURFPluginGUI_HypothesisCreator::retrieveParams() const QStringList name_value = option.split( ":", QString::KeepEmptyParts ); if ( name_value.count() > 1 ) { QString idStr = QString("%1").arg( i ); - int row = myOptionTable->rowCount(); - myOptionTable->setRowCount( row+1 ); - myOptionTable->setItem( row, OPTION_ID_COLUMN, new QTableWidgetItem( idStr ) ); - myOptionTable->item( row, OPTION_ID_COLUMN )->setFlags( 0 ); - myOptionTable->setItem( row, OPTION_TYPE_COLUMN, new QTableWidgetItem( "BLSURF" ) ); - myOptionTable->item( row, OPTION_TYPE_COLUMN )->setFlags( 0 ); - myOptionTable->setItem( row, OPTION_NAME_COLUMN, new QTableWidgetItem( name_value[0] ) ); - myOptionTable->item( row, OPTION_NAME_COLUMN )->setFlags( 0 ); - myOptionTable->setItem( row, OPTION_VALUE_COLUMN, new QTableWidgetItem( name_value[1] ) ); - myOptionTable->item( row, OPTION_VALUE_COLUMN )->setFlags( Qt::ItemIsSelectable | - Qt::ItemIsEditable | - Qt::ItemIsEnabled ); + int row = myAdvWidget->myOptionTable->rowCount(); + myAdvWidget->myOptionTable->setRowCount( row+1 ); + myAdvWidget->myOptionTable->setItem( row, OPTION_ID_COLUMN, new QTableWidgetItem( idStr ) ); + myAdvWidget->myOptionTable->item( row, OPTION_ID_COLUMN )->setFlags( 0 ); + myAdvWidget->myOptionTable->setItem( row, OPTION_TYPE_COLUMN, new QTableWidgetItem( "BLSURF" ) ); + myAdvWidget->myOptionTable->item( row, OPTION_TYPE_COLUMN )->setFlags( 0 ); + myAdvWidget->myOptionTable->setItem( row, OPTION_NAME_COLUMN, new QTableWidgetItem( name_value[0] ) ); + myAdvWidget->myOptionTable->item( row, OPTION_NAME_COLUMN )->setFlags( 0 ); + myAdvWidget->myOptionTable->setItem( row, OPTION_VALUE_COLUMN, new QTableWidgetItem( name_value[1] ) ); + myAdvWidget->myOptionTable->item( row, OPTION_VALUE_COLUMN )->setFlags( Qt::ItemIsSelectable | + Qt::ItemIsEditable | + Qt::ItemIsEnabled ); } } } @@ -1577,23 +1360,23 @@ void BLSURFPluginGUI_HypothesisCreator::retrieveParams() const QStringList name_value = option.split( ":", QString::KeepEmptyParts ); if ( name_value.count() > 1 ) { QString idStr = QString("%1").arg( i ); - int row = myOptionTable->rowCount(); - myOptionTable->setRowCount( row+1 ); - myOptionTable->setItem( row, OPTION_ID_COLUMN, new QTableWidgetItem( idStr ) ); - myOptionTable->item( row, OPTION_ID_COLUMN )->setFlags( 0 ); - myOptionTable->setItem( row, OPTION_TYPE_COLUMN, new QTableWidgetItem( "PRECAD" ) ); - myOptionTable->item( row, OPTION_TYPE_COLUMN )->setFlags( 0 ); - myOptionTable->setItem( row, OPTION_NAME_COLUMN, new QTableWidgetItem( name_value[0] ) ); - myOptionTable->item( row, OPTION_NAME_COLUMN )->setFlags( 0 ); - myOptionTable->setItem( row, OPTION_VALUE_COLUMN, new QTableWidgetItem( name_value[1] ) ); - myOptionTable->item( row, OPTION_VALUE_COLUMN )->setFlags( Qt::ItemIsSelectable | - Qt::ItemIsEditable | - Qt::ItemIsEnabled ); + int row = myAdvWidget->myOptionTable->rowCount(); + myAdvWidget->myOptionTable->setRowCount( row+1 ); + myAdvWidget->myOptionTable->setItem( row, OPTION_ID_COLUMN, new QTableWidgetItem( idStr ) ); + myAdvWidget->myOptionTable->item( row, OPTION_ID_COLUMN )->setFlags( 0 ); + myAdvWidget->myOptionTable->setItem( row, OPTION_TYPE_COLUMN, new QTableWidgetItem( "PRECAD" ) ); + myAdvWidget->myOptionTable->item( row, OPTION_TYPE_COLUMN )->setFlags( 0 ); + myAdvWidget->myOptionTable->setItem( row, OPTION_NAME_COLUMN, new QTableWidgetItem( name_value[0] ) ); + myAdvWidget->myOptionTable->item( row, OPTION_NAME_COLUMN )->setFlags( 0 ); + myAdvWidget->myOptionTable->setItem( row, OPTION_VALUE_COLUMN, new QTableWidgetItem( name_value[1] ) ); + myAdvWidget->myOptionTable->item( row, OPTION_VALUE_COLUMN )->setFlags( Qt::ItemIsSelectable | + Qt::ItemIsEditable | + Qt::ItemIsEnabled ); } } } - myOptionTable->resizeColumnToContents( OPTION_NAME_COLUMN ); - myGMFFileName->setText(QString(data.myGMFFileName.c_str())); + myAdvWidget->myOptionTable->resizeColumnToContents( OPTION_NAME_COLUMN ); + myAdvWidget->myGMFFileName->setText(QString(data.myGMFFileName.c_str())); // myGMFFileMode->setChecked(data.myGMFFileMode); // Sizemaps @@ -1674,8 +1457,8 @@ void BLSURFPluginGUI_HypothesisCreator::retrieveParams() const myInternalEnforcedVerticesAllFacesGroup->setEnabled(data.myInternalEnforcedVerticesAllFaces); // update widgets - that->onPhysicalMeshChanged(); - that->onGeometricMeshChanged(); + that->myStdWidget->onPhysicalMeshChanged(); + that->myStdWidget->onGeometricMeshChanged(); } /** BLSURFPluginGUI_HypothesisCreator::storeParams() @@ -1704,37 +1487,39 @@ bool BLSURFPluginGUI_HypothesisCreator::readParamsFromHypo( BlsurfHypothesisData HypothesisData* data = SMESH::GetHypothesisData( hypType() ); h_data.myName = isCreation() && data ? hypName() : ""; - h_data.myTopology = (int) h->GetTopology(); - h_data.myPhysicalMesh = (int) h->GetPhysicalMesh(); - h_data.myPhySize = h->GetPhySize(); - h_data.myGeometricMesh = (int) h->GetGeometricMesh(); - h_data.myAngleMeshS = h->GetAngleMeshS(); - h_data.myAngleMeshC = h->GetAngleMeshC(); - h_data.myGradation = h->GetGradation(); - h_data.myAllowQuadrangles = h->GetQuadAllowed(); - h_data.myDecimesh = h->GetDecimesh(); - h_data.myVerbosity = h->GetVerbosity(); - h_data.myPreCADMergeEdges = h->GetPreCADMergeEdges(); - h_data.myPreCADRemoveNanoEdges = h->GetPreCADRemoveNanoEdges(); - h_data.myPreCADDiscardInput = h->GetPreCADDiscardInput(); - double EpsNano = h->GetPreCADEpsNano(); - h_data.myPreCADEpsNano = EpsNano > 0 ? EpsNano : -1.0; - -#ifdef WITH_SIZE_BOUNDARIES - double PhyMin = h->GetPhyMin(); - double PhyMax = h->GetPhyMax(); - double GeoMin = h->GetGeoMin(); - double GeoMax = h->GetGeoMax(); -// if ( PhyMin > 0 ) -// h_data.myPhyMin = PhyMin > 0 ? QString::number( h->GetPhyMin() ) : QString(""); -// h_data.myPhyMax = PhyMax > 0 ? QString::number( h->GetPhyMax() ) : QString(""); -// h_data.myGeoMin = GeoMin > 0 ? QString::number( h->GetGeoMin() ) : QString(""); -// h_data.myGeoMax = GeoMax > 0 ? QString::number( h->GetGeoMax() ) : QString(""); - h_data.myPhyMin = PhyMin > 0 ? PhyMin : -1.0; - h_data.myPhyMax = PhyMax > 0 ? PhyMax : -1.0; - h_data.myGeoMin = GeoMin > 0 ? GeoMin : -1.0; - h_data.myGeoMax = GeoMax > 0 ? GeoMax : -1.0; -#endif + h_data.myPhysicalMesh = (int) h->GetPhysicalMesh(); + h_data.myGeometricMesh = (int) h->GetGeometricMesh(); + h_data.myPhySize = h->GetPhySize(); + h_data.myPhySizeRel = h->IsPhySizeRel(); + double minSize = h->GetMinSize(); + double maxSize = h->GetMaxSize(); + h_data.myMinSize = minSize > 0 ? minSize : -1.0; + h_data.myMinSizeRel = h->IsMinSizeRel(); + h_data.myMaxSize = maxSize > 0 ? maxSize : -1.0; + h_data.myMaxSizeRel = h->IsMaxSizeRel(); + h_data.myGradation = h->GetGradation(); + h_data.myAllowQuadrangles = h->GetQuadAllowed(); + double angle = h->GetAngleMesh(); + h_data.myAngleMesh = angle > 0 ? angle : -1.0; + double chordalError = h->GetChordalError(); + h_data.myChordalError = chordalError > 0 ? chordalError : -1.0; + h_data.myAnisotropic = h->GetAnisotropic(); + double myAnisotropicRatio = h->GetAnisotropicRatio(); + h_data.myAnisotropicRatio = myAnisotropicRatio > 0 ? myAnisotropicRatio : -1.0; + h_data.myRemoveTinyEdges = h->GetRemoveTinyEdges(); + double myTinyEdgeLength = h->GetTinyEdgeLength(); + h_data.myTinyEdgeLength = myTinyEdgeLength > 0 ? myTinyEdgeLength : -1.0; + h_data.myForceBadElementRemoval = h->GetBadElementRemoval(); + double myBadElementAspectRatio = h->GetBadElementAspectRatio(); + h_data.myBadElementAspectRatio = myBadElementAspectRatio > 0 ? myBadElementAspectRatio : -1.0; + h_data.myOptimizeMesh = h->GetOptimizeMesh(); + h_data.myQuadraticMesh = h->GetQuadraticMesh(); + h_data.myVerbosity = h->GetVerbosity(); + h_data.myTopology = (int) h->GetTopology(); + h_data.myPreCADMergeEdges = h->GetPreCADMergeEdges(); + h_data.myPreCADProcess3DTopology = h->GetPreCADProcess3DTopology(); + h_data.myPreCADDiscardInput = h->GetPreCADDiscardInput(); + BLSURFPluginGUI_HypothesisCreator* that = (BLSURFPluginGUI_HypothesisCreator*)this; that->myOptions = h->GetOptionValues(); @@ -1886,52 +1671,77 @@ bool BLSURFPluginGUI_HypothesisCreator::storeParamsToHypo( const BlsurfHypothesi bool ok = true; try { - if( isCreation() ) + if ( isCreation() ) SMESH::SetName( SMESH::FindSObject( h ), h_data.myName.toLatin1().constData() ); - if ( h->GetTopology() != h_data.myTopology ) // avoid duplication of DumpPython commands - h->SetTopology( (int) h_data.myTopology ); - if ( h->GetPhysicalMesh() != h_data.myPhysicalMesh ) + if ( h->GetPhysicalMesh() != h_data.myPhysicalMesh ) // avoid duplication of DumpPython commands h->SetPhysicalMesh( (int) h_data.myPhysicalMesh ); if ( h->GetGeometricMesh() != (int) h_data.myGeometricMesh ) h->SetGeometricMesh( (int) h_data.myGeometricMesh ); + + if ( ((int) h_data.myPhysicalMesh == PhysicalGlobalSize)||((int) h_data.myPhysicalMesh == PhysicalLocalSize) ) { + if ( h->GetPhySize() != h_data.myPhySize ) { + if ( h_data.myPhySizeRel ) + h->SetPhySizeRel( h_data.myPhySize ); + else + h->SetPhySize( h_data.myPhySize ); + } + } + if (h->GetMinSize() != h_data.myMinSize) { + if ( h_data.myMinSizeRel ) + h->SetMinSizeRel( h_data.myMinSize <= 0 ? -1 : h_data.myMinSize ); + else + h->SetMinSize( h_data.myMinSize <= 0 ? -1 : h_data.myMinSize ); + } + if (h->GetMaxSize() != h_data.myMaxSize) { + if ( h_data.myMaxSizeRel ) + h->SetMaxSizeRel( h_data.myMaxSize <= 0 ? -1 : h_data.myMaxSize ); + else + h->SetMaxSize( h_data.myMaxSize <= 0 ? -1 : h_data.myMaxSize ); + } if ( h->GetGradation() != h_data.myGradation ) - h->SetGradation( h_data.myGradation ); + h->SetGradation( h_data.myGradation <= 0 ? -1 : h_data.myGradation ); if ( h->GetQuadAllowed() != h_data.myAllowQuadrangles ) h->SetQuadAllowed( h_data.myAllowQuadrangles ); - if ( h->GetDecimesh() != h_data.myDecimesh ) - h->SetDecimesh( h_data.myDecimesh ); + + if ( (int) h_data.myGeometricMesh != DefaultGeom ) { + if ( h->GetAngleMesh() != h_data.myAngleMesh ) + h->SetAngleMesh( h_data.myAngleMesh <= 0 ? -1 :h_data.myAngleMesh ); + if ( h->GetChordalError() != h_data.myChordalError ) + h->SetChordalError( h_data.myChordalError <= 0 ? -1 :h_data.myChordalError ); + } + + if ( h->GetAnisotropic() != h_data.myAnisotropic ) + h->SetAnisotropic( h_data.myAnisotropic ); + if ( h_data.myAnisotropic && ( h->GetAnisotropicRatio() != h_data.myAnisotropicRatio ) ) + h->SetAnisotropicRatio( h_data.myAnisotropicRatio <= 0 ? -1 :h_data.myAnisotropicRatio ); + + if ( h->GetRemoveTinyEdges() != h_data.myRemoveTinyEdges ) + h->SetRemoveTinyEdges( h_data.myRemoveTinyEdges ); + if ( h_data.myRemoveTinyEdges && ( h->GetTinyEdgeLength() != h_data.myTinyEdgeLength ) ) + h->SetTinyEdgeLength( h_data.myTinyEdgeLength <= 0 ? -1 :h_data.myTinyEdgeLength ); + + if ( h->GetBadElementRemoval() != h_data.myForceBadElementRemoval ) + h->SetBadElementRemoval( h_data.myForceBadElementRemoval ); + if ( h_data.myForceBadElementRemoval && ( h->GetBadElementAspectRatio() != h_data.myBadElementAspectRatio ) ) + h->SetBadElementAspectRatio( h_data.myBadElementAspectRatio <= 0 ? -1 :h_data.myBadElementAspectRatio ); + + if ( h->GetOptimizeMesh() != h_data.myOptimizeMesh ) + h->SetOptimizeMesh( h_data.myOptimizeMesh ); + + if ( h->GetQuadraticMesh() != h_data.myQuadraticMesh ) + h->SetQuadraticMesh( h_data.myQuadraticMesh ); + if ( h->GetVerbosity() != h_data.myVerbosity ) h->SetVerbosity( h_data.myVerbosity ); + if ( h->GetTopology() != h_data.myTopology ) + h->SetTopology( (int) h_data.myTopology ); if ( h->GetPreCADMergeEdges() != h_data.myPreCADMergeEdges ) h->SetPreCADMergeEdges( h_data.myPreCADMergeEdges ); - if ( h->GetPreCADRemoveNanoEdges() != h_data.myPreCADRemoveNanoEdges ) - h->SetPreCADRemoveNanoEdges( h_data.myPreCADRemoveNanoEdges ); + if ( h->GetPreCADProcess3DTopology() != h_data.myPreCADProcess3DTopology ) + h->SetPreCADProcess3DTopology( h_data.myPreCADProcess3DTopology ); if ( h->GetPreCADDiscardInput() != h_data.myPreCADDiscardInput ) h->SetPreCADDiscardInput( h_data.myPreCADDiscardInput ); - if ( h->GetPreCADEpsNano() != h_data.myPreCADEpsNano && h_data.myPreCADEpsNano > 0) - h->SetPreCADEpsNano( h_data.myPreCADEpsNano ); - - if( ((int) h_data.myPhysicalMesh == PhysicalUserDefined)||((int) h_data.myPhysicalMesh == SizeMap) ) { - if ( h->GetPhySize() != h_data.myPhySize ) - h->SetPhySize( h_data.myPhySize ); - } - if( (int) h_data.myGeometricMesh == UserDefined ) { - if ( h->GetAngleMeshS() != h_data.myAngleMeshS ) - h->SetAngleMeshS( h_data.myAngleMeshS ); - if ( h->GetAngleMeshC() != h_data.myAngleMeshC ) - h->SetAngleMeshC( h_data.myAngleMeshC ); - } -#ifdef WITH_SIZE_BOUNDARIES - if (h->GetPhyMin() != h_data.myPhyMin && h_data.myPhyMin > 0) - h->SetPhyMin( h_data.myPhyMin ); - if (h->GetPhyMax() != h_data.myPhyMax && h_data.myPhyMax > 0) - h->SetPhyMax( h_data.myPhyMax ); - if (h->GetGeoMin() != h_data.myGeoMin && h_data.myGeoMin > 0) - h->SetGeoMin( h_data.myGeoMin ); - if (h->GetGeoMax() != h_data.myGeoMax && h_data.myGeoMax > 0) - h->SetGeoMax( h_data.myGeoMax ); -#endif h->SetOptionValues( myOptions ); // is set in checkParams() h->SetPreCADOptionValues( myPreCADOptions ); // is set in checkParams() @@ -2046,57 +1856,72 @@ QString BLSURFPluginGUI_HypothesisCreator::readParamsFromWidgets( BlsurfHypothes { MESSAGE("BLSURFPluginGUI_HypothesisCreator::readParamsFromWidgets"); h_data.myName = myName ? myName->text() : ""; - h_data.myTopology = myTopology->currentIndex(); - h_data.myPhysicalMesh = myPhysicalMesh->currentIndex(); - h_data.myPhySize = myPhySize->GetValue(); -#ifdef WITH_SIZE_BOUNDARIES - h_data.myPhyMin = myPhyMin->GetValue(); - h_data.myPhyMax = myPhyMax->GetValue(); - h_data.myGeoMin = myGeoMin->GetValue(); - h_data.myGeoMax = myGeoMax->GetValue(); -#endif - h_data.myGeometricMesh = myGeometricMesh->currentIndex(); - h_data.myAngleMeshS = myAngleMeshS->GetValue(); - h_data.myAngleMeshC = myAngleMeshC->GetValue(); - h_data.myGradation = myGradation->GetValue(); - h_data.myAllowQuadrangles = myAllowQuadrangles->isChecked(); - h_data.myDecimesh = myDecimesh->isChecked(); - h_data.myVerbosity = myVerbosity->value(); - h_data.myPreCADMergeEdges = myPreCADMergeEdges->isChecked(); - h_data.myPreCADRemoveNanoEdges = myPreCADRemoveNanoEdges->isChecked(); - h_data.myPreCADDiscardInput = myPreCADDiscardInput->isChecked(); - h_data.myPreCADEpsNano = myPreCADEpsNano->GetValue(); + h_data.myPhysicalMesh = myStdWidget->myPhysicalMesh->currentIndex(); + h_data.myGeometricMesh = myStdWidget->myGeometricMesh->currentIndex(); + h_data.myPhySize = myStdWidget->myPhySize->text().isEmpty() ? -1.0 : myStdWidget->myPhySize->GetValue(); + h_data.myPhySizeRel = myStdWidget->myPhySizeRel->isChecked(); + h_data.myMinSize = myStdWidget->myMinSize->text().isEmpty() ? -1.0 : myStdWidget->myMinSize->GetValue(); + h_data.myMinSizeRel = myStdWidget->myMinSizeRel->isChecked(); + h_data.myMaxSize = myStdWidget->myMaxSize->text().isEmpty() ? -1.0 : myStdWidget->myMaxSize->GetValue(); + h_data.myMaxSizeRel = myStdWidget->myMaxSizeRel->isChecked(); + h_data.myGradation = myStdWidget->myGradation->text().isEmpty() ? -1.0 : myStdWidget->myGradation->GetValue(); + h_data.myAllowQuadrangles = myStdWidget->myAllowQuadrangles->isChecked(); + h_data.myAngleMesh = myStdWidget->myAngleMesh->text().isEmpty() ? -1.0 : myStdWidget->myAngleMesh->GetValue(); + h_data.myChordalError = myStdWidget->myChordalError->text().isEmpty() ? -1.0 : myStdWidget->myChordalError->GetValue(); + h_data.myAnisotropic = myStdWidget->myAnisotropic->isChecked(); + h_data.myAnisotropicRatio = myStdWidget->myAnisotropicRatio->text().isEmpty() ? -1.0 : myStdWidget->myAnisotropicRatio->GetValue(); + h_data.myRemoveTinyEdges = myStdWidget->myRemoveTinyEdges->isChecked(); + h_data.myTinyEdgeLength = myStdWidget->myTinyEdgeLength->text().isEmpty() ? -1.0 : myStdWidget->myTinyEdgeLength->GetValue(); + h_data.myForceBadElementRemoval= myStdWidget->myForceBadElementRemoval->isChecked(); + h_data.myBadElementAspectRatio = myStdWidget->myBadElementAspectRatio->text().isEmpty() ? -1.0 : myStdWidget->myBadElementAspectRatio->GetValue(); + h_data.myOptimizeMesh = myStdWidget->myOptimizeMesh->isChecked(); + h_data.myQuadraticMesh = myStdWidget->myQuadraticMesh->isChecked(); + h_data.myVerbosity = myAdvWidget->myVerbosity->value(); + h_data.myTopology = myAdvWidget->myPreCADGroupBox->isChecked() ? PreCAD : FromCAD; + h_data.myPreCADMergeEdges = myAdvWidget->myPreCADMergeEdges->isChecked(); + h_data.myPreCADProcess3DTopology = myAdvWidget->myPreCADProcess3DTopology->isChecked(); + h_data.myPreCADDiscardInput = myAdvWidget->myPreCADDiscardInput->isChecked(); QString guiHyp; - guiHyp += tr("BLSURF_TOPOLOGY") + " = " + QString::number( h_data.myTopology ) + "; "; guiHyp += tr("BLSURF_PHY_MESH") + " = " + QString::number( h_data.myPhysicalMesh ) + "; "; - guiHyp += tr("BLSURF_HPHYDEF") + " = " + QString::number( h_data.myPhySize ) + "; "; guiHyp += tr("BLSURF_GEOM_MESH") + " = " + QString::number( h_data.myGeometricMesh ) + "; "; - guiHyp += tr("BLSURF_ANGLE_MESH_S") + " = " + QString::number( h_data.myAngleMeshS ) + "; "; + guiHyp += tr("BLSURF_HPHYDEF") + " = " + QString::number( h_data.myPhySize ) + "; "; + guiHyp += tr("BLSURF_HPHYDEF") + " " + tr("BLSURF_SIZE_REL") +" = " + QString(h_data.myPhySizeRel ? "yes" : "no") + "; "; + guiHyp += tr("BLSURF_MINSIZE") + " = "+ QString::number( h_data.myMinSize ) + "; "; + guiHyp += tr("BLSURF_MINSIZE") + " " + tr("BLSURF_SIZE_REL") + " = " + QString(h_data.myMinSizeRel ? "yes" : "no") + "; "; + guiHyp += tr("BLSURF_MAXSIZE") + " = "+ QString::number( h_data.myMaxSize ) + "; "; + guiHyp += tr("BLSURF_MAXSIZE") + " " + tr("BLSURF_SIZE_REL") + " = " + QString(h_data.myMaxSizeRel ? "yes" : "no") + "; "; guiHyp += tr("BLSURF_GRADATION") + " = " + QString::number( h_data.myGradation ) + "; "; guiHyp += tr("BLSURF_ALLOW_QUADRANGLES") + " = " + QString(h_data.myAllowQuadrangles ? "yes" : "no") + "; "; - guiHyp += tr("BLSURF_DECIMESH") + " = " + QString(h_data.myDecimesh ? "yes" : "no") + "; "; -#ifdef WITH_SIZE_BOUNDARIES - guiHyp += "hphymin = " + QString::number( h_data.myPhyMin ) + "; "; - guiHyp += "hphymax = " + QString::number( h_data.myPhyMax ) + "; "; - guiHyp += "hgeomin = " + QString::number( h_data.myGeoMin ) + "; "; - guiHyp += "hgeomax = " + QString::number( h_data.myGeoMax ) + "; "; -#endif + guiHyp += tr("BLSURF_ANGLE_MESH") + " = " + QString::number( h_data.myAngleMesh ) + "; "; + guiHyp += tr("BLSURF_CHORDAL_ERROR") + " = " + QString::number( h_data.myChordalError ) + "; "; + guiHyp += tr("BLSURF_ANISOTROPIC") + " = " + QString(h_data.myAnisotropic ? "yes" : "no") + "; "; + guiHyp += tr("BLSURF_ANISOTROPIC_RATIO") + " = " + QString::number( h_data.myAnisotropicRatio ) + "; "; + + + guiHyp += tr("BLSURF_REMOVE_TINY_EDGES") + " = " + QString(h_data.myRemoveTinyEdges ? "yes" : "no") + "; "; + guiHyp += tr("BLSURF_TINY_EDGES_LENGTH") + " = " + QString::number( h_data.myTinyEdgeLength ) + "; "; + guiHyp += tr("BLSURF_REMOVE_SLIVERS") + " = " + QString(h_data.myForceBadElementRemoval ? "yes" : "no") + "; "; + guiHyp += tr("BLSURF_BAD_SURFACE_ELEMENT_ASPECT_RATIO") + " = " + QString::number( h_data.myBadElementAspectRatio ) + "; "; + guiHyp += tr("BLSURF_OPTIMISATION") + " = " + QString(h_data.myOptimizeMesh ? "yes" : "no") + "; "; + guiHyp += tr("BLSURF_ELEMENT_ORDER") + " = " + QString(h_data.myQuadraticMesh ? "yes" : "no") + "; "; + + + guiHyp += tr("BLSURF_TOPOLOGY") + " = " + QString::number( h_data.myTopology ) + "; "; guiHyp += tr("BLSURF_PRECAD_MERGE_EDGES") + " = " + QString(h_data.myPreCADMergeEdges ? "yes" : "no") + "; "; - guiHyp += tr("BLSURF_PRECAD_REMOVE_NANO_EDGES") + " = " + QString(h_data.myPreCADRemoveNanoEdges ? "yes" : "no") + "; "; + guiHyp += tr("BLSURF_PRECAD_REMOVE_NANO_EDGES") + " = " + QString(h_data.myPreCADProcess3DTopology ? "yes" : "no") + "; "; guiHyp += tr("BLSURF_PRECAD_DISCARD_INPUT") + " = " + QString(h_data.myPreCADDiscardInput ? "yes" : "no") + "; "; - guiHyp += tr("BLSURF_PRECAD_EPS_NANO") + " = " + QString::number( h_data.myPreCADEpsNano ) + "; "; BLSURFPluginGUI_HypothesisCreator* that = (BLSURFPluginGUI_HypothesisCreator*)this; - int row = 0, nbRows = myOptionTable->rowCount(); + int row = 0, nbRows = myAdvWidget->myOptionTable->rowCount(); for ( ; row < nbRows; ++row ) { - int id = myOptionTable->item( row, OPTION_ID_COLUMN )->text().toInt(); - std::string optionType = myOptionTable->item( row, OPTION_TYPE_COLUMN )->text().toStdString(); + int id = myAdvWidget->myOptionTable->item( row, OPTION_ID_COLUMN )->text().toInt(); + std::string optionType = myAdvWidget->myOptionTable->item( row, OPTION_TYPE_COLUMN )->text().toStdString(); if ( id >= 0 && ( ( optionType == "BLSURF" && id < myOptions->length() ) || ( optionType == "PRECAD" && id < myPreCADOptions->length() ) ) ) { - QString name = myOptionTable->item( row, OPTION_NAME_COLUMN )->text(); - QString value = myOptionTable->item( row, OPTION_VALUE_COLUMN )->text().trimmed(); + QString name = myAdvWidget->myOptionTable->item( row, OPTION_NAME_COLUMN )->text(); + QString value = myAdvWidget->myOptionTable->item( row, OPTION_VALUE_COLUMN )->text().trimmed(); if ( value.isNull() ) value = ""; if (optionType == "PRECAD") @@ -2112,7 +1937,7 @@ QString BLSURFPluginGUI_HypothesisCreator::readParamsFromWidgets( BlsurfHypothes } } - h_data.myGMFFileName = myGMFFileName->text().toStdString(); + h_data.myGMFFileName = myAdvWidget->myGMFFileName->text().toStdString(); // h_data.myGMFFileMode = myGMFFileMode->isChecked(); // SizeMap @@ -2186,58 +2011,6 @@ QString BLSURFPluginGUI_HypothesisCreator::readParamsFromWidgets( BlsurfHypothes return guiHyp; } - -void BLSURFPluginGUI_HypothesisCreator::onTopologyChanged(int index) { - MESSAGE("BLSURFPluginGUI_HypothesisCreator::onTopologyChanged"); - myPreCADGroupBox->setEnabled(index == PreCAD); -} - -void BLSURFPluginGUI_HypothesisCreator::onPhysicalMeshChanged() { - MESSAGE("BLSURFPluginGUI_HypothesisCreator::onPhysicalMeshChanged"); - bool isPhysicalUserDefined = (myPhysicalMesh->currentIndex() == PhysicalUserDefined); - bool isSizeMap = (myPhysicalMesh->currentIndex() == SizeMap); - bool isCustom = (isPhysicalUserDefined || isSizeMap) ; - bool geomIsCustom = (myGeometricMesh->currentIndex() == UserDefined); - - myGradation->setEnabled(!isPhysicalUserDefined || geomIsCustom); - myPhySize->setEnabled(isCustom); - myPhyMax->setEnabled(isCustom); - myPhyMin->setEnabled(isCustom); - - if ( !myGradation->isEnabled()) - myGradation->SetValue( 1.1 ); - - if ( !isCustom ) { - if ( myGeometricMesh->currentIndex() == DefaultGeom ) { - myGeometricMesh->setCurrentIndex( UserDefined ); - onGeometricMeshChanged(); - } - } -} - -void BLSURFPluginGUI_HypothesisCreator::onGeometricMeshChanged() { - MESSAGE("BLSURFPluginGUI_HypothesisCreator::onGeometricMeshChanged"); - bool isCustom = (myGeometricMesh->currentIndex() == UserDefined); - bool phyIsSizemap = (myPhysicalMesh->currentIndex() == SizeMap); - - myAngleMeshS->setEnabled(isCustom); - myAngleMeshC->setEnabled(isCustom); - myGradation->setEnabled(isCustom || phyIsSizemap); - myGeoMax->setEnabled(isCustom); - myGeoMin->setEnabled(isCustom); - - if ( !myGradation->isEnabled()) - myGradation->SetValue( 1.1 ); - - if ( ! isCustom ) { - // hphy_flag = 0 and hgeo_flag = 0 is not allowed (spec) - if ( myPhysicalMesh->currentIndex() == DefaultSize ) { - myPhysicalMesh->setCurrentIndex( PhysicalUserDefined ); - onPhysicalMeshChanged(); - } - } -} - void BLSURFPluginGUI_HypothesisCreator::onAddOption() { QMenu* menu = (QMenu*)sender(); @@ -2264,7 +2037,7 @@ void BLSURFPluginGUI_HypothesisCreator::onAddOption() void BLSURFPluginGUI_HypothesisCreator::onOptionChosenInPopup( QAction* a ) { - myOptionTable->setFocus(); + myAdvWidget->myOptionTable->setFocus(); QMenu* menu = (QMenu*)( a->parent() ); int idx = menu->actions().indexOf( a ); @@ -2281,69 +2054,59 @@ void BLSURFPluginGUI_HypothesisCreator::onOptionChosenInPopup( QAction* a ) QString optionName = option.split( ":", QString::KeepEmptyParts )[0]; // look for a row with optionName - int row = 0, nbRows = myOptionTable->rowCount(); + int row = 0, nbRows = myAdvWidget->myOptionTable->rowCount(); for ( ; row < nbRows; ++row ) - if ( myOptionTable->item( row, OPTION_ID_COLUMN )->text() == idStr ) - if ( myOptionTable->item( row, OPTION_TYPE_COLUMN )->text() == optionType ) + if ( myAdvWidget->myOptionTable->item( row, OPTION_ID_COLUMN )->text() == idStr ) + if ( myAdvWidget->myOptionTable->item( row, OPTION_TYPE_COLUMN )->text() == optionType ) break; // add a row if not found if ( row == nbRows ) { - myOptionTable->setRowCount( row+1 ); - myOptionTable->setItem( row, OPTION_ID_COLUMN, new QTableWidgetItem( idStr ) ); - myOptionTable->item( row, OPTION_ID_COLUMN )->setFlags( 0 ); - myOptionTable->setItem( row, OPTION_TYPE_COLUMN, new QTableWidgetItem( optionType ) ); - myOptionTable->item( row, OPTION_TYPE_COLUMN )->setFlags( 0 ); - myOptionTable->setItem( row, OPTION_NAME_COLUMN, new QTableWidgetItem( optionName ) ); - myOptionTable->item( row, OPTION_NAME_COLUMN )->setFlags( 0 ); - myOptionTable->setItem( row, OPTION_VALUE_COLUMN, new QTableWidgetItem( "" ) ); - myOptionTable->item( row, OPTION_VALUE_COLUMN )->setFlags( Qt::ItemIsSelectable | - Qt::ItemIsEditable | - Qt::ItemIsEnabled ); - myOptionTable->resizeColumnToContents( OPTION_NAME_COLUMN ); - } - myOptionTable->clearSelection(); - myOptionTable->scrollToItem( myOptionTable->item( row, OPTION_VALUE_COLUMN ) ); - //myOptionTable->item( row, OPTION_VALUE_COLUMN )->setSelected( true ); - myOptionTable->setCurrentCell( row, OPTION_VALUE_COLUMN ); - //myOptionTable->openPersistentEditor( myOptionTable->item( row, OPTION_VALUE_COLUMN ) ); + myAdvWidget->myOptionTable->setRowCount( row+1 ); + myAdvWidget->myOptionTable->setItem( row, OPTION_ID_COLUMN, new QTableWidgetItem( idStr ) ); + myAdvWidget->myOptionTable->item( row, OPTION_ID_COLUMN )->setFlags( 0 ); + myAdvWidget->myOptionTable->setItem( row, OPTION_TYPE_COLUMN, new QTableWidgetItem( optionType ) ); + myAdvWidget->myOptionTable->item( row, OPTION_TYPE_COLUMN )->setFlags( 0 ); + myAdvWidget->myOptionTable->setItem( row, OPTION_NAME_COLUMN, new QTableWidgetItem( optionName ) ); + myAdvWidget->myOptionTable->item( row, OPTION_NAME_COLUMN )->setFlags( 0 ); + myAdvWidget->myOptionTable->setItem( row, OPTION_VALUE_COLUMN, new QTableWidgetItem( "" ) ); + myAdvWidget->myOptionTable->item( row, OPTION_VALUE_COLUMN )->setFlags( Qt::ItemIsSelectable | + Qt::ItemIsEditable | + Qt::ItemIsEnabled ); + myAdvWidget->myOptionTable->resizeColumnToContents( OPTION_NAME_COLUMN ); + } + myAdvWidget->myOptionTable->clearSelection(); + myAdvWidget->myOptionTable->scrollToItem( myAdvWidget->myOptionTable->item( row, OPTION_VALUE_COLUMN ) ); + //myAdvWidget->myOptionTable->item( row, OPTION_VALUE_COLUMN )->setSelected( true ); + myAdvWidget->myOptionTable->setCurrentCell( row, OPTION_VALUE_COLUMN ); + //myAdvWidget->myOptionTable->openPersistentEditor( myOptionTable->item( row, OPTION_VALUE_COLUMN ) ); } void BLSURFPluginGUI_HypothesisCreator::onDeleteOption() { // clear option values and remember selected row QList selectedRows; - QList selected = myOptionTable->selectedItems(); + QList selected = myAdvWidget->myOptionTable->selectedItems(); QTableWidgetItem* item; foreach( item, selected ) { int row = item->row(); if ( !selectedRows.contains( row ) ) { selectedRows.append( row ); - int id = myOptionTable->item( row, OPTION_ID_COLUMN )->text().toInt(); - std::string optionType = myOptionTable->item( row, OPTION_TYPE_COLUMN )->text().toStdString(); + int id = myAdvWidget->myOptionTable->item( row, OPTION_ID_COLUMN )->text().toInt(); + QString optionType = myAdvWidget->myOptionTable->item( row, OPTION_TYPE_COLUMN )->text(); if ( id >= 0 ) if (optionType == "BLSURF" && id < myOptions->length() ) - myOptions[ id ] = myOptionTable->item( row, OPTION_NAME_COLUMN )->text().toLatin1().constData(); + myOptions[ id ] = myAdvWidget->myOptionTable->item( row, OPTION_NAME_COLUMN )->text().toLatin1().constData(); else if (optionType == "PRECAD" && id < myPreCADOptions->length() ) - myPreCADOptions[ id ] = myOptionTable->item( row, OPTION_NAME_COLUMN )->text().toLatin1().constData(); + myPreCADOptions[ id ] = myAdvWidget->myOptionTable->item( row, OPTION_NAME_COLUMN )->text().toLatin1().constData(); } } qSort( selectedRows ); QListIterator it( selectedRows ); it.toBack(); while ( it.hasPrevious() ) - myOptionTable->removeRow( it.previous() ); + myAdvWidget->myOptionTable->removeRow( it.previous() ); } -void BLSURFPluginGUI_HypothesisCreator::onChooseGMFFile() -{ -// QFileDialog dlg(0); -// dlg.selectFile(myGMFFileName->text()); -// dlg.setNameFilter(tr("BLSURF_GMF_FILE_FORMAT")); -// dlg.setDefaultSuffix(QString("mesh")); - myGMFFileName->setText(QFileDialog::getSaveFileName(0, tr("BLSURF_GMF_FILE_DIALOG"), myGMFFileName->text(), tr("BLSURF_GMF_FILE_FORMAT"))); -} - - // ********************** // *** BEGIN SIZE MAP *** // ********************** @@ -2677,9 +2440,9 @@ void BLSURFPluginGUI_HypothesisCreator::insertElement(GEOM::GEOM_Object_var anOb mySizeMapTable->resizeColumnToContents( SMP_ENTRY_COLUMN ); mySizeMapTable->clearSelection(); - if ( myPhysicalMesh->currentIndex() != SizeMap ) { - myPhysicalMesh->setCurrentIndex( SizeMap ); - onPhysicalMeshChanged(); + if ( myStdWidget->myPhysicalMesh->currentIndex() != PhysicalLocalSize ) { + myStdWidget->myPhysicalMesh->setCurrentIndex( PhysicalLocalSize ); + myStdWidget->onPhysicalMeshChanged(); } } @@ -2765,9 +2528,9 @@ void BLSURFPluginGUI_HypothesisCreator::insertAttractor(GEOM::GEOM_Object_var aF mySizeMapTable->resizeColumnToContents( SMP_NAME_COLUMN ); mySizeMapTable->resizeColumnToContents( SMP_SIZEMAP_COLUMN ); - if ( myPhysicalMesh->currentIndex() != SizeMap ) { - myPhysicalMesh->setCurrentIndex( SizeMap ); - onPhysicalMeshChanged(); + if ( myStdWidget->myPhysicalMesh->currentIndex() != PhysicalLocalSize ) { + myStdWidget->myPhysicalMesh->setCurrentIndex( PhysicalLocalSize ); + myStdWidget->onPhysicalMeshChanged(); } MESSAGE("mySMPMap.size() = "< +#include + +using namespace std; + +////////////////////////////////////////// +// BLSURFPluginGUI_StdWidget +////////////////////////////////////////// + +BLSURFPluginGUI_StdWidget::BLSURFPluginGUI_StdWidget( QWidget* parent, Qt::WindowFlags f ) +: QWidget( parent, f ) +{ + setupUi( this ); + myPhySize->RangeStepAndValidator(0, COORD_MAX, 10.0, "length_precision"); + myMinSize->RangeStepAndValidator(0, COORD_MAX, 10.0, "length_precision"); + myMaxSize->RangeStepAndValidator(0, COORD_MAX, 10.0, "length_precision"); + myGradation->RangeStepAndValidator(1.1, COORD_MAX, 0.1, "length_precision"); + myAngleMesh->RangeStepAndValidator(0, 90, 0.5, "angular_precision"); + myChordalError->RangeStepAndValidator(0, COORD_MAX, 0.1, "length_precision"); + myAnisotropicRatio->RangeStepAndValidator(0, COORD_MAX, 0.1, "length_precision"); + myTinyEdgeLength->RangeStepAndValidator(COORD_MIN, COORD_MAX, 0.1, "length_precision"); + myBadElementAspectRatio->RangeStepAndValidator(0, COORD_MAX, 1000, "length_precision"); + myMinSize->setText(""); + myMaxSize->setText(""); + myAngleMesh->setText(""); + myChordalError->setText(""); + myAnisotropicRatio->setText(""); + myTinyEdgeLength->setText(""); + myBadElementAspectRatio->setText(""); +} + +BLSURFPluginGUI_StdWidget::~BLSURFPluginGUI_StdWidget() +{ +} + +void BLSURFPluginGUI_StdWidget::onPhysicalMeshChanged() { + bool isPhysicalGlobalSize = (myPhysicalMesh->currentIndex() == PhysicalGlobalSize); + bool isPhysicalLocalSize = (myPhysicalMesh->currentIndex() == PhysicalLocalSize); + bool isCustom = (isPhysicalGlobalSize || isPhysicalLocalSize) ; + bool geomIsCustom = (myGeometricMesh->currentIndex() != DefaultGeom); + + myGradation->setEnabled(!isPhysicalGlobalSize || geomIsCustom); + myPhySize->setEnabled(isCustom); + myPhySizeRel->setEnabled(isCustom); + + if ( !isCustom ) { + if ( myGeometricMesh->currentIndex() == DefaultGeom ) { + myGeometricMesh->setCurrentIndex( GeometricalGlobalSize ); + onGeometricMeshChanged(); + } + } +} + +void BLSURFPluginGUI_StdWidget::onGeometricMeshChanged() { + bool isCustom = (myGeometricMesh->currentIndex() != DefaultGeom); + bool isPhysicalLocalSize = (myPhysicalMesh->currentIndex() == PhysicalLocalSize); + + GeomParamsGroupBox->setEnabled(isCustom); + myGradation->setEnabled(isCustom || isPhysicalLocalSize); + + if ( ! isCustom ) { + // hphy_flag = 0 and hgeo_flag = 0 is not allowed (spec) + if ( myPhysicalMesh->currentIndex() == DefaultSize ) { + myPhysicalMesh->setCurrentIndex( PhysicalGlobalSize ); + onPhysicalMeshChanged(); + } + } +} + +void BLSURFPluginGUI_StdWidget::resizeWidgets() { + // Set minimum width of spin boxes + // Main parameters + QFontMetrics metrics1( myPhySize->font() ); + QFontMetrics metrics2( myMinSize->font() ); + QFontMetrics metrics3( myMaxSize->font() ); + int width1 = metrics1.width(myPhySize->GetString()); + int width2 = metrics2.width(myMinSize->GetString()); + int width3 = metrics3.width(myMaxSize->GetString()); + int max_width = max(width1,width2); + max_width = max(max_width, width3); + myPhySize->setMinimumWidth( max_width+50 ); + myMinSize->setMinimumWidth( max_width+50 ); + myMaxSize->setMinimumWidth( max_width+50 ); + // Geometrical parameters + metrics1 = myAngleMesh->font(); + metrics2 = myChordalError->font(); + width1 = metrics1.width(myAngleMesh->GetString()); + width2 = metrics2.width(myChordalError->GetString()); + max_width = max(width1,width2); + myAngleMesh->setMinimumWidth( max_width+50 ); + myChordalError->setMinimumWidth( max_width+50 ); + // Other parameters + metrics1 = myAnisotropicRatio->font(); + metrics2 = myTinyEdgeLength->font(); + metrics3 = myBadElementAspectRatio->font(); + width1 = metrics1.width(myAnisotropicRatio->GetString()); + width2 = metrics2.width(myTinyEdgeLength->GetString()); + width3 = metrics3.width(myBadElementAspectRatio->GetString()); + max_width = max(width1,width2); + max_width = max(max_width, width3); + myAnisotropicRatio->setMinimumWidth( max_width+50 ); + myTinyEdgeLength->setMinimumWidth( max_width+50 ); + myBadElementAspectRatio->setMinimumWidth( max_width+50 ); +} + +void BLSURFPluginGUI_StdWidget::onEditingFinished() { + SMESHGUI_SpinBox* spinBox = (SMESHGUI_SpinBox*)sender(); + bool isEmpty = spinBox->editor()->text().isEmpty(); + if ( isEmpty ) { + spinBox->SetValue(-1); + spinBox->setText(""); + } +} + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/GUI/BLSURFPluginGUI_StdWidget_QTD.ui b/src/GUI/BLSURFPluginGUI_StdWidget_QTD.ui new file mode 100644 index 0000000..9167973 --- /dev/null +++ b/src/GUI/BLSURFPluginGUI_StdWidget_QTD.ui @@ -0,0 +1,548 @@ + + + Gilles DAVID (OCC) + BLSURFPluginGUI_StdWidget_QTD + + + + 0 + 0 + 588 + 244 + + + + + 0 + + + + + BLSURF_MESH_TYPE + + + + + + BLSURF_PHY_MESH + + + + + + + BLSURF_PHY_MESH_TOOLTIP + + + 1 + + + + BLSURF_DEFAULT_USER + + + + + GLOBAL_SIZE + + + + + LOCAL_SIZE + + + + + + + + BLSURF_GEOM_MESH + + + + + + + BLSURF_GEOM_MESH_TOOLTIP + + + + BLSURF_DEFAULT_USER + + + + + GLOBAL_SIZE + + + + + + + + + + + false + + + BLSURF_GEOMETRICAL_PARAMETERS + + + + + + + + + + + + BLSURF_ANGLE_MESH_TOOLTIP + + + BLSURF_ANGLE_MESH + + + + + + + BLSURF_CHORDAL_TOOLTIP + + + BLSURF_CHORDAL_ERROR + + + + + + + + + + BLSURF_MAIN_PARAMETERS + + + + + + BLSURF_HPHYDEF_TOOLTIP + + + BLSURF_HPHYDEF + + + + + + + + + + BLSURF_SIZE_REL_TOOLTIP + + + BLSURF_SIZE_REL + + + + + + + + + + BLSURF_SIZE_REL_TOOLTIP + + + BLSURF_SIZE_REL + + + + + + + 10.000000000000000 + + + + + + + BLSURF_SIZE_REL_TOOLTIP + + + BLSURF_SIZE_REL + + + + + + + BLSURF_GRADATION_TOOLTIP + + + BLSURF_GRADATION + + + + + + + false + + + + + + + BLSURF_MINSIZE + + + + + + + BLSURF_MAXSIZE + + + + + + + BLSURF_ELEMENT_ORDER + + + + + + + + + + BLSURF_OTHER_PARAMETERS + + + + + + BLSURF_ANISOTROPIC_TOOLTIP + + + BLSURF_ANISOTROPIC + + + + + + + false + + + + + + + BLSURF_REMOVE_TINY_EDGES_TOOLTIP + + + BLSURF_REMOVE_TINY_EDGES + + + + + + + false + + + + + + + BLSURF_REMOVE_SLIVERS_TOOLTIP + + + BLSURF_REMOVE_SLIVERS + + + + + + + false + + + + + + + BLSURF_OPTIMISATION_TOOLTIP + + + BLSURF_OPTIMISATION + + + true + + + + + + + BLSURF_ALLOW_QUADRANGLES + + + + + + + + + + + SMESHGUI_SpinBox + QDoubleSpinBox +
SMESHGUI_SpinBox.h
+
+
+ + myPhysicalMesh + myGeometricMesh + myPhySize + myPhySizeRel + myMinSize + myMinSizeRel + myMaxSize + myMaxSizeRel + myGradation + myQuadraticMesh + myAngleMesh + myChordalError + myAnisotropic + myAnisotropicRatio + myRemoveTinyEdges + myTinyEdgeLength + myForceBadElementRemoval + myBadElementAspectRatio + myOptimizeMesh + myAllowQuadrangles + + + + + myGeometricMesh + activated(int) + BLSURFPluginGUI_StdWidget_QTD + onGeometricMeshChanged() + + + 188 + 60 + + + 281 + 243 + + + + + myPhysicalMesh + activated(int) + BLSURFPluginGUI_StdWidget_QTD + onPhysicalMeshChanged() + + + 188 + 37 + + + 218 + 243 + + + + + myAnisotropic + toggled(bool) + myAnisotropicRatio + setEnabled(bool) + + + 384 + 122 + + + 541 + 127 + + + + + myRemoveTinyEdges + toggled(bool) + myTinyEdgeLength + setEnabled(bool) + + + 414 + 151 + + + 547 + 152 + + + + + myForceBadElementRemoval + toggled(bool) + myBadElementAspectRatio + setEnabled(bool) + + + 448 + 181 + + + 542 + 180 + + + + + myAnisotropic + toggled(bool) + myChordalError + setDisabled(bool) + + + 441 + 119 + + + 525 + 60 + + + + + myAnisotropic + toggled(bool) + label_8 + setDisabled(bool) + + + 425 + 121 + + + 438 + 64 + + + + + myPhySize + editingFinished() + BLSURFPluginGUI_StdWidget_QTD + onEditingFinished() + + + 159 + 119 + + + 220 + 90 + + + + + myMinSize + editingFinished() + BLSURFPluginGUI_StdWidget_QTD + onEditingFinished() + + + 144 + 150 + + + 205 + 83 + + + + + myMaxSize + editingFinished() + BLSURFPluginGUI_StdWidget_QTD + onEditingFinished() + + + 128 + 176 + + + 135 + 83 + + + + + myGradation + editingFinished() + BLSURFPluginGUI_StdWidget_QTD + onEditingFinished() + + + 170 + 201 + + + 315 + 121 + + + + + myAngleMesh + editingFinished() + BLSURFPluginGUI_StdWidget_QTD + onEditingFinished() + + + 548 + 34 + + + 566 + 86 + + + + + myChordalError + editingFinished() + BLSURFPluginGUI_StdWidget_QTD + onEditingFinished() + + + 542 + 56 + + + 537 + 86 + + + + + + onGeometricMeshChanged() + onPhysicalMeshChanged() + onEditingFinished() + +
diff --git a/src/GUI/BLSURFPlugin_msg_en.ts b/src/GUI/BLSURFPlugin_msg_en.ts index e533c0a..767eb12 100644 --- a/src/GUI/BLSURFPlugin_msg_en.ts +++ b/src/GUI/BLSURFPlugin_msg_en.ts @@ -4,76 +4,159 @@ @default - ADD_OPTION - Add option + BLSURF_MESH_TYPE + Type of mesh - BLSURF_ALLOW_QUADRANGLES - Allow Quadrangles (Test) + BLSURF_PHY_MESH + Physical Mesh - BLSURF_ANGLE_MESH_C - Angle Mesh C + BLSURF_PHY_MESH_TOOLTIP + <b><u>Physical size mode</u></b><br><br> +- "Global size": the physical size is global and the mesher will use the global physical size provided.<br> +- "Local size": the size is locally computed, on curves and surfaces, using the associated physical sizemap functions.<br> +- "None": no physical size will be computed. - BLSURF_ANGLE_MESH_S - Angle Mesh S + BLSURF_GEOM_MESH + Geometrical Mesh - BLSURF_CUSTOM_GEOM - Custom + BLSURF_GEOM_MESH_TOOLTIP + <b><u>Geometric size mode</u></b><br><br> +- "Global size": the geometrical size is global and the mesher will use the geometrical approximation provided by the geometrical parameters..<br> +- "None": no geometrical sizes will be computed. - BLSURF_CUSTOM_USER - Custom + BLSURF_DEFAULT_USER + None - BLSURF_DECIMESH - Patch independent + GLOBAL_SIZE + Global size - BLSURF_DEFAULT_GEOM - None + LOCAL_SIZE + Local size - BLSURF_DEFAULT_USER - None + BLSURF_MAIN_PARAMETERS + Main parameters - BLSURF_GEOM_MESH - Geometrical Mesh + BLSURF_HPHYDEF + User Size + + + BLSURF_HPHYDEF_TOOLTIP + Defines the constant global size.<br> +The default computed value is <em>diag</em>/<em>ratio</em>, where <em>ratio</em> is defined in the preferences. + + + BLSURF_MINSIZE + Min Size + + + BLSURF_MINSIZE_TOOLTIP + Defines the global minimum cell size desired.<br> +The default computed value is <em>diag</em>/1000. + + + BLSURF_MAXSIZE + Max Size + + + BLSURF_MAXSIZE_TOOLTIP + Defines the global maximum cell size desired.<br> +The default computed value is <em>diag</em>/5. + + + BLSURF_SIZE_REL + Relative value + + + BLSURF_SIZE_REL_TOOLTIP + The value is relative to <em>diag</em> BLSURF_GRADATION Gradation - BLSURF_HGEOMAX - Max Geometrical Size + BLSURF_GRADATION_TOOLTIP + Maximum ratio between the lengths of two adjacent edges. - BLSURF_HGEOMIN - Min Geometrical Size + BLSURF_ALLOW_QUADRANGLES + Allow Quadrangles - BLSURF_HPHYDEF - User Size + BLSURF_GEOMETRICAL_PARAMETERS + Geometrical parameters - BLSURF_HPHYMAX - Max Physical Size + BLSURF_ANGLE_MESH + Mesh angle - BLSURF_HPHYMIN - Min Physical Size + BLSURF_ANGLE_MESH_TOOLTIP + Limiting angle between the plane of a triangle of the mesh and each of the tangent planes at the three vertices.<br> +The smaller this angle is, the closer the mesh is to the exact surface, and the denser the resulting mesh is. - BLSURF_HYPOTHESIS - BLSURF 2D + BLSURF_CHORDAL_ERROR + Mesh distance - BLSURF_PHY_MESH - Physical Mesh + BLSURF_CHORDAL_TOOLTIP + Maximum desired distance between a triangle and its supporting CAD surface.<br> +The smaller this distance is, the closer the mesh is to the exact surface (only available in isotropic meshing). + + + BLSURF_OTHER_PARAMETERS + Other parameters + + + BLSURF_ANISOTROPIC + Anisotropic + + + BLSURF_ANISOTROPIC_TOOLTIP + If checked, this parameter defines the maximum anisotropic ratio of the metric governing the anisotropic meshing process.<br> + The default value of 0 means that the metric (and thus the generated elements) can be arbitrarily stretched. + + + BLSURF_REMOVE_TINY_EDGES + Remove tiny edges + + + BLSURF_REMOVE_TINY_EDGES_TOOLTIP + If checked, this parameter defines the minimal length under which an edge is considered to be a tiny one. + + + BLSURF_REMOVE_SLIVERS + Remove bad elements + + + BLSURF_REMOVE_SLIVERS_TOOLTIP + If checked, this parameter defines the aspect ratio triggering the "bad element” classification. + + + BLSURF_OPTIMISATION + Mesh optimisation + + + BLSURF_OPTIMISATION_TOOLTIP + If checked, MeshGems-CADSurf will optimize the mesh in order to get better shaped elements. + + + BLSURF_ELEMENT_ORDER + Quadratic mesh + + + BLSURF_HYPOTHESIS + BLSURF 2D BLSURF_ADV_ARGS @@ -109,7 +192,7 @@ OBLIGATORY_VALUE - (Obligatory value) + (Mandatory value) OPTION_TYPE_COLUMN @@ -132,7 +215,11 @@ PreCAD - REMOVE_OPTION + BLSURF_ADD_OPTION + Add option + + + BLSURF_REMOVE_OPTION Clear option @@ -160,21 +247,13 @@ Merge edges - BLSURF_PRECAD_REMOVE_NANO_EDGES - Remove nano edges + BLSURF_PRECAD_PROCESS_3D_TOPOLOGY + Process 3D topology BLSURF_PRECAD_DISCARD_INPUT Discard input topology - - BLSURF_PRECAD_EPS_NANO - Nano edge length - - - BLSURF_SIZE_MAP - Local Size - SMP_ENTRY_COLUMN Entry diff --git a/src/GUI/BLSURFPlugin_msg_fr.ts b/src/GUI/BLSURFPlugin_msg_fr.ts index 6a8bde3..fbe4538 100755 --- a/src/GUI/BLSURFPlugin_msg_fr.ts +++ b/src/GUI/BLSURFPlugin_msg_fr.ts @@ -4,76 +4,159 @@ @default - ADD_OPTION - Ajouter l'option + BLSURF_MESH_TYPE + Type de maillage - BLSURF_ALLOW_QUADRANGLES - Autoriser les quadrangles (Test) + BLSURF_PHY_MESH + Maillage physique - BLSURF_ANGLE_MESH_C - Angle de maillage C + BLSURF_PHY_MESH_TOOLTIP + <b><u>Mode de taille physique</u></b><br><br> +- "Taille globale": la taille physique est globale et le mailleur utilisera la taille physique globale fournie.<br> +- "Taille locale": la taille est localement calculée sur les courbes et surfaces en utilisant les fonctions de carte de taille associées.<br> +- "Inactive": aucune taille physique ne sera calculée. - BLSURF_ANGLE_MESH_S - Angle de maillage S + BLSURF_GEOM_MESH + Maillage géométrique - BLSURF_CUSTOM_GEOM - Personnalisé + BLSURF_GEOM_MESH_TOOLTIP + <b><u>Mode de taille géométrique</u></b><br><br> +- "Taille globale": la taille géométrique est globale et le mailleur utilisera l'approximation géométrique fournie par les paramètres géométriques.<br> +- "Inactive": aucune taille géométrique ne sera calculée. - BLSURF_CUSTOM_USER - Personnalisé + BLSURF_DEFAULT_USER + Inactif - BLSURF_DECIMESH - S'affranchir des frontières des surfaces + GLOBAL_SIZE + Taille globale - BLSURF_DEFAULT_GEOM - Inactif + LOCAL_SIZE + Taille locale - BLSURF_DEFAULT_USER - Inactif + BLSURF_MAIN_PARAMETERS + Paramètres principaux - BLSURF_GEOM_MESH - Maillage géométrique + BLSURF_HPHYDEF + Taille d'utilisateur + + + BLSURF_HPHYDEF_TOOLTIP + Défini la taille globale constante pour le maillage physique.<br> +La valeur par défaut est calculée par <em>diag</em>/<em>ratio</em>, où <em>ratio</em> est défini dans les préférences. + + + BLSURF_MINSIZE + Taille minimale + + + BLSURF_MINSIZE_TOOLTIP + Défini la taille globale minimum de cellule désirée.<br> +La valeur par défaut est calculée par <em>diag</em>/1000. + + + BLSURF_MAXSIZE + Taille maximale + + + BLSURF_MAXSIZE_TOOLTIP + Défini la taille globale maximum de cellule désirée.<br> +La valeur par défaut est calculée par <em>diag</em>/5. + + + BLSURF_SIZE_REL + Valeur relative + + + BLSURF_SIZE_REL_TOOLTIP + La valeur est relative à <em>diag</em> BLSURF_GRADATION Taux d'accroissement - BLSURF_HGEOMAX - Taille géométrique maximale + BLSURF_GRADATION_TOOLTIP + Ratio maximum entre les longueurs de deux segments adjacents. - BLSURF_HGEOMIN - Taille géométrique minimale + BLSURF_ALLOW_QUADRANGLES + Autoriser les quadrangles - BLSURF_HPHYDEF - Taille d'utilisateur + BLSURF_GEOMETRICAL_PARAMETERS + Paramètres géometriques - BLSURF_HPHYMAX - Taille physique maximale + BLSURF_ANGLE_MESH + Angle de maillage - BLSURF_HPHYMIN - Taille physique minimale + BLSURF_ANGLE_MESH_TOOLTIP + Limite d'angle entre le plan d'un triangle du maillage et chacun des plans tangents aux sommets.<br> +Plus l'angle est petit, plus le maillage sera dense et proche de la géométrie. - BLSURF_HYPOTHESIS - BLSURF 2D + BLSURF_CHORDAL_ERROR + Distance du maillage - BLSURF_PHY_MESH - Maillage physique + BLSURF_CHORDAL_TOOLTIP + Distance maximum désirée entre un triangle et sa surface CAO.<br> +Plus la distance est petite, plus le maillage sera proche de la surface (disponible en mode isotrope seulement). + + + BLSURF_OTHER_PARAMETERS + Autres paramètres + + + BLSURF_ANISOTROPIC + Anisotropie + + + BLSURF_ANISOTROPIC_TOOLTIP + Si activé, ce paramètre défini le ratio d'anisotropie maximum de la métrique pilotant de processus de maillage anisotropique.<br> + La valeur par défaut de 0 signifie que la métrique (et donc les éléments générés) peut être étirée arbitrairement. + + + BLSURF_REMOVE_TINY_EDGES + Enlever les petites arêtes + + + BLSURF_REMOVE_TINY_EDGES_TOOLTIP + Si activé, ce paramètre défini la longueur minimale sous laquelle une arête est considérée comme toute petite. + + + BLSURF_REMOVE_SLIVERS + Enlever les mauvais éléments + + + BLSURF_REMOVE_SLIVERS_TOOLTIP + Si activé, ce paramètre défini les proportions déclenchants la classification des "mauvais éléments”. + + + BLSURF_OPTIMISATION + Optimisation du maillage + + + BLSURF_OPTIMISATION_TOOLTIP + Si activé, MeshGems-CADSurf optimisera le maillage pour obtenir des éléments de meilleurs qualité. + + + BLSURF_ELEMENT_ORDER + Maillage quadratique + + + BLSURF_HYPOTHESIS + BLSURF 2D BLSURF_ADV_ARGS @@ -132,7 +215,11 @@ PreCAD - REMOVE_OPTION + BLSURF_ADD_OPTION + Ajouter l'option + + + BLSURF_REMOVE_OPTION Effacer l'option @@ -160,21 +247,13 @@ Fusionner des arêtes - BLSURF_PRECAD_REMOVE_NANO_EDGES - Supprimer les petites arêtes + BLSURF_PRECAD_PROCESS_3D_TOPOLOGY + Nettoyer la CAO BLSURF_PRECAD_DISCARD_INPUT Ignorer la topologie - - BLSURF_PRECAD_EPS_NANO - Longueur max des petites arêtes - - - BLSURF_SIZE_MAP - Tailles locales - SMP_ENTRY_COLUMN Entrée diff --git a/src/GUI/Makefile.am b/src/GUI/Makefile.am index 8f0b6a0..bb88c89 100644 --- a/src/GUI/Makefile.am +++ b/src/GUI/Makefile.am @@ -26,6 +26,7 @@ include $(top_srcdir)/adm_local/unix/make_common_starter.am # header files salomeinclude_HEADERS = \ + BLSURFPluginGUI_Dlg.h \ BLSURFPluginGUI_HypothesisCreator.h # Libraries targets @@ -33,10 +34,19 @@ lib_LTLIBRARIES = libBLSURFPluginGUI.la dist_libBLSURFPluginGUI_la_SOURCES = \ BLSURFPluginGUI.cxx \ + BLSURFPluginGUI_StdWidget.cxx \ + BLSURFPluginGUI_AdvWidget.cxx \ BLSURFPluginGUI_HypothesisCreator.cxx MOC_FILES = \ - BLSURFPluginGUI_HypothesisCreator_moc.cxx + BLSURFPluginGUI_HypothesisCreator_moc.cxx \ + BLSURFPluginGUI_Dlg_moc.cxx + +UIC_FILES = \ + ui_BLSURFPluginGUI_StdWidget_QTD.h \ + ui_BLSURFPluginGUI_AdvWidget_QTD.h + +BUILT_SOURCES = $(UIC_FILES) nodist_libBLSURFPluginGUI_la_SOURCES = \ $(MOC_FILES) @@ -56,17 +66,17 @@ libBLSURFPluginGUI_la_CPPFLAGS = \ $(BOOST_CPPFLAGS) \ $(CORBA_CXXFLAGS) \ $(CORBA_INCLUDES) \ - $(BLSURF_INCLUDES) \ + $(MESHGEMS_CADSURF_INCLUDES) \ -I$(srcdir)/../BLSURFPlugin \ -I$(top_builddir)/idl libBLSURFPluginGUI_la_LDFLAGS = \ - $(QT_LIBS) \ + $(QT_LIBS) $(QT_MT_LIBS)\ ../BLSURFPlugin/libBLSURFEngine.la \ $(GUI_LDFLAGS) -lqtx -lSalomeApp -lsuit -lSalomeObject -lLightApp \ $(GEOM_LDFLAGS) -lGEOM \ ${SMESH_LDFLAGS} -lSMESH -lGeomSelectionTools -lStdMeshersGUI -lSMESHFiltersSelection \ - $(CAS_KERNEL) $(BLSURF_LIBS) + $(CAS_KERNEL) $(MESHGEMS_CADSURF_LIBS) # resources files nodist_salomeres_DATA = \ -- 2.39.2