From 856524def1094611dfd996d00a5226cee4b0c3cf Mon Sep 17 00:00:00 2001 From: jfa Date: Tue, 21 Aug 2007 08:30:33 +0000 Subject: [PATCH] Join modifications from V3_2_0_maintainance (V3_2_6pre4 - T32x_16Aug2007_16h00m) --- adm_local/unix/config_files/check_SMESH.m4 | 8 +- build_configure | 43 +- configure.ac | 133 ++--- idl/SMESH_Gen.idl | 1 - resources/StdMeshers.xml | 1 + resources/mesh_tree_mesh_partial.png | Bin 313 -> 27767 bytes src/DriverMED/DriverMED_R_SMESHDS_Mesh.cxx | 15 +- src/DriverUNV/UNV2417_Structure.cxx | 10 +- src/Makefile.am | 13 +- src/SMDS/SMDS_Mesh.cxx | 48 +- src/SMDS/SMDS_Mesh.hxx | 7 + src/SMDS/SMESH_SMDS.hxx | 2 +- src/SMESH/SMESH_Algo.hxx | 15 +- src/SMESH/SMESH_Block.cxx | 357 ++++++++----- src/SMESH/SMESH_Block.hxx | 26 +- src/SMESH/SMESH_Gen.cxx | 6 +- src/SMESH/SMESH_HypoFilter.hxx | 8 +- src/SMESH/SMESH_Mesh.cxx | 286 +--------- src/SMESH/SMESH_Mesh.hxx | 30 +- src/SMESH/SMESH_MeshEditor.cxx | 36 +- src/SMESH/SMESH_MesherHelper.cxx | 18 +- src/SMESH/SMESH_MesherHelper.hxx | 12 +- src/SMESH/SMESH_Pattern.cxx | 189 ++++++- src/SMESH/SMESH_Pattern.hxx | 12 +- src/SMESH/SMESH_subMesh.cxx | 258 ++++----- src/SMESHDS/SMESHDS_SubMesh.hxx | 1 + src/SMESHDS/SMESH_SMESHDS.hxx | 2 +- src/SMESHGUI/SMESHGUI.cxx | 15 +- src/SMESHGUI/SMESHGUI_ComputeDlg.cxx | 140 +++-- src/SMESHGUI/SMESHGUI_ComputeDlg.h | 1 + src/SMESHGUI/SMESHGUI_FilterDlg.cxx | 3 +- src/SMESHGUI/SMESHGUI_Hypotheses.cxx | 57 +- src/SMESHGUI/SMESHGUI_Hypotheses.h | 25 +- src/SMESHGUI/SMESHGUI_HypothesesUtils.cxx | 28 +- src/SMESHGUI/SMESHGUI_MakeNodeAtPointDlg.cxx | 12 +- src/SMESHGUI/SMESHGUI_MeshOp.cxx | 138 +++-- src/SMESHGUI/SMESHGUI_MeshOp.h | 23 +- src/SMESHGUI/SMESHGUI_MoveNodesDlg.cxx | 12 +- src/SMESHGUI/SMESHGUI_NodesDlg.cxx | 14 +- src/SMESHGUI/SMESHGUI_SpinBox.h | 1 + src/SMESHGUI/SMESHGUI_TranslationDlg.cxx | 12 +- src/SMESHGUI/SMESH_msg_en.po | 6 + src/SMESH_I/SMESH_2smeshpy.cxx | 341 ++++++++---- src/SMESH_I/SMESH_2smeshpy.hxx | 122 +++-- src/SMESH_I/SMESH_Filter_i.cxx | 60 ++- src/SMESH_I/SMESH_Gen_i.cxx | 25 +- src/SMESH_I/SMESH_Gen_i_1.cxx | 1 + src/SMESH_I/SMESH_Mesh_i.cxx | 137 ++++- src/SMESH_I/SMESH_Mesh_i.hxx | 10 +- src/SMESH_I/SMESH_Pattern_i.cxx | 23 +- src/SMESH_I/SMESH_PythonDump.hxx | 38 +- src/SMESH_I/SMESH_subMesh_i.cxx | 8 +- src/SMESH_I/SMESH_subMesh_i.hxx | 4 + src/SMESH_SWIG/Makefile.am | 83 --- src/SMESH_SWIG/smeshDC.py | 496 ++++++++++++----- src/SMESH_SWIG_WITHIHM/Makefile.am | 115 ++++ .../libSMESH_Swig.i | 0 .../StdMeshers_CompositeSegment_1D.cxx | 3 +- src/StdMeshers/StdMeshers_FaceSide.cxx | 49 ++ src/StdMeshers/StdMeshers_FaceSide.hxx | 18 +- src/StdMeshers/StdMeshers_Hexa_3D.cxx | 17 +- src/StdMeshers/StdMeshers_Hexa_3D.hxx | 2 +- src/StdMeshers/StdMeshers_MEFISTO_2D.cxx | 58 +- src/StdMeshers/StdMeshers_Prism_3D.cxx | 148 ++++-- src/StdMeshers/StdMeshers_Prism_3D.hxx | 4 +- src/StdMeshers/StdMeshers_ProjectionUtils.cxx | 185 ++++--- src/StdMeshers/StdMeshers_ProjectionUtils.hxx | 8 +- src/StdMeshers/StdMeshers_Projection_1D.cxx | 4 +- src/StdMeshers/StdMeshers_Projection_2D.cxx | 33 +- src/StdMeshers/StdMeshers_Projection_3D.cxx | 25 +- src/StdMeshers/StdMeshers_Propagation.cxx | 498 ++++++++++++------ src/StdMeshers/StdMeshers_Propagation.hxx | 2 +- .../StdMeshers_QuadranglePreference.cxx | 2 +- src/StdMeshers/StdMeshers_Quadrangle_2D.cxx | 42 +- src/StdMeshers/StdMeshers_Quadrangle_2D.hxx | 21 +- src/StdMeshers/StdMeshers_RadialPrism_3D.cxx | 33 +- src/StdMeshers/StdMeshers_Regular_1D.cxx | 34 +- ...tdMeshersGUI_LayerDistributionParamWdg.cxx | 10 +- .../StdMeshersGUI_LayerDistributionParamWdg.h | 4 +- .../StdMeshersGUI_NbSegmentsCreator.cxx | 3 +- .../StdMeshersGUI_StdHypothesisCreator.cxx | 4 +- 81 files changed, 2951 insertions(+), 1743 deletions(-) create mode 100644 src/SMESH_SWIG_WITHIHM/Makefile.am rename src/{SMESH_SWIG => SMESH_SWIG_WITHIHM}/libSMESH_Swig.i (100%) diff --git a/adm_local/unix/config_files/check_SMESH.m4 b/adm_local/unix/config_files/check_SMESH.m4 index f1dbf22f1..5518cfa24 100644 --- a/adm_local/unix/config_files/check_SMESH.m4 +++ b/adm_local/unix/config_files/check_SMESH.m4 @@ -28,7 +28,9 @@ if test "x$SMESH_DIR" == "x" ; then else # search SMESH binaries in PATH variable - AC_PATH_PROG(TEMP, libSMESH_Swig.py) + #CCRTAC_PATH_PROG(TEMP, libSMESH_Swig.py) + #AC_PATH_PROG(TEMP, MED_Test) + AC_PATH_PROG(TEMP, smesh.py) if test "x$TEMP" != "x" ; then SMESH_BIN_DIR=`dirname $TEMP` SMESH_DIR=`dirname $SMESH_BIN_DIR` @@ -38,7 +40,9 @@ if test "x$SMESH_DIR" == "x" ; then # fi -if test -f ${SMESH_DIR}/bin/salome/libSMESH_Swig.py ; then +#CCRTif test -f ${SMESH_DIR}/bin/salome/libSMESH_Swig.py ; then +#if test -f ${SMESH_DIR}/bin/salome/MED_Test ; then +if test -f ${SMESH_DIR}/bin/salome/smesh.py ; then SMesh_ok=yes AC_MSG_RESULT(Using SMesh module distribution in ${SMESH_DIR}) diff --git a/build_configure b/build_configure index 7f3e6a42e..66f991e57 100755 --- a/build_configure +++ b/build_configure @@ -12,6 +12,7 @@ ORIG_DIR=`pwd` CONF_DIR=`echo $0 | sed -e "s,[^/]*$,,;s,/$,,;s,^$,.,"` +SMESH_WITH_GUI="yes" ######################################################################## # Test if the KERNEL_ROOT_DIR is set correctly @@ -28,12 +29,26 @@ fi # exit #fi +for option +do + case $option in + -with-ihm | --with-ihm) + SMESH_WITH_GUI="yes" + break;; + -without-ihm | --without-ihm | -with-ihm=no | --with-ihm=no) + SMESH_WITH_GUI="no" + break;; + esac +done + ######################################################################## # Test if the GUI_ROOT_DIR is set correctly -if test ! -d "${GUI_ROOT_DIR}"; then - echo "failed : GUI_ROOT_DIR variable is not correct !" - exit +if test ${SMESH_WITH_GUI} = yes; then + if test ! -d "${GUI_ROOT_DIR}"; then + echo "failed : GUI_ROOT_DIR variable is not correct !" + exit + fi fi ######################################################################## @@ -56,6 +71,11 @@ fi cd ${CONF_DIR} ABS_CONF_DIR=`pwd` +####################################################################### +# Update configure.ac script: to set SMESH_WITH_GUI variable +sed -e s/SMESH_WITH_GUI=[a-z]*/SMESH_WITH_GUI=${SMESH_WITH_GUI}/g configure.ac > configure.tmp +mv -f configure.tmp configure.ac + mkdir -p salome_adm/unix/config_files #cp -f ${KERNEL_ROOT_DIR}/salome_adm/unix/config_files/* salome_adm/unix/config_files #cp -f ${KERNEL_ROOT_DIR}/salome_adm/unix/pythonbe.py salome_adm/unix @@ -84,11 +104,18 @@ cp -f ${KERNEL_ROOT_DIR}/salome_adm/unix/SALOMEconfig.h.in salome_adm/unix # autom4te.cache (directory) echo "====================================================== aclocal" -aclocal -I adm_local/unix/config_files \ - -I ${KERNEL_ROOT_DIR}/salome_adm/unix/config_files \ - -I ${GUI_ROOT_DIR}/adm_local/unix/config_files \ - -I ${MED_ROOT_DIR}/adm_local/unix/config_files \ - -I ${GEOM_ROOT_DIR}/adm_local/unix/config_files || exit 1 +if test ${SMESH_WITH_GUI} = yes; then + aclocal -I adm_local/unix/config_files \ + -I ${KERNEL_ROOT_DIR}/salome_adm/unix/config_files \ + -I ${GUI_ROOT_DIR}/adm_local/unix/config_files \ + -I ${MED_ROOT_DIR}/adm_local/unix/config_files \ + -I ${GEOM_ROOT_DIR}/adm_local/unix/config_files || exit 1 +else + aclocal -I adm_local/unix/config_files \ + -I ${KERNEL_ROOT_DIR}/salome_adm/unix/config_files \ + -I ${MED_ROOT_DIR}/adm_local/unix/config_files \ + -I ${GEOM_ROOT_DIR}/adm_local/unix/config_files || exit 1 +fi # ____________________________________________________________________ # libtoolize creates some configuration files (ltmain.sh, diff --git a/configure.ac b/configure.ac index b2799afe1..c267da8db 100644 --- a/configure.ac +++ b/configure.ac @@ -194,14 +194,22 @@ echo ENABLE_PTHREADS -if test "x${GUI_DISABLE_CORBA}" != "xyes" ; then echo echo --------------------------------------------- -echo testing omniORB +echo testing msg2qm echo --------------------------------------------- echo -CHECK_OMNIORB +CHECK_MSG2QM + +if test "x${GUI_DISABLE_CORBA}" != "xyes" ; then + echo + echo --------------------------------------------- + echo testing omniORB + echo --------------------------------------------- + echo + + CHECK_OMNIORB dnl echo dnl echo --------------------------------------------- @@ -211,58 +219,78 @@ dnl echo dnl CHECK_MICO -echo -echo --------------------------------------------- -echo default ORB : omniORB -echo --------------------------------------------- -echo + echo + echo --------------------------------------------- + echo default ORB : omniORB + echo --------------------------------------------- + echo -DEFAULT_ORB=omniORB + DEFAULT_ORB=omniORB -echo -echo --------------------------------------------- -echo testing Corba -echo --------------------------------------------- -echo + echo + echo --------------------------------------------- + echo testing Corba + echo --------------------------------------------- + echo -CHECK_CORBA + CHECK_CORBA -AC_SUBST_FILE(CORBA) -corba=make_$ORB -CORBA=adm_local/unix/$corba + AC_SUBST_FILE(CORBA) + corba=make_$ORB + CORBA=adm_local/unix/$corba fi -echo -echo --------------------------------------------- -echo testing openGL -echo --------------------------------------------- -echo -CHECK_OPENGL -echo -echo --------------------------------------------- -echo testing QT -echo --------------------------------------------- -echo +SMESH_WITH_GUI=yes -CHECK_QT +AM_CONDITIONAL(SMESH_ENABLE_GUI, [test "${SMESH_WITH_GUI}" = "yes"]) -echo -echo --------------------------------------------- -echo testing msg2qm -echo --------------------------------------------- -echo +if test "${SMESH_WITH_GUI}" = "yes"; then + echo + echo --------------------------------------------- + echo testing openGL + echo --------------------------------------------- + echo -CHECK_MSG2QM + CHECK_OPENGL -echo -echo --------------------------------------------- -echo testing VTK -echo --------------------------------------------- -echo + echo + echo --------------------------------------------- + echo testing QT + echo --------------------------------------------- + echo + + CHECK_QT -CHECK_VTK + echo + echo --------------------------------------------- + echo testing VTK + echo --------------------------------------------- + echo + + CHECK_VTK + + echo + echo --------------------------------------------- + echo Testing GUI + echo --------------------------------------------- + echo + + CHECK_SALOME_GUI + + echo + echo --------------------------------------------- + echo Testing full GUI + echo --------------------------------------------- + echo + + CHECK_CORBA_IN_GUI + if test "x${CORBA_IN_GUI}" != "xyes"; then + echo "failed : For configure SMESH module necessary full GUI !" + exit + fi +fi echo echo --------------------------------------------- @@ -304,26 +332,6 @@ echo CHECK_HTML_GENERATORS -echo -echo --------------------------------------------- -echo Testing GUI -echo --------------------------------------------- -echo - -CHECK_SALOME_GUI - -echo -echo --------------------------------------------- -echo Testing full GUI -echo --------------------------------------------- -echo - -CHECK_CORBA_IN_GUI -if test "x${CORBA_IN_GUI}" != "xyes"; then - echo "failed : For configure SMESH module necessary full GUI !" - exit -fi - echo echo --------------------------------------------- echo Testing Kernel @@ -458,6 +466,7 @@ AC_OUTPUT([ \ ./src/SMESHGUI/Makefile \ ./src/SMESH_I/Makefile \ ./src/SMESH_SWIG/Makefile \ + ./src/SMESH_SWIG_WITHIHM/Makefile \ ./src/StdMeshers/Makefile \ ./src/StdMeshersGUI/Makefile \ ./src/StdMeshers_I/Makefile \ diff --git a/idl/SMESH_Gen.idl b/idl/SMESH_Gen.idl index ba4d798d6..4f81e6e51 100644 --- a/idl/SMESH_Gen.idl +++ b/idl/SMESH_Gen.idl @@ -82,7 +82,6 @@ module SMESH interface SMESH_Gen : Engines::Component, SALOMEDS::Driver { - //GEOM::GEOM_Gen SetGeomEngine( in string containerLoc ); void SetGeomEngine( in GEOM::GEOM_Gen geomcompo ); diff --git a/resources/StdMeshers.xml b/resources/StdMeshers.xml index 9b1a1dfaf..70530de01 100644 --- a/resources/StdMeshers.xml +++ b/resources/StdMeshers.xml @@ -60,6 +60,7 @@ +qjU{;K3f>gCBN zUW$fZIb6r-f!>xZQ$7olk{@mW|54_7?sL^Ec4u-)mwi`8AQF* ze%5sVljq}ei4|Odg-CE&iem(gKWQeoDajc$sYL5 zLfz2`h+MptBXWn#a1Y#Vx6PP(w!ORu0kZ&yRa^Vh&zzz1qzin_45{;og<9_a6NraF z%)yPj$~(Gdzr#bp`GS+Bpy!9k9Zf*776r)|Pzc#!m~H{*OzjNzwY`Jv4EI_54ydU* z#2KbLoDxH3)|0T5)U_4>a{iMWtqtRsd{=RHe5G`;I6(YIP?!1t2zYZvf0B{0KXP`| z)wvXnnTh9|WaZ|_zEjUgknKmTZWe<#J*L!q(Ts~8E zX(eAtSX7(j!tId9FXJ9Nn0ScC@O^rH@8Ov@Hc~0)5u5CR=`bj)bbIIqWgDxeojxby zH2#y%Cxh_eR^w+uFclyXX}g zM^8VwiPj0FbXd!zbb3LSqs}lbmWFouj6yQ_O0U_TE>$&^v%*|t756L`s~1GcZEobL z*G(!0khnv5*8ZZGZDdwh*tXM^Ypj@#*rwZTH19LVN{9+=)jbSbs5Ik6YKup>JVT$wh^uwUEVg&b|{!q>hN zP3bsWL|*Yt{fcD$nG(`SUH$HgjJM0 z4x01ob_Th18ug>jwEI0b8dV;qQFA4RS_{WHT~A5g_AJ93H9KE&V)zY@{0UN z+BeidqLP;B(jn~3(%+lVQn5!Au}4q0mYGJ)Db0mKnU~aVz;B8&d;o@)kLpOb-C0h~ zqA0g{`iR{k@lN8_>@y7;!wwd37d<_DSbI2y>jsql?!#wioC3MueDkxy(+#k~vgM zeeWs@|A{vFB<)J4US&o-q|7=b@V1`zP-1eC+!TtrX@4wA=_Qc=onwVi=#x&B|0mME z^O>v?OJgZ}p69s^(g*TcWc{jH+^fm3xO-~FHX{5s9sHlnT3<@^Qa2{U<1*&sB1@3x z;NeJ!kr6C<$7Y-4Qjj2gEBxY` zpYvCPC(o$Q;$$J7-mWe2#pU%yO8b9*SYWNQEL(!K@OrXX1o*%QzfeuKp}KIe1^c{GON;=3o!}Gs9coPxoWswp*cA`v+*pn8q(n zu299Ys(9A-Wh{{Xtd*qA9{m|Vb#dF>XG6(fV#YK0LSuqW`eZlyoW8h`?@-(8;0Gi% z?b$LOKaOJ>KXLK#O9~mt;MFC2Ci6y-$lhHcU1%>ao@+_dM0YNz6VpGh>9+vSXx*9Q zhP@jdu$2cWYTDqVb%pDJ!Z+{ ze)GMtI$iYB*u(6~{b!n+-`3DPVGw&lv8>qu!?QHB^&d@)|g}X)*y`^#yN+<_m|-oe{8{6`uBEGO`E6>;^~#oY6l{v z>_7M)fhH4H)}v{P7+r)>J`IAwQC{zQG}RNRm)5IP0e2^(l66jB>ncdyzeBr-`Q;^y z(tYbpPR4HGg89W8w=4-&)_EGT$zbdNHF>6K`!!

A0~cu1CS1@wq5Bo!^9NWZj9d zNwn>%-HVCy`uF*qD@wF^hPv@?j^<%2vS$2ab9MJX>SeTESNGh*1R&Pg&GFIQ73??r z+XdU5L(N{2cZ*O_CfKe^Kyp;PqaN33^JlVcM?Hu6iSpcbPx1zxGCy4FP*072Ik@9^ zf6MK41RYbL@Q+EUCj&|CH(vAJA==R_#6RX)PXMBhZUzwJc6q-DYw?Af#7MoEi3Yb8 zeCGSrJ)d_LBVRwsy{SaHqNXL%vjpvWbYwQe$Kk~57J!qkWJ+O z1`Oc*%Y5ynQ)t3_F73DXcjNOd-jdxvc?FNIPky}dI`IaS|;SF@DuQlvhGm74dv1a_7RoRsDG^EOtllWf0^TyO6uX&&`&&@J%Q01u>N5S~7 z1b4eI z6!IvG2R_b*MSd>4;%d#U#QM|T#&p6IWiRsM&BR;CG^?Cio@20@2E>_t(*ES?FCQzH zKNRthu{4viJ~$8cDnOu>KSe7n`RnyOyqp;APPbm1yhfO0rJi)^3P$Bcl*b2Idyihq zrScE?Vk@20t=m*GKG$y2)EB^&z4ScJgqM9^#p0g$$64x$zZPQt{YDA>x45n0 zlS-ZqU$0>C!kZrSl|0TLvC%3w_gjtg^yG>%O(Yi3Opz$6TeU2{ENH(d`H1 z^YwapPLefO&MI#+zCrc+TnW(9=tx{82l#`2SktXMqyF{7-XG~5wBLLsRpz@BZmyKp z`px}BiZoaz+YRbO9sae8V5jN11M^|f(E-zq8&+3)eZMeCK_u9 zKo#;$34poU;=DS%_(Ls)`Z{V}kk9udoV6@9#uA zM0@s1A&XQ;Y!j*+`}HampN3N1V#&JM%w?i$;c2>@?pRU$;qPMs&hZAR5i3)k*N)OjcBk>ho*NM0|M zOulwh<mUegKuKi7!+a3xFLdD^=j9|$s zF`#2@i|ujA-Vi*N*<(S;e9~4^PhmfvzflN=D}EPMlltn1V|31p>1`)H*IA9G4=UH+ zD_(!jTo=ggUrC?ke74zT&%>?ls<#bHdfeBO)RgaG-Lktp>GqSCEXcoxtmUR#UC;r>&`wA zir~8#VObg1tQR`bcDi}94!1v9(p2+J2)>fu_NT$3CVq;u&i7SdaL+mZ#z*j|+{pr( z;}56wlThfN3TJ^IrTtrv*g8)modR^G7eFsXOKA4wJH4jWQjIEJ5WzZwbhDPsJr{?P zW3%jkt#F8Zd=rmR26(k~noAoS{A-^)=vp6iYQvjokl~;qJvT~yHX){iySa#SySlVe zAsi&(MHMTy5~B&GF`M~pKrymh@Z23yBQ+H=Y=@>lXCwXC{=$c_GHA^W1bx5KgkeEx zukJ)v6f54FWMYx~C9N?WzvHA(yqr9Wy)}M4kcW5TVU8Bj-wg0_ur-E=Dt^9 z7H>NaNl*|v!|G@{{7TV_-UFyjPi1!bl?Kd`$cW^K%yl}zua@>U_g4yztOYx;mq7rG zokQs74Z#_!V5*lWEteI!n!`|&nj%ug>^qGValzPaUR^OOfY!_l+~lLtd+!+_PA+3r z1!5gf%!s$SgvW`0N-`0I2cYQqjFbDEUMe3Mtbu|Ki;DR{a`Y@BXGwNx%zOyb=#K+F z8U~L)q%7|QWEN9)B^`W(mib>4FFO=$Zl@QtJ%m1xJ7uX1k#IXmFLo>=O4rX8H8gJS z2t^emCQM7y#7q!Q1ikVavnuc5DT_NMU|8O-Nj&IH&*(JVbP{D&g+;V4+72&@1%O|o z1XdqYY{?9ei?wa;q!+hcFLU{8YUX*$&^2jUdbe$j_QK@EYk0!qn$}>6_CK{^q(ive zLIWOvF_E^QG++@kSRyYgJHdV|BPP^exU3&c%9@>cWwjangB%^WGl@KyyzJ2X@{FhV z@T8GxP|7j(V{O??ic&7>9DNfADn+irs(*s zczCJUzj1S08VuXqhGi8rjmmxeK&|(spdm=$O96+x+4p;uJ=bB8vH+vUz<_pp=i!Jp z;c7(V-QW>~iP0`|f?YE~549#zS1*k~^U@Rp{c&pk;G`8x(M= ze0*K}_hJG4_F`p_j@o#Z(~@rNo8Sg$A)d9y&Nv`{1E8Z&xktJWuckJjU2c6*Y{6t; z1r(1`O%1wA`eQ19yDDaY_=oEVRz<(ecK0x2+crhaBk?K|$lfM2+l0o7ByZJa*Ma)H zQ_10ZN2Y$8!8&EW-b3aty)CV1Ke-=Lk34)0(=Ax; z4f1cwNkta(I9fXp_O^1(RJl30ygbg`Be=gvD(uW%O)iS3!O~ngrWy^f@5sK5FhKNG z9$i=d1F>*vULiM?xNhE-i;=K|3k4TACpvB4AK6o`^=jo>z}=P8+J@FYz{t$p*d118 z*2$j*ZY%r1)pqXggnpBIex7-KJD$9yPKRh8eMYkpdl8W?9zojTtbPIjUA+NKP&`B9 zW3DZBAbn?fCivb=`NLaa)}_FXtgQRov0o^JZY^$qKwYf*8ik$k(7rZtS>icEC#nlc z9&96Pz5;_VS(Q*ZlHl<~@0^w#Au*-^T=2z0diXe~@=ly%(FIl|wBwhIoc?3&br&q1 zeeMBg!2ZYAO3b)Fyxs@atVn?Rl+NkF&nw^XO@Mcn6=#~eH@VgWxZKZNm$PY1>F)@M zWUmW6UuJUWjr}g86Tn0)E7EeKHxZ_LooSZow}pVCg3fF18DC&sJEv|2zd3aLkm=osdaaY!uzi z`4-lr3gvr35|jK?5}?T3s;>DyJrc{_y&uFjnEg80)vWUvkyfWLD;he zq#8fGWxtiF$XD&|*2KG1qF)Uqy}N$J8veZ-Ep6$JuksZWwN;J zzNukdF@v)Rb;eAa$R3z=$hZT__n{s~6h zpJzUP?{hXZ9|FrGe*?7}UiwN#db}3+rq+w67!Vv&6(s-3(H_8E>yw-K+Kt`V>uQU@ z7d)>qo8@sT*gTe+_&NX@f_P)))ZP$MKN>rw*Ol3vo>IvlgXprWzX*vlHZPlcnt3Ev zy9j2Qz}^<9CzndK_|6Koms#h|)}dmrD32QwX~A%JTwf+0SOU^@GkFy9oeb;TNUN^kR!1ptD;{YYrR06{A%U_PWwvS!PnZJ-26D6Y+su;VH#Nj=K zkNqjR5Wlor$b(!)`{)jhsx^F=-sUn9$T-SebiDFkE`E$IJA5Hk6d2~A>WAg9dKa~u zz->bp7}oOLOSpL7aB#Miv$t@ReBu?aQIZ9pE$xF4; z?hkhRcZi^uRneI?-phrRw%X@QYYpml--QG3?V;7#&0_F;OQ)yH)XE{NcQGV$d$CuAj^kJ-S@%ijRh!ccWZJykd9d-Sp86 z`0U!j0e7_M9*FH40QVPy=oZlJC!Wc>XVVD zeg54VwsY`AC`WHpMIoh$cn;{k1xzHkI`F3uM4RjUz35IN>l$jie93I`e$A+9=iC9|&MB9RnDq3E~n@8Jvo(;%Z&E)@X_vnce5i#b}1X}s)sU>~e85vCK zPmNswq{$}#;^OyoVIEdW5n~uQ=&rO0XSy{QKS^87{$hi@oN8M0TxPz1Ym9ly)Ocwa zp_%+F8y)1T@K_^GA#s&a$;y;!VPt(psG#%DROnbP_iYKTgfe zW{-So$9kVJV5SQm{?N(_?wWVJ4+9mSs*cywIuK>FIW1kSi{)5JY~I4Mo4Bsq7Y|+q z-(Sq}Hvb&9KW2Y@&y`)X(5*n!ar~CdLd#`fNQRPf^d`@8IfKuN!X&c6N|5;$CmTjBJ)rDDo02II8$B(sw8Fz1~WIKd)clu|7vNY+x3<7j?+@5515 zG{Wz#OBF=HY2U6cEE|Li`Z%)CtA*Paeqg4LYBIYw=(sc7y1S}_qEWSO>U>mamU5ky zbswCQkRaJ<0N5ERrr6nab9-(nR^d0f(6xHl-kSbr&}-^O;SIwN<*!n1@dWq*erM6W zBYzE;=h|S!Sd2fRjCAY&^MOJ7dgm$8F(d$dB4)UF!WJ02Mjp_^^FCNFyJ=osO2E#*9^Z?Z!wAqAyUcr_i-i2$mQWvQ*IE_R4A&4)ho6m_o{_=SCy>cB z_g||;?y-!5MRw6u;6=?D+cr%T&#bjE^8Bzn-oLRG;7twz%KCjn61q38c=;_wGZXwPvr82@%e0);Oby zm4c3Y<7u-)XjV?IEpGKav6b|Y;2j{6Rww&BRBRq7T}GS#Tn3;ogT-dCe`r2Ezw;Wq zWp{Qnq;UD}ElY*s>mRSWzIS@H+RYd+gKC?*1#%N|t*okI(zAI`C&nS1tM3s;?oBuH zSc0)aZ11x;W6#}5MXS*&sc-ua`OF4}6e<%R*vuLY6?wQ}3X|DAV9*;>%cGra?1!IN z_#bgi2096v#W2VX^0o2gR`TdNQ~;cS-cRvKGPPyycSc8|iEkPkVp6Z>h6m&+%2_&z zYu_6$F_J}FEGQSBYE^x{yCGepa?(tmV_>GM?h$htJ-=0RIT+oGk;`a0*r4(MD3t!6 z7hguvv%ba8Nm486s4%NO;^q358+SiJ>7B~u16SXZeJYiHBN*G9pD1*4Co=cOyUI+(?t%+MNHXvnX=KOG_)3ps|(MBx7&bHbS45W&vJ8_}S z@KwxVGO?klHg?jL8(gMra63RQ7(YEV`G&YpaspqVw-HOOORWU_@x~zd;unUY26oK* zOlV|-5gD&ZFfE&fSIoMeC;DWWI2c<@R(ycJ8Ob6FNuPs>_;ZB#sTN6~;X8Gll!zq| zsY~p;pN1ehF`ykso&f9UX0L3pU{LE8BFAU2t#!EY`YUh^b-ZT{J=SQwS8Q3XRXReB zY`_X2jGE~ul@PVgeGjO&{MXIF#R3lzv$gz$A;bP95ZM+k3F_TB>Zx(giAc~h+m%zX zz^1nQpBW|e`ZPY8`*IqyVd326Kuvn*y-M_~<}e#J%yi}`u&~4N8W}C}(q1@knj!r8 zQz}cGXCHzhg!^~W|C5(~ij2KWiOS`O0@8`A(1FqM!UenOj$@W!L7ZIl<-YE zm8`>LOlwmz_9P1rpFV;FM)*Uq-mP7NElGG%1o7m7DG^=u0p6J(tMQcJyFJ&*u7Fg07nO#4m>yX_W%r4ro(N29yv7?2l>+t<-w=5982H!}JV zd%m~9ch|Kt2hz~*h?$7k zy#*?5Z+rIV?2w+Qx;3F*dyeV&Bh}lzUWEBz21G#oG4jI2ydWsF_P}`ajJDDLHFP)S z1dggZ5!;H|CLs;`!FePDpF?zBffgGJ@7`lvh1K&B)_nb+eUr@k3tu?Pwj*1|wG9qbs0XYA|HYT*)JR5)Wk=E0c4UNHb;8=& zm28%|`5uNd&^mK*|JfCbuq=Ep!x`RGhqy)+C|kx$vJ4D`bPpgUTHF79Q@aS(Bzf&d zuzmpF13GnK%@x*?mhSpEmX=JnaF#7!GQ$QJx6eze7L^q>M^MhO)HZZD9+p@;om+wb zJgxhv#+Q+~;R=3ib9^ByxHbTNpYdnMoJSNibPUIAdEd(ZlkYUgC*E|iiny_Lqc~8)q#hj121hpWL$LXJo52)gm2bOkYE3T&_x$(+&qbi%I3PJ%dT2mqMTKia#A2ueS;puemBV4#m14xiq zh;Jff;U^gWc0V42jqT-v(YG5Ggz@*MPS*b%Dcd1PdjWjo5Q@44FoN9)=POH200b#7 zw4i2{dVa^5U+{9AW`)+GK&otR>&k6Ocq-VM8j7rBDsv=YIAErK$)@js3YV^&1dbOL z+3uYyg~8on1!)f6&bACGiE?d%ZIi@>ppvrT-Q&!%VCV_lZsJ|tmce%@ai-(r zUebAh+MFuI_>Y7mZ?Uxi7eB>=Awi6_KQ}U&4bPFjd)>A1vpz$>rH%5X!b9xqLsBT@ z+;}eWP{3U%8Mst+1Zdlly*oG*TpN=S$w^q6*(@c^Y&OZ&PRuAdl49l_yA#hq<>Vfv zZQ5I|H>G;IJo5R^qV`J*T!xKIWLWnKTsNi3dBO6u^#bn^1p?C&(RiMK5tfQ2SccB{ zUctgelRT`WW@G6zTW$S7ieqaZKlP)nzdjKxM=PD}@<()=9(l{cgkGL`tpQj9p)-`3|(TsS+>`>!egpE~hBG~@GT!LGLtQi5r(auAild8}e%ZtxeWV|a!3K}DHS8A7Q+GIbyB2vB~;@?>(g+>Kgvq1tr zd(t>QLN6)jq*5bb(IADL0KvU6YJeGIO9yspe!YKE7jt`WJl9DI65f0dnY0J3O=F#e z!8x_ydLX{7KYApf%szqc+%pzAZ=D{@?sK%PS(g#{ItwZBOwb5f%);j*J>hR7gFcfS z49XAQCM^Vp*H!X$#xI6z5~aX7%M0y6Ndd2VpqyUUVcV$)zx}wi$x=^nPuPd2G@lX5Cg)Ju+~Y1dzyRf^AlEV0c>JGN6#-MtFR z5`ytfx0nRPrY*5GdK@k&pf$>j5bpWGD_bT_tN{@J=;oZV<6(d1n^xEQKrh=07ST=U z_(hqCecyx6#T6mFQYj^Lpngw~LECqnN?GO!>O?>CgP$mg?8m2zhs$kGaxUN7Mf|q` zn-Kbc&wyp+r4DC{qH}*p)AdF24&~}=);{y?9XUjkovJ(>PBesl{AkzYaOd8Q(J*LA z%Afbo8L6*_{kvEO;xA5jH<0jbaNw#mwg|cEnO8z)bB6sx(%wG*N)!zw5eXX;1zP`V z7708*-dKVQwg%xaG6&@nHdoO&Wu?EkYG@Kv>$L5P_!zMaV{xi|;ggh~h}c^?&oa|J zF1dV}kGaJ>Z?Md6uQ@=@?IW@nw2R`{a9r|ksCErtPp9?2Rz!sP+nmPYvVmYCHegF& zoN#uuhHdeSX#6ci^;)`xeOvT35&HBvs=0x|rr2DC0deZT^TUBtNK2Uw4Z?qe7m<3G z{;|1(_ist#JT+{_jyW~H!$pmm{+ELo6H`xsB6HS>WOb0D zT&^-hU*Wdy{@D+z*~$Sngf2&soj~?c5Q2CyL|=jj>)TF|w!vA=p+m$S*WWt&z9?3Z ze$bfUYM9Wd-0$E}S$z+mMtQk`M?fsSUKZgz4nDZVL^=>=sP86j$zE`t?yu(&lL$d< ztL?SZ0HTt~!^Y>rI_ z>$j~j2H?np;R~Li1p;J8eBXV6z}3oG1q6+XCvU%+C>(ZR=sUpl0*}@48%)CzWslZG zQCb$-L8IB^-lqpUu1rg;>FjCSCKmu`9<7&SUSBlsOrxC?-*fPYJ4lG)v?tQKanwWP zyx*c%;UbcBQ284#ol=P2Ze;uSZ6Ym+O<4dBAG`hm)PLra6gYVi)IA67u-fR#GlW~a zhXz>c5qDhLD#)ygk7rT}#21$-Xf zNBDr6U3LA9Nj&i;QZEn4OVXDs9Zx)o7~#EOzlQXS3lGesFxoB|5AC6EvSW7uqt`M` zyZs&J&8;@|E+&p$S0 zR6Qm5Uj&b6jYsCh*wdoLpbIr^u}n~mE@c6xjef^8a1RuzVV={T1MLMHg0#izZbj8D-@-rGeYHGxvO`P_z(3Wiz7A^1HAe+ zqTIe^-;wcl%64h7fP**0GV}kMo42}Jqs}uwc|UYa)#EQxqw}0&BO=+Sv}9qw2JEMxhhFB3LbuVX;1kJ+Ui+$J-{S%6p>c17?_eLgK1`2Q6}xVL zbpIZ9C|SBci9o96$WdnTrQ{sRZ=k-@x}~96wY#%dPWqIsh{h>J_^e~oo}!_hi`eEa z7QG(264X*w-Bq)p@pGXw={?fc09@1>DbrspZTCv5?_JinKJ-DLvO#cC%09xEsaT|V zSLWCjB>S=#62J7-4u!JV1|yyBo?jFUGWd@YV&UUNX!mN>F#wiT^;s`%@|4YA6aan5 zLP|10i(BmB8fHnNW_kpR!F|*LE4ql}xM)U#ZGz26h|2%yd+{SFBvwE!VkO%vaQloe z#X*c%JnupZfvyyfWZN|w4;ux_o(gOFcb5bzN)R0{{$nKAa^Pv%6bU5cm@$u#TbE6T zlK|gF;)67^hc}uSLr22Tq2x?>xef0P1OHO%l7W&k*tj)__1}}{+19)%&_J?XIVWKd z!NEZeU%g_~gkv9?l>S5*hrgz`E5=y0+Q~*!4Piw1D(ge`XC?_G?p=c#`U>$DsJqK_ zb^w&pW6K-)*tcGGT-OmjBACXGHvQp|o7C#E!J@T{JD8NyLqSsMf~_Jsb%8lYd}X^( zf6PHZv-WuhKZM^r%Uy|0$gmsdBiSf8RcJ@If)EYb>#JYAqV@J1jDk=HyF6L5*P~oi zenC@!Jmayzg?qXL8U*RuJ@qrU+C?YwEA0`&YkSY>%R9$P>uHXQ(KUQ)U#VpO43Iea zf`r!ed?jCvytB7}4;-wI1vZI_KB9F__Ar&ulZtWPS>g%k9?NpeN^AA8ncukLJGyOx zE4lE4?b0a!KByVGXp3DkBP~?`?PN~*kuFQ)Eflk^zLJe*WmV&dBq9vHWC_NS`u5j= z7rk2g+s%OUdgB?3laU@08!m^l&Bq20T-owz7}2ya=pkiQ#nKm@ws|ZXsfX;&y2`}f zIWNy15w5bUlycKIPg1T4mP<3SxWup5)T-0LvN2`Ti~f5pYzDU@w`LEt>l5l)P1e{C zS`pLjH+^itTBi3M%_YgEzC(Uf_{fs)8e4)IVU=@~rsT0J_nEa&Zh5h=YnBgMUATfD z90rxN()7A+fs#ZSkH%7OJFBfxZ56Ni==F>c&CHt|sx=#F7dPq+*j{3qIIFRKvAf@k zx39!+eq0*x>N-WSQn^!otCFV7X@e^QMsI_jOocDGpYtkM9ZedM*C=*hI$G{&)nxs-?Zzt|@=gmJepZ;0dW)4Haj@)Mf&i4TRfodnmXFlD+CL_8&1YmUhX2}dtd7I zbzRfHu>?MLg^I-MfM*A3{l$T)ZOVsl*tF^u1~w=R%+8bP{bGd$tI`f?e$Yx;C}xjV z6t3QGA?Op_dx_+y;DI$>pK%`K@3kKT@j-A@n~Czq)uVGZ-`|7S5 z{6%sOt4A-d1E7ZZOek<9);!K^P`g2MG)ve$R=MHEw>)3D&W3=Eq!lVzrJ~c5lW!w` z^oiLXl_D)JGmB2Hr0H+d1-*e4&b6)?wO6=T-7Qh2d%q^42lqX)-rImtJ2tizBznk} z_^s!Zznwq{*`6;KEh?Lf8O!%+$NeNKrciY`&-V3#zU`O3D|>Rn#Me^arcg##f^VC% zK;EpI%??&IC1_(1!4-~R{B{3AIHyG&>7y%U@N0j)4chiH^P&srdofZD)Gelwa^nHc zv0*>bwFW4i%Q`t&M(9`QrKxGy_nqmd1ef8n2Y2Ow6KX#24e6J)#FHRJ>AJoVi((g6 zzJM{JH>neVf}OPO%zON(%D}o0C$eE%D@LDXrH`rEqUU z&k*~;!zSf9j#{J}ID>Nsl(H3la1Za=4Yn=;StyNfezPC}BI-UAltjA*1#|lpc^~?6 z=~pC_xG*P<`K%oCRC-i4c981J#9|Lb3R|LdWDM$~2S|=F7I3vO`1g}i$yY*@3xBfg z&$krelRr38xTB?Ze1Tv!nQ=eqV?UO|#%r?4s6hEz+BvJLE_h2BePqG8{>8HYY7aeS zlhvgXlb=hD)nWG?mV8CYnsn@5*11nI!{smlAlo98XeY?42^(?!AR7#}AqrYreEg2U zQ#ZZcIk>WTQ=hnGGk`JHW&OGP`NaZ``d6uq2<2h|fzRd02m{{)pS?OwX@p$K z)^-0}rh^9~NEA&(nx*gCvKgHRXW&wkr*HrsY)gtY35+0NX-~19<)HnyNM0u8t&Odj zKSeu7aT3se9UpJ0VP)*zQ6UP}X4TQkiJ94!tK)}%bUiFR_6<0ljJROG6FJ4QP#LL? zyLt{Nb~f1BIqnnjw#dbND2*flae4m5$)W!PggOOG_0$F<|HB2m-;E z@~<4alLp0E_9LipZtwx(v`$gF1f@0iQ%gpcR6_F1!uzLW?Em~5ltDh5(dzgmDEJ~~ zzhW}5Mk68OfLoGDL6?D8_Ory5@3)Bo^y1SHCZ^>qLN9H-@Zdl@?Udlbjls6;nR#Ngm+$yg}eZf3Q2i;%6(Fe^IMO)BF)~W`=yY7n=-Q?}a!L z$-N2=EOh`Po4CNd@d~(qwdSlvkQQv;266s|aUdZ{mG>WF8%zgHmb4Si&_ zB~*(ha}I9LmtQ&olfqP_?LCz}7|{%yo{0QHI5mB|XD~RlXtr@uGC;&@$+U`a%eSJ| z(QY#z|%l_4;wMKRdjRMSnnw`@NGxlQ^!Wgd@m| zd+!)H^~CucvX<<-6;=Sa@EB~UC50I~d?(2YOvVg@>qhWuw34LT8v>+hatnm&8r}-i zTQxfqLSt$R7-_+h$U53MmPr5Gq_=0#V{>4{UAhh1%RQg||ILnH;{V%y{!bTPhOE-R zIPX5cbIt7k5weN`il14@I;qT5Sf8a+QhUX%RtzdUu36&C`~L0??>`3u0*l2GcXu7% zgfE3vvZtuy?rmG>=w&asNNk*(c# zZb0~rXYN-62YnI}A5XCGRy$PWAbo+?M+tdk4xQ(8L|Lq++o>fPm?0{lX~T*}?8jD4 z11J0@`PsUeMl32#x~-RgM^l?|PTJesJB*DA^2^8es&fXt%y`&5zM6?q#zXbl1|^zP z;?1!^a)}P((8fvuB=sjl0|bC;04iVv7wR0g^wP=fIr{kdE^0oWUd)=Pde zC{uiJ5Av%N4-qY9HakGd ztJH3#NOr~r1YpJXxCrgIs}5uNew+76cCtNO$B&22Tb}@S@UVYL3aXPbiyZbkun{_+ z`o8-xrTjw>%W$jX1@^B+4aUC)SR(Z|z29jV^lh9JR5MVmmp^mDJX1%a zdzm>#h$kuA$SDUAf!!n~FoqcCvzpn$6niF0>Nlhd{@8MnnG$g245V9tep#nw4nH0! zACsfQRslV;{2>E@WwnRkC1u|1xB0R{!c)S*BFSS=L`3#Gp$WMC%<-XDpb* z(*tsxN;(HWKH)jVEs&~2vWu;V@CG&+bZ~;V!08chP*_{kplq$)nQ)UGW9>RY8u_8e zZPgN4Ef$bqy>7`tUcbAr~isJRXx^gkzCP{-@7p<(Hz>S?GW#(4+=zjhekfi#(te-S(do z@?W#kOhe}G|83)a7{mws?isn$Ny8K6^uQ!pQ3K?3sT@9xZodhn`|5xG|b7w`i9%vz@25Wq=ZH-!3 zS2KhsYp-W|elHxwNZ`l*ZSj6ESSf4X`f?PhO)vVw3uGi{CL6NEv})&mO?0_h(-3q+tuK{j)seZ;|BE#YDai)P1^e3R~?wXIHC^!JzjvgB8Iwx1tlL)Q%G|ie@gr}OnauVjnE8IOv8mFb@`|CKzv#;c@`B?Ha+4`-* zkcHHPzHvFN>(8G$6~Cy5s53h&bjgE|KZoIYh59u*onF6en>>_UM+_aJ2YVPl^v{nyW z)Gg0$wsTAh)u-Xa@h{k9gUQ0Fs@WwZbaq%mdsj3UCSPeIR;Kn&b_;%g_tsd(20&tQ zVtr2pU*&7|f2Cq{lxDo?n4#I;>>MgJO^Zifc~;;Zs@EMT@;hSYiOkr+-O!9;wt6$A zl@EvnUN}|JJH;m|23F5C>?nHVn$CEIyd3NkZBtJtZ;sU)M#v2eu>QU`s5sbtyv9qP z{8yHie_I^m`J#KJ9XutL0a~^^1m^yF!*RHbF=dfu(qh$kqQ%K0u`a$WUGU(4G;@_r zad6ENXK|MVhhPcrzPJP@A-HRBcV9HPTX0Qq2=4OWut0Ek7Izj~_Rakl_uKh2RWmiG zX1cn2#4+-IpTPdcqU%YOKnFmII4xCxB$YyUf!t|iRgmt<=##XCZXVM}*5_^_4-~6T zj`0V=*UEoJe-3gxE0#1ca9#|U$IgBH!6i=}Q5*pl>_hyXFb)g83d5i=68r2iP}KU( zCO5}4K#5Ikzb!p*TmBYT)6QtdnbAPQY!-$XEdV3eCDiMk65ApB4aBe1bGAhYkA6OA9|Y?_xw^EtVn)Y1dRKQ{u`Ddi}98KgCnQf*c&lbRk`a z_|~BoVI5J&iiXC;!8SA zCcd~i)jNI&tsFL95}ppf^pjQq=ND>uN-TScDKLt{6dzZI3eZ#ydPt-mzErbllkC(W{v%9vp_q zh9NjSg4Vp%2|GJEa>p5xNZKpreQdehTo*7XpS4M^%*57GiC>QYUHL>%10-u@!H#G0 z-rx|FVF;4;2ZR~b{l#3`&D5UPL2ASn%%0;8wzCfkvr4m2=mVcvdGF;MvfsruZHTsd;}e{8Tk8dO-BQyp#*$z_ z8O8yH$8Af?WnyHPv8IQ0F!?S^1$rC+rC(04^v)bv26U8Mc0$J*ZbGiH+5)o8)h{evq;OKVg=rI#`wrChALJdqzn83715oBatj05gkPMf@m!B`L|Ti1-Jaf6 zL4$q9itvs8$hxKEVV*sznQj-k`_ni-sedi97>P0;juKflZqd37H&#=YY)*d5(LP%p;USB*k83 z`0vqlKU&e$Ipt_J0PmnAR)O`9a^9a%aNPN7;y)+L%EwYj>(x%Wzogr}MwSHru>F8{ zoc&UFPZ1VF8=k!`nYC{+;iB9KG-p)m*Oc^t@PMZ(e*M}epN4q53CdrGl%!!Boy6MZ zs13Dr;su5b6Q}Gbh09VGWEU(p{RnD8xVC4mz-TIT@LPHA-}<%#E;;37!H)s0Fmj_h z|GZa0etE;=`IgRSKh0&5LO;5lun}|&PZGrti3|8`xu;7`4~=*K?> z+r|q5dyA{Ld#1GPIhIU>J0Hbc7>D}Ct@TpGdW};+%dMs+0(q5NqXD*5ZIh>{yvs!r zA>ll@DK(57^mikkl-Nt+vU5d5B46Rx|AK?h8zs23Qx?rInmNU%#f zK&-GhR8V(OXUD;Rt`VS8B%6ahua5^S=Z$?nT+{BGJ|h+B_&fsY$@>8t^AfZ1OW2Ep zpj^{l!vWm#A6*@@*+o-vly2gQ5d?97$eYx=>Sru^Za6EJRwJ0;F?qCcGMs~KjJfC8 zGI)mDf6Iy)_%sv!W@jTKYekSU3G!il1h%5|wmM#TEQRcuJ|MPT?s|N<7IDti_3CU{ z(1jut*ajMn+f=SbOM?E#h&x*GAygD^w+l!O)2wzQj~8fi(Lfe7?J~=bY&$j<4@VD& zjcFaVn2<%@XE(7rmV}Q;^vUuvP!E(~cbPEb94WmGP>t1i;!VZM^pCS^#XI3!?bU@h zHG*$x+}+drE>ysiVxu*jM9te2TC4#o9wywK$2a|Ap7()rn6jgO4g=R8h!y`5;C{MP z15lZe@SOF!qgx=Z)v@2WDJFm8D16sc7Jc^~K0Uvf$Q+V<8J8Ww5{R|!jL~>5Vg#wK zSQDs_w{`Gti0qP#oAVp?7wFJ1$p&I0w&2K}Qp|0T&)7B=2suxTog&{Zph z+`lv1F`7b!Gbp@0@f~P@?k#cT1~w;Hkn3-4sjBy@90jL; zPl0o8D@KE^(q9UV8JtOP-Z&gW7*YI?c6UQ#aq5PkdUJb0-=p`_KpM3O(XRN^r=CoL zEa9k>Puil=NJS|Qw0`oZK1&H`O`*lHs=3gK8!WZ}4QuRg_lt!O_F>7)xoRDE=96ih zMIYqU(%XMyDk4iQecyc1#1aqlWT)Z$dZ;NSE1X(VIcKwQrgMI^&8Vk;S!)+FUVl?vs!}xc#7b1E^xBVz$GW*;^Ti`Sot;#?5_8(X@N(q( z+z8+Lf;1w@%bldR3<_%vZ45~Ki>jhhY~Gjb>8&AqX%*-&Q$$8#`pa9@J91xcBF6b+ zA#Hf~pd+im7ete&1S^?7Bp_O(Ud84%)M_zP@Z9_P|b=7Ss5w55G&OmjoqVCOwU=!y!~fouqtu$^o^B45qkb zfn;U{_5@mLyYNEh%pfIgx&iwe9mJ4OmAG8}rF+>d6gB1a{xVePWRdnB8g|J~@DLQX zA^IoBW|HtyCCH4$=%8+sPTI~3!ZK@pGjdN;(%XJ#*m^5{fEt)0<*5kODk?1`K$}KF zSg<*TW?j5jrMbYW6cdcXR*!8J89g62fI13zo_jqcY>bHVCLA`4kG@`bQyo`$$2n0$ zUh3eF&xx5RrKP+s%5T%E#icD}pvo%$TMh&dtXldaP^cjZt^sj7frYE$X`yLJ-Xm-$T5R6%35EBxPRQ*t1T(RzJ>wWqF0XG zK;jqc36Z*i0y5J0Is$8*2ubo=WR->&ycv%Ed~`;_@SV<@rS;EzPRGQ{MEsxsx`%s* zts7(imMwtVR^o-l-^KYogmt!*Y{7)!>D!bVr)fr+etBe9w;kLq6h39UL1YN8&7XxB zEP5D2!97H^trqhBmbaM{8(YX!9o^1U&}d2T|F~i_-8Jg=+6i+^NG3z4X@LM#XOI4XZrMO#$hgoKa3D~nlgKXrcS;jk18*`P z|C~Wf@^1qZU!7TjFg_A9&lqC-5sqmtXg5GG$GQN~B#e3&^6I5>8q z>+gF`h8P^5`i+qUwj z)ZsmE*_T)P<-8M>i|%OMq?3rFyefkoe#eKRM_lZVUQGmXde6XzUs^M{3) zj*Gp_J%;b9pPHT|JN4<3Fy30hwLx~ZROLoNlqbC_UMzm=wbVV6Bh*eg8(< z#M$?CCOZZcJ!&42jt}|(7PA`5L&+@(W9gcz&qN_&68x?7yI$vxzUj`e$9^f7Wp+5g<397+rLE(w0-1 zJpY?C^F2EDtCzYHA$`2ToHY24@?AIsB2(99&rvwH1-CrkZUN@vu8L(uD9k z*d#sbn;%987s6E5{9OQl-lf0N#BeTuoKT^UC$=>4#iqFoF0g0gyTDSI%z(|B%Sy2I zgE^e-3F%?7qLBfD83r6Al+Ch>GUsGcKMM%<8DhSV93DHsU+ZGP1w~4W)ib0wfZf|o z8rfdgZlh0|BNl->0CTc~qIw(5i# zt*{$80oexxqKkzNVq|^xF56ps+Z!588lX(-hgOUiTe9=|xu0b1* zxx!5bjZXlHCE(;ame#2#h(}BUO~J3P-NtgkB%d=JV+o0WAA4+$`j^RMHs^Lv%2Xp+ zn08;RaE(WJQS(y`4)}=egKiCl^^jUO;1)YCOEdd{+^bvy^hHEbL)mo64jIf6I!4HW7Ey5#oq)O-9qV!2))Q=Z>K2qQ%W%f+p`(Vca+hCd; zY)eXl+`&S7R>Wn*sc&BIq6Uk=Lx_1Uqv(`w@Wo*Y0>x6EK)L|Nv%@>X_z@CYqZ!ua;6Al{_&7)*!gCUBhVJ*&uj+d$q)`ZDK2e@(Tt z7E6YW*j^M?!eArt(Wgw9=BhUQ(%xS&sa8xUsqz7EzAjCwxfQQ|)QhM34Taz-!e80; zzQ9;)Qa+d@MhAyVY`yeSFGb`SiWawY8gpwIFw>sJTo9j2cPZMeZXL?h5uh|I#FguD&H)QTvZW4RG z$LH_Nx?}HNtwDw&>sGa!T~ONfpmq)6oP#;;^R4*ACd>z#NG8DqA&r;U zLo`3Fu(Nx)>Z)%h#=SBM`|O(Mk5W%k;lp)wX-gkL#i(!DJ&Vgs9M7a``29{ zo~l3~8#aUdm?vz z-`~e0S-aag}Zt`q&>2u?*IHR#;` z3yn>muoEO%OE-f`CeYxiDweFk7F~VXLnb$qn?Z*cg8nh*MMSil$%H&gfp~2#><`mV z#ekTNneBcEf0#;g3|x$F40L&8XpUO`@~={n1evlxBWqRvZvr2~zU+%d<*uw*Wyf=| z71C8L<4FCPSnlaMdWhIBdWchQ0~9!x{&dXiAKr=|bc@aF{>PEXq}G(?yms-#U;=2M z!HYW#pg|Yr4}av7CVD05=KQ(x$-adXlF#?^g0r^f>ZRRsb*}40y2CWTNQ65aRk=%{J!hZID~s^67^#f zQ0@eV`MTnfxo_8;HPM+?HPHn5G8D6`lW$-xB>#SBEmA7hO@}5qE=~{-2Y0=pUsq20 zg0Dko?+XGhUq5m=OBRPx7_Fto7_*pa;1P_wo>vWkyjp6ktXmO}!Cn{4IqFj4(jhO@ zaiEPbm;Fnb)Xxl!(|L;eOFt=Yi~vW}3`Q15R{=Mk*f^S?kVPLeLp zm+?o9MjMmt~@y2yQMM2+QmOJZEFQuuCI}C`!=N=c&e@m z3^xnu>lz6SJ{r43{Pxy7C6((r!eIhj#zoa|lUlnGY2_gID}R5vKAQP}uTV-lP4xF_ ze&c6e;@Sw}OgcGrT-}u|FLP*L?Z9JNYbx4^e-|Y&VnYr!wW#P~kbL2T@&&KpjC~Gq z#-yhhz~!OYay;Px68%Z0GWcCiDIgm=UTX(08LH~nKAd>eD@eiWgfJHZ_;rZ#Fi-0s zhm5O0Md3T;&>ba0IGGGrir+j>ai(dIJ`)4l@}XogA$wY%rA@qr(x4G>6h+^Up-; zr2J{dl%G<^vnYuFc652z&7$9o%vh4DD2cn}V-VmKYiQZrzKqAaa+K7AWZ#(A`s+g&u z<KSU{n_=@*nLxjJ4mV$qUE&~S3O%JS!zWQs9y!%lgm z3hR$uT*t{&$ZI7C>$vI~$Vty5{48$a`disVKAOq+`lJ$ovLJ;*DJyC<_WQjjxSihJ zx?tv9kCW)L6Yy_4y+&)D&s-pBRBQTsQhX}TZMFRea)eDCk&Pcre=?VPB3DFw=&?^~ z%4R|MqLD*dN5tm|Y3*d#p|uwKxe>G3_YK$UB(PT)nVf^8!a#+Ycp?^=E#QW9pi)}F zri%D?t{ux)YJ7N~>|=utJ_bQi z6H!dauQ`0Bq&b2tC`zg@XM2Tbm^tfxsD6_JxyUKD`%V{bJFQS7fWNQr^L>s)5d8a} z(4V16Gq+hvVoCOS=ePqcIMFMmd&b3ImV9yyVj<{_i|)7~H43t1Z9AlWdn}O%pJFoU zg&ze5TDP)z#j4OVlR*D}qIol!Wd0 z^miLvReI-W*R_(V)`3}NEo1Pb|1{+6>KsQ`y+kfGN2#fzdr>auHr>>E>I}Rm@ACY% zKRz`4;HLz{S^$gfXbRv5&6z-DliBwgd9%!HwC?&W&R=l?l1~Ox4cQq_ zAZaNtw&5vfzM%fc|8B<(F)Wlh$uK4=^c3bhSCif%;|XW|m@MeAKaQ}lZOsO+!&`mN z2q2wPiD$hhzS>DYg;Ull0{_kAv?C z#JvGo{}4^#%R*-Kk8t4g-(&b>OR^`S8kMd8x(ylL?K9BB^>==><2lqa7HXCOYDX*jPmlcIP|s;g4}rE-O;{B=BP`Dn zJmG*u(e(W>GxLZi5UVpkkAkd>g zXcag2-G)3v@|K=1DAa|d)Rp+XQRcdP!oU5F&0v7>BNJs2T7x8rO18`Tc5tp;DrzO$ z+C2@sdxEVJv?IPyDjp3euy4 zP0Z}e9h{I~1DwcOaqnKa>Vp2;=B$#!-M9(G%uqgXgoYtD;7b_8H+1xhT_fq65ebRP zcE!j6vyt*Y8mCV`TA;Ugi@f()^9~OvoyzyF$z+6C*=pI;A1ps39>@g=*ikA*~sj%Adk1>4}gBpr^nwdeHlY+jjW#k z834f{;L+@V73TZJa@`G7S0GN;oS6YKDR1%1;^e@Te1hYciHsY}Lj6 z#TB*h$h`@Ax-&jAl|*HS3*r@gn7%`bf?~^Iwm+n~ypWEI-=55NON3l_Zw!Rx^`7uY5cjcfDE0E+f)OjUm z2Chn!0d<00XzJX-g}{8cebc5CbV+&8?Z4)s|EBFFGnB3ZB#eEo+}nUK!-XqTHdzYD z{{3VM;;*>+f4qGi`f;8PGTFalCu7DXM3BcLZ>$j6zweq=(W7@rA9bxwgv1yFs1b;S zOwO`nTnII8xg#U?F2Z%*`Wzg$Kv}6jtbu&_u&z##?wiR_yi}8t`7|%umqe-;)ooGx zd=Zza#o$I7++E6elf|bUce~{TS8t;a@=+y$l<;DbPTwk=rKJ}(b8_YdNWEIr^qcs+ zbNj>M-8>f?=6&S|yrXkBC}UVPmKrqlf~l9T^(Ur`Z&%wXq1c8dmuvfh2pg&VYo_+;`^TH`?oO20JntHMPQIqi#l(M5wdX>nN7K{* z)nC0S6{W*s)Tz!W9l7OGy8oJg%~99p!Zel|0bM9>dZ<|K=E%46urptuV>UV&%)@N+ zMvlT0fP?ko(n0?tGj8}?zai~X!8G`M@6^VV4S%|;wJpb+os;x#i+8Q;spI-wt^Ryh zmnGK%2bA!4*ZE$RK=vxxef(XqSu4XU1DC%APXB1%6=Softd5K{B2k%sh}7|vzCb72 za^lg84-AV%pE0VTdHKjYWVUbThoU)}?N@W2r#G<=(BY33eO-qDCwpj9nhA6%DgCNy z2HMNuFZ)RvUo4w$cjWa8XO|5ec`(uRQ8=xJ!x-JDAaSrDdsyat@{>gN8Sf?NQ#vY) zfB4j>6wNg+DtySL+>RO3txmYPOI~)gnl(rSdk;d?QIILD;JAL4>cf*#_QVc!N6TGXOUE>7RIJlCh#3njIN3VcIdX;dlM@t3jGpu7URu!W64gY^LxdzfW1hx{e)e6^9{>&PnZ)pGL~iY8uflM!zz? z&2D4==2y8mHuM3+{-=>sU{jg@v9VTgrR+wT_#YIlGEZZ_!CH&Dl!~TF^fD${+%A+D z=I?@hk6%b8K6g`Yr6ry-DV7~-|DsUX?xZvzcnRCFa03iZm52TidrpZhqF(9^qJE3v z3tWvL&p)>FS@DLEAy5v;rFQkn(d?~%ZtS{$4pbB@y$LBS**ipLxP3E*)Ig zrPp;h>VMSQir~nG{<+cL#wKvgD~R>P2#;*`(47wG{Rn~T=Ej5`Lb9k8GUe;b9OwiS zBDH@m2FN(=kXm0hMTl@nI=V8}_Cuo58vboJf3?uaJb~yO8Hplw5Hso1uEmbYNjy0Q z1xk<&v#)NI>;c>}>Wfate)h-@S=P8L9`2>t=65mQnxoBZbgH*C5}F!a+kd5N59++7r)-@-uZ7Lo>W=$+CXERk!Ih(RL1z;BF3j( z^a$x2{_W(yEg70f$mzh59@~Mx*qnxab>x-30Eq+Px@m-b8K3~Mmw4$Iy{q17&U&u$O{GPB$lfwr;Pb{b&w=v2clJega#=(HFEOs*UkUTXC}GOq*uYrZ;E(@4 z>YI=K&U&C`l25;O`!NyPPfpdf*G=T1ft^tCJgm}%dKXyF_@VgGk0b!~w6V{#H0eYl zlx%ZV*{7=FujG|M(#^C|cF(+?v=Qmo-{rgcN$A;$NATxaWmnWO4y2v#5RJt(Zwh$V z;9n^P!@C@v0dQ>S@~-gH9xj;Y3w2ZGfs`R6RnPF}maq6o<&}aRv}f{ozP={e_LG^3b;6il-bmdfFV$D8VK;^A%ynIz_ z%ft=ll;;qjEd{Q_7bCzdZl4G!Z=?%r6YU`E7s@u_Ubi`R-;946mMMsW_wLhTNt}F> zjtM$sYiX~2S2&Sn0%x+$-e0hDx#rYanU5d$HbZz)r|rtASHvdd9b0>O>p@g9%^JP& zTz(?yyl>+^nJOK7X$6deq43~?PbN>}Iz2b(bpikXpClo0^o^W%+1{+>(0@YDY$aK# zuRcHXQYLVa>9A$Ds%@FeO3R~jDjAqDb0`4?R!YU&Yo_rq2e!4dp@st_q!10wfwmv^ zS!&*Ki7gRayUf9rd6pO~){PfSSv z@EMyk=@uca)3oLjt8sIxA~YJkHGJcAYuDUsS!i;FwB)#pA;A2rn)e=RdJv?{l;RUA S<&6JNjjAN4CR;0Q8umY6YpgQ> delta 286 zcmV+(0pb4l*a5i$kR^X-K}|sb0I`mI`%#ks001CkNK#Dz0D2_=0Dyx40Qvs_0D$NK z0Cg|`0P0`>06Lcd02gnUshQLO006{EL_t(|oMQa{|33pc03d*v$kGJ_00G1TV=w|C zl<^-38F6UpF07*qoM6N<$f_Q&ndH?_b diff --git a/src/DriverMED/DriverMED_R_SMESHDS_Mesh.cxx b/src/DriverMED/DriverMED_R_SMESHDS_Mesh.cxx index f87bd3f07..7271a5c86 100644 --- a/src/DriverMED/DriverMED_R_SMESHDS_Mesh.cxx +++ b/src/DriverMED/DriverMED_R_SMESHDS_Mesh.cxx @@ -182,9 +182,9 @@ DriverMED_R_SMESHDS_Mesh for(; aGeom2SizeIter != aGeom2Size.end(); aGeom2SizeIter++){ const EGeometrieElement& aGeom = aGeom2SizeIter->first; - switch(aGeom){ - case ePOINT1: - break; + switch(aGeom) { +// case ePOINT1: ## PAL16410 +// break; case ePOLYGONE: { PPolygoneInfo aPolygoneInfo = aMed->GetPPolygoneInfo(aMeshInfo,anEntity,aGeom); EBooleen anIsElemNum = takeNumbers ? aPolygoneInfo->IsElemNum() : eFAUX; @@ -345,6 +345,7 @@ DriverMED_R_SMESHDS_Mesh case ePENTA15: aNbNodes = 15; break; case eHEXA8: aNbNodes = 8; break; case eHEXA20: aNbNodes = 20; break; + case ePOINT1: aNbNodes = 1; break; default:; } vector aNodeIds(aNbNodes); @@ -378,14 +379,14 @@ DriverMED_R_SMESHDS_Mesh continue; bool isRenum = false; - SMDS_MeshElement* anElement = NULL; + const SMDS_MeshElement* anElement = NULL; TInt aFamNum = aCellInfo->GetFamNum(iElem); #ifndef _DEXCEPT_ try{ #endif //MESSAGE("Try to create element # " << iElem << " with id = " // << aCellInfo->GetElemNum(iElem)); - switch(aGeom){ + switch(aGeom) { case eSEG2: if(anIsElemNum) anElement = myMesh->AddEdgeWithID(aNodeIds[0], @@ -671,6 +672,10 @@ DriverMED_R_SMESHDS_Mesh isRenum = anIsElemNum; } break; + + case ePOINT1: + anElement = FindNode(myMesh,aNodeIds[0]); + break; } #ifndef _DEXCEPT_ }catch(const std::exception& exc){ diff --git a/src/DriverUNV/UNV2417_Structure.cxx b/src/DriverUNV/UNV2417_Structure.cxx index 67d2cbe25..a9da97d62 100644 --- a/src/DriverUNV/UNV2417_Structure.cxx +++ b/src/DriverUNV/UNV2417_Structure.cxx @@ -34,8 +34,9 @@ static int MYDEBUG = 0; #endif -static string _group_labels[] = {"2417", "2429", "2430", "2432", "2435", "2452", "2467"}; -#define NBGROUP 7 +static string _group_labels[] = {"2417", "2429", "2430", "2432", + "2435", "2452", "2467", "2477"}; +#define NBGROUP 8 static string _label_dataset = "2467"; @@ -98,7 +99,10 @@ void UNV2417::ReadGroup(const std::string& myGroupLabel, std::ifstream& in_strea for(int j=0; j < n_nodes; j++){ in_stream>>aElType; in_stream>>aElId; - if ((myGroupLabel.compare("2435") == 0) || (myGroupLabel.compare("2452") == 0) || (myGroupLabel.compare("2467") == 0)) { + if ((myGroupLabel.compare("2435") == 0) || + (myGroupLabel.compare("2452") == 0) || + (myGroupLabel.compare("2467") == 0) || + (myGroupLabel.compare("2477") == 0)) { in_stream>>aTmp; in_stream>>aTmp; } diff --git a/src/Makefile.am b/src/Makefile.am index 350144b07..941a72227 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -39,11 +39,16 @@ SUBDIRS = \ SMESH \ SMESH_I \ SMESHClient \ - OBJECT \ - SMESHFiltersSelection \ - SMESHGUI \ SMESH_SWIG \ MEFISTO2 \ StdMeshers \ - StdMeshers_I \ + StdMeshers_I + +if SMESH_ENABLE_GUI + SUBDIRS += \ + OBJECT \ + SMESHFiltersSelection \ + SMESHGUI \ + SMESH_SWIG_WITHIHM \ StdMeshersGUI +endif diff --git a/src/SMDS/SMDS_Mesh.cxx b/src/SMDS/SMDS_Mesh.cxx index bf40922dd..9c4838274 100644 --- a/src/SMDS/SMDS_Mesh.cxx +++ b/src/SMDS/SMDS_Mesh.cxx @@ -39,6 +39,37 @@ #include using namespace std; +#ifndef WIN32 +#include +#endif + +//================================================================================ +/*! + * \brief Raise an exception if free memory (ram+swap) too low + * \param doNotRaise - if true, suppres exception, just return bool + * \retval bool - true if there is enough memory + */ +//================================================================================ + +bool SMDS_Mesh::CheckMemory(const bool doNotRaise) throw (std::bad_alloc) +{ +#ifndef WIN32 + struct sysinfo si; + int err = sysinfo( &si ); + if ( err ) + return true; + + int freeMbyte = ( si.freeram + si.freeswap ) * si.mem_unit / 1024 / 1024; + if ( freeMbyte > 4 ) + return true; + if ( doNotRaise ) + return false; + throw std::bad_alloc(); +#else + return true; +#endif +} + /////////////////////////////////////////////////////////////////////////////// /// Create a new mesh object /////////////////////////////////////////////////////////////////////////////// @@ -96,6 +127,7 @@ SMDS_MeshNode * SMDS_Mesh::AddNodeWithID(double x, double y, double z, int ID) // find the MeshNode corresponding to ID const SMDS_MeshElement *node = myNodeIDFactory->MeshElement(ID); if(!node){ + CheckMemory(); SMDS_MeshNode * node=new SMDS_MeshNode(x, y, z); myNodes.Add(node); myNodeIDFactory->BindID(ID,node); @@ -143,6 +175,7 @@ SMDS_MeshEdge* SMDS_Mesh::AddEdgeWithID(const SMDS_MeshNode * n1, { if ( !n1 || !n2 ) return 0; + CheckMemory(); SMDS_MeshEdge * edge=new SMDS_MeshEdge(n1,n2); if(myElementIDFactory->BindID(ID, edge)) { SMDS_MeshNode *node1,*node2; @@ -280,6 +313,7 @@ SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshEdge * e1, return NULL; if ( !e1 || !e2 || !e3 ) return 0; + CheckMemory(); SMDS_MeshFace * face = new SMDS_FaceOfEdges(e1,e2,e3); myFaces.Add(face); @@ -318,6 +352,7 @@ SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshEdge * e1, if (!hasConstructionEdges()) return NULL; if ( !e1 || !e2 || !e3 || !e4 ) return 0; + CheckMemory(); SMDS_MeshFace * face = new SMDS_FaceOfEdges(e1,e2,e3,e4); myFaces.Add(face); @@ -381,6 +416,7 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1, { SMDS_MeshVolume* volume = 0; if ( !n1 || !n2 || !n3 || !n4) return volume; + CheckMemory(); if(hasConstructionFaces()) { SMDS_MeshFace * f1=FindFaceOrCreate(n1,n2,n3); SMDS_MeshFace * f2=FindFaceOrCreate(n1,n2,n4); @@ -464,6 +500,7 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1, { SMDS_MeshVolume* volume = 0; if ( !n1 || !n2 || !n3 || !n4 || !n5) return volume; + CheckMemory(); if(hasConstructionFaces()) { SMDS_MeshFace * f1=FindFaceOrCreate(n1,n2,n3,n4); SMDS_MeshFace * f2=FindFaceOrCreate(n1,n2,n5); @@ -551,6 +588,7 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1, { SMDS_MeshVolume* volume = 0; if ( !n1 || !n2 || !n3 || !n4 || !n5 || !n6) return volume; + CheckMemory(); if(hasConstructionFaces()) { SMDS_MeshFace * f1=FindFaceOrCreate(n1,n2,n3); SMDS_MeshFace * f2=FindFaceOrCreate(n4,n5,n6); @@ -650,6 +688,7 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1, { SMDS_MeshVolume* volume = 0; if ( !n1 || !n2 || !n3 || !n4 || !n5 || !n6 || !n7 || !n8) return volume; + CheckMemory(); if(hasConstructionFaces()) { SMDS_MeshFace * f1=FindFaceOrCreate(n1,n2,n3,n4); SMDS_MeshFace * f2=FindFaceOrCreate(n5,n6,n7,n8); @@ -707,6 +746,7 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshFace * f1, if (!hasConstructionFaces()) return NULL; if ( !f1 || !f2 || !f3 || !f4) return 0; + CheckMemory(); SMDS_MeshVolume * volume = new SMDS_VolumeOfFaces(f1,f2,f3,f4); myVolumes.Add(volume); @@ -749,6 +789,7 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshFace * f1, if (!hasConstructionFaces()) return NULL; if ( !f1 || !f2 || !f3 || !f4 || !f5) return 0; + CheckMemory(); SMDS_MeshVolume * volume = new SMDS_VolumeOfFaces(f1,f2,f3,f4,f5); myVolumes.Add(volume); @@ -793,6 +834,7 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshFace * f1, if (!hasConstructionFaces()) return NULL; if ( !f1 || !f2 || !f3 || !f4 || !f5 || !f6) return 0; + CheckMemory(); SMDS_MeshVolume * volume = new SMDS_VolumeOfFaces(f1,f2,f3,f4,f5,f6); myVolumes.Add(volume); @@ -829,6 +871,7 @@ SMDS_MeshFace* SMDS_Mesh::AddPolygonalFaceWithID { SMDS_MeshFace * face; + CheckMemory(); if (hasConstructionEdges()) { MESSAGE("Error : Not implemented"); @@ -892,6 +935,7 @@ SMDS_MeshVolume* SMDS_Mesh::AddPolyhedralVolumeWithID const int ID) { SMDS_MeshVolume* volume; + CheckMemory(); if (hasConstructionFaces()) { MESSAGE("Error : Not implemented"); return NULL; @@ -961,6 +1005,7 @@ SMDS_MeshFace * SMDS_Mesh::createTriangle(const SMDS_MeshNode * node1, const SMDS_MeshNode * node3) { if ( !node1 || !node2 || !node3) return 0; + CheckMemory(); if(hasConstructionEdges()) { SMDS_MeshEdge *edge1, *edge2, *edge3; @@ -990,6 +1035,7 @@ SMDS_MeshFace * SMDS_Mesh::createQuadrangle(const SMDS_MeshNode * node1, const SMDS_MeshNode * node4) { if ( !node1 || !node2 || !node3 || !node4 ) return 0; + CheckMemory(); if(hasConstructionEdges()) { SMDS_MeshEdge *edge1, *edge2, *edge3, *edge4; @@ -1290,6 +1336,7 @@ SMDS_MeshEdge* SMDS_Mesh::FindEdgeOrCreate(const SMDS_MeshNode * node1, SMDS_MeshEdge * toReturn=NULL; toReturn=const_cast(FindEdge(node1,node2)); if(toReturn==NULL) { + CheckMemory(); toReturn=new SMDS_MeshEdge(node1,node2); myEdges.Add(toReturn); } @@ -2996,4 +3043,3 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1, } return volume; } - diff --git a/src/SMDS/SMDS_Mesh.hxx b/src/SMDS/SMDS_Mesh.hxx index 2cdf3749b..1a1ef117e 100644 --- a/src/SMDS/SMDS_Mesh.hxx +++ b/src/SMDS/SMDS_Mesh.hxx @@ -482,6 +482,13 @@ public: const SMDS_MeshFace *FindFace(std::vector nodes_ids) const; static const SMDS_MeshFace* FindFace(std::vector nodes); + /*! + * \brief Raise an exception if free memory (ram+swap) too low + * \param doNotRaise - if true, suppres exception, just return bool + * \retval bool - true if there is enough memory + */ + static bool CheckMemory(const bool doNotRaise=false) throw (std::bad_alloc); + int MaxNodeID() const; int MinNodeID() const; int MaxElementID() const; diff --git a/src/SMDS/SMESH_SMDS.hxx b/src/SMDS/SMESH_SMDS.hxx index 207cf7210..d354e130e 100755 --- a/src/SMDS/SMESH_SMDS.hxx +++ b/src/SMDS/SMESH_SMDS.hxx @@ -36,4 +36,4 @@ #define SMDS_EXPORT #endif -#endif \ No newline at end of file +#endif diff --git a/src/SMESH/SMESH_Algo.hxx b/src/SMESH/SMESH_Algo.hxx index b27055c31..f08fd85e7 100644 --- a/src/SMESH/SMESH_Algo.hxx +++ b/src/SMESH/SMESH_Algo.hxx @@ -260,8 +260,14 @@ public: * \param E2 - the 2nd edge * \retval GeomAbs_Shape - regularity at the junction between E1 and E2 */ - static GeomAbs_Shape Continuity(const TopoDS_Edge & E1, - const TopoDS_Edge & E2); + static GeomAbs_Shape Continuity(const TopoDS_Edge & E1, const TopoDS_Edge & E2); + + /*! + * \brief Return true if an edge can be considered as a continuation of another + */ + static bool IsContinuous(const TopoDS_Edge & E1, const TopoDS_Edge & E2) { + return ( Continuity( E1, E2 ) >= GeomAbs_G1 ); + } /*! * \brief Return the node built on a vertex @@ -279,9 +285,10 @@ protected: */ bool error(int error, const SMESH_Comment& comment = ""); /*! - * \brief To be used as error in previous method + * \brief store COMPERR_ALGO_FAILED error and comment and then return false */ - SMESH_ComputeErrorName dfltErr() const { return COMPERR_ALGO_FAILED; } + bool error(const SMESH_Comment& comment = "") + { return error(COMPERR_ALGO_FAILED, comment); } /*! * \brief store error and return error->IsOK() */ diff --git a/src/SMESH/SMESH_Block.cxx b/src/SMESH/SMESH_Block.cxx index fa7fc282f..dfde6865a 100644 --- a/src/SMESH/SMESH_Block.cxx +++ b/src/SMESH/SMESH_Block.cxx @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -45,6 +46,8 @@ #include #include #include +#include +#include #include "SMDS_MeshNode.hxx" #include "SMDS_MeshVolume.hxx" @@ -55,7 +58,7 @@ using namespace std; -#define SQRT_FUNC 0 +//#define DEBUG_PARAM_COMPUTE //================================================================================ /*! @@ -381,24 +384,37 @@ bool SMESH_Block::ShellPoint(const gp_XYZ& theParams, const vector& p = thePointOnShape; thePoint = - x1 * p[ID_F0yz] + x * p[ID_F1yz] - + y1 * p[ID_Fx0z] + y * p[ID_Fx1z] - + z1 * p[ID_Fxy0] + z * p[ID_Fxy1] - + x1 * (y1 * (z1 * p[ID_V000] + z * p[ID_V001]) - + y * (z1 * p[ID_V010] + z * p[ID_V011])) - + x * (y1 * (z1 * p[ID_V100] + z * p[ID_V101]) - + y * (z1 * p[ID_V110] + z * p[ID_V111])); + x1 * p[ID_F0yz] + x * p[ID_F1yz] + + y1 * p[ID_Fx0z] + y * p[ID_Fx1z] + + z1 * p[ID_Fxy0] + z * p[ID_Fxy1] + + x1 * (y1 * (z1 * p[ID_V000] + z * p[ID_V001]) + + y * (z1 * p[ID_V010] + z * p[ID_V011])) + + x * (y1 * (z1 * p[ID_V100] + z * p[ID_V101]) + + y * (z1 * p[ID_V110] + z * p[ID_V111])); thePoint -= - x1 * (y1 * p[ID_E00z] + y * p[ID_E01z]) - + x * (y1 * p[ID_E10z] + y * p[ID_E11z]) - + y1 * (z1 * p[ID_Ex00] + z * p[ID_Ex01]) - + y * (z1 * p[ID_Ex10] + z * p[ID_Ex11]) - + z1 * (x1 * p[ID_E0y0] + x * p[ID_E1y0]) - + z * (x1 * p[ID_E0y1] + x * p[ID_E1y1]); + x1 * (y1 * p[ID_E00z] + y * p[ID_E01z]) + + x * (y1 * p[ID_E10z] + y * p[ID_E11z]) + + y1 * (z1 * p[ID_Ex00] + z * p[ID_Ex01]) + + y * (z1 * p[ID_Ex10] + z * p[ID_Ex11]) + + z1 * (x1 * p[ID_E0y0] + x * p[ID_E1y0]) + + z * (x1 * p[ID_E0y1] + x * p[ID_E1y1]); return true; } +//======================================================================= +//function : Constructor +//purpose : +//======================================================================= + +SMESH_Block::SMESH_Block(): + myNbIterations(0), + mySumDist(0.), + myTolerance(-1.) // to be re-initialized +{ +} + + //======================================================================= //function : NbVariables //purpose : @@ -428,12 +444,12 @@ Standard_Boolean SMESH_Block::Value(const math_Vector& theXYZ, math_Vector& theF { gp_XYZ P, params( theXYZ(1), theXYZ(2), theXYZ(3) ); if ( params.IsEqual( myParam, DBL_MIN )) { // same param - theFxyz( 1 ) = myValues[ 0 ]; + theFxyz( 1 ) = funcValue( myValues[ SQUARE_DIST ]); } else { ShellPoint( params, P ); gp_Vec dP( P - myPoint ); - theFxyz(1) = SQRT_FUNC ? dP.SquareMagnitude() : dP.Magnitude(); + theFxyz(1) = funcValue( dP.SquareMagnitude() ); } return true; } @@ -445,55 +461,60 @@ Standard_Boolean SMESH_Block::Value(const math_Vector& theXYZ, math_Vector& theF Standard_Boolean SMESH_Block::Derivatives(const math_Vector& XYZ,math_Matrix& Df) { - MESSAGE( "SMESH_Block::Derivatives()"); math_Vector F(1,3); return Values(XYZ,F,Df); } //======================================================================= -//function : Values +//function : GetStateNumber //purpose : //======================================================================= -//#define DEBUG_PARAM_COMPUTE +Standard_Integer SMESH_Block::GetStateNumber () +{ + return 0; //myValues[0] < 1e-1; +} + +//======================================================================= +//function : Values +//purpose : +//======================================================================= Standard_Boolean SMESH_Block::Values(const math_Vector& theXYZ, math_Vector& theFxyz, math_Matrix& theDf) { -// MESSAGE( endl<<"SMESH_Block::Values( "< myPoint), P is defined by the 2 other derivative direction -// int iPrev = ( iP ? iP - 1 : 2 ); -// int iNext = ( iP == 2 ? 0 : iP + 1 ); -// gp_Vec plnNorm = drv[ iPrev ].Crossed( drv [ iNext ] ); -// double Direc = plnNorm * drv[ iP ]; -// if ( Abs(Direc) <= DBL_MIN ) -// theDf( 1, iP + 1 ) = dP * drv[ iP ]; -// else { -// double Dis = plnNorm * P - plnNorm * myPoint; -// theDf( 1, iP + 1 ) = Dis/Direc; -// } +#else + // Distance from P to plane passing through myPoint and defined + // by the 2 other derivative directions: + // like IntAna_IntConicQuad::Perform (const gp_Lin& L, const gp_Pln& P) + // where L is (P -> myPoint), P is defined by the 2 other derivative direction + int iPrev = ( iP ? iP - 1 : 2 ); + int iNext = ( iP == 2 ? 0 : iP + 1 ); + gp_Vec plnNorm = drv[ iPrev ].Crossed( drv [ iNext ] ); + double Direc = plnNorm * drv[ iP ]; + if ( Abs(Direc) <= DBL_MIN ) + theDf( 1, iP + 1 ) = dP * drv[ iP ]; + else { + double Dis = plnNorm * P - plnNorm * myPoint; + theDf( 1, iP + 1 ) = Dis/Direc; + } +#endif } #ifdef DEBUG_PARAM_COMPUTE cout << "F = " << theFxyz(1) << " DRV: " << theDf(1,1) << " " << theDf(1,2) << " " << theDf(1,3) << endl; + myNbIterations +=3; // how many times call ShellPoint() #endif - //myNbIterations +=3; // how many time call ShellPoint() // store better values - myParam = params; - myValues[0]= theFxyz(1); - myValues[1]= theDf(1,1); - myValues[2]= theDf(1,2); - myValues[3]= theDf(1,3); - -// SCRUTE( theFxyz(1) ); -// SCRUTE( theDf( 1,1 )); -// SCRUTE( theDf( 1,2 )); -// SCRUTE( theDf( 1,3 )); + myParam = params; + myValues[SQUARE_DIST]= sqDist; + myValues[DRV_1] = theDf(1,DRV_1); + myValues[DRV_2] = theDf(1,DRV_2); + myValues[DRV_3] = theDf(1,DRV_3); } return true; } +//============================================================================ +//function : computeParameters +//purpose : compute point parameters in the block using math_FunctionSetRoot +//============================================================================ + +bool SMESH_Block::computeParameters(const gp_Pnt& thePoint, + gp_XYZ& theParams, + const gp_XYZ& theParamsHint) +{ + myPoint = thePoint.XYZ(); + + myParam.SetCoord( -1,-1,-1 ); + myValues[ SQUARE_DIST ] = 1e100; + + math_Vector low ( 1, 3, 0.0 ); + math_Vector up ( 1, 3, 1.0 ); + math_Vector tol ( 1, 3, 1e-4 ); + math_Vector start( 1, 3, 0.0 ); + start( 1 ) = theParamsHint.X(); + start( 2 ) = theParamsHint.Y(); + start( 3 ) = theParamsHint.Z(); + + math_FunctionSetRoot paramSearch( *this, tol ); + + mySquareFunc = 0; // large approaching steps + //if ( hasHint ) mySquareFunc = 1; // small approaching steps + + double loopTol = 10 * myTolerance; + int nbLoops = 0; + while ( distance() > loopTol && nbLoops <= 3 ) + { + paramSearch.Perform ( *static_cast(this), + start, low, up ); + start( 1 ) = myParam.X(); + start( 2 ) = myParam.Y(); + start( 3 ) = myParam.Z(); + mySquareFunc = !mySquareFunc; + nbLoops++; + } +#ifdef DEBUG_PARAM_COMPUTE + mySumDist += distance(); + cout << " ------ SOLUTION: ( "<< myParam.X() <<" "<< myParam.Y() <<" "<< myParam.Z() <<" )"< 0 ) + theParams.SetCoord( myFaceIndex, myFaceParam ); + + return true; +} + //======================================================================= //function : ComputeParameters //purpose : compute point parameters in the block @@ -558,7 +631,8 @@ Standard_Boolean SMESH_Block::Values(const math_Vector& theXYZ, bool SMESH_Block::ComputeParameters(const gp_Pnt& thePoint, gp_XYZ& theParams, - const int theShapeID) + const int theShapeID, + const gp_XYZ& theParamsHint) { if ( VertexParameters( theShapeID, theParams )) return true; @@ -575,19 +649,17 @@ bool SMESH_Block::ComputeParameters(const gp_Pnt& thePoint, return false; } -// MESSAGE( endl<<"SMESH_Block::ComputeParameters( " -// <X(); - start( 2 ) = bestParam->Y(); - start( 3 ) = bestParam->Z(); + start = *bestParam; } - myFaceIndex = -1; + int myFaceIndex = -1; + double myFaceParam = 0.; if ( isOnFace ) { // put a point on the face for ( int iCoord = 0; iCoord < 3; iCoord++ ) if ( coef[ iCoord ] ) { - myFaceIndex = iCoord; - myFaceParam = ( coef[ myFaceIndex ] < 0.5 ) ? 0.0 : 1.0; - start( iCoord + 1 ) = myFaceParam; + myFaceIndex = iCoord + 1; + myFaceParam = ( coef[ iCoord ] < 0.5 ) ? 0.0 : 1.0; + start.SetCoord( myFaceIndex, myFaceParam ); } } - math_Vector low ( 1, 3, 0.0 ); - math_Vector up ( 1, 3, 1.0 ); - math_Vector tol ( 1, 3, 1e-4 ); - math_FunctionSetRoot paramSearch( *this, tol ); #ifdef DEBUG_PARAM_COMPUTE cout << " #### POINT " < 1e-1 && nbLoops++ < 10 ) { - paramSearch.Perform ( *static_cast(this), - start, low, up ); - if ( !paramSearch.IsDone() ) { - //MESSAGE( " !paramSearch.IsDone() " ); + + if ( myTolerance < 0 ) myTolerance = 1e-6; + + const double parDelta = 1e-4; + const double sqTolerance = myTolerance * myTolerance; + + gp_XYZ solution = start, params = start; + double sqDistance = 1e100; + int nbLoops = 0, nbGetWorst = 0; + + while ( nbLoops <= 100 ) + { + gp_XYZ P, Pi; + ShellPoint( params, P ); + + gp_Vec dP( thePoint, P ); + double sqDist = dP.SquareMagnitude(); + + if ( sqDist > sqDistance ) { // solution get worse + if ( ++nbGetWorst > 2 ) + return computeParameters( thePoint, theParams, solution ); } - else { - //MESSAGE( " NB ITERATIONS: " << paramSearch.NbIterations() ); +#ifdef DEBUG_PARAM_COMPUTE + cout << "PARAMS: ( " << params.X() <<" "<< params.Y() <<" "<< params.Z() <<" )"<< endl; + cout << "DIST: " << sqrt( sqDist ) << endl; +#endif + + if ( sqDist < sqDistance ) { // get better + sqDistance = sqDist; + solution = params; + nbGetWorst = 0; + if ( sqDistance < sqTolerance ) // a solution found + break; } - start( 1 ) = myParam.X(); - start( 2 ) = myParam.Y(); - start( 3 ) = myParam.Z(); - //MESSAGE( "Distance: " << ( SQRT_FUNC ? sqrt(myValues[0]) : myValues[0] )); + + // look for a next better solution + for ( int iP = 1; iP <= 3; iP++ ) { + if ( iP == myFaceIndex ) + continue; + // see where we move with a small (=parDelta) step in this direction + gp_XYZ nearParams = params; + bool onEdge = ( params.Coord( iP ) + parDelta > 1. ); + if ( onEdge ) + nearParams.SetCoord( iP, params.Coord( iP ) - parDelta ); + else + nearParams.SetCoord( iP, params.Coord( iP ) + parDelta ); + ShellPoint( nearParams, Pi ); + gp_Vec dPi ( P, Pi ); + if ( onEdge ) dPi *= -1.; + // modify a parameter + double mag = dPi.Magnitude(); + if ( mag < DBL_MIN ) + continue; + gp_Vec dir = dPi / mag; // dir we move modifying the parameter + double dist = dir * dP; // where we should get to + double dPar = dist / mag * parDelta; // predict parameter change + double curPar = params.Coord( iP ); + double par = curPar - dPar; // new parameter value + while ( par > 1 || par < 0 ) { + dPar /= 2.; + par = curPar - dPar; + } + params.SetCoord( iP, par ); + } + + nbLoops++; } #ifdef DEBUG_PARAM_COMPUTE - cout << "-------SOLUTION-------: " << endl - << myParam.X() << " " << myParam.Y() << " " << myParam.Z() << endl - << " ------ DIST :" << myValues[0] << endl; + myNbIterations += nbLoops*4; // how many times ShellPoint called + mySumDist += sqrt( sqDistance ); + cout << " ------ SOLUTION: ( "<= 0 ) - myParam.SetCoord( myFaceIndex + 1, myFaceParam ); + theParams = solution; - theParams = myParam; + if ( myFaceIndex > 0 ) + theParams.SetCoord( myFaceIndex, myFaceParam ); return true; } @@ -734,18 +860,6 @@ bool SMESH_Block::EdgeParameters(const int theEdgeID, const double theU, gp_XYZ& return false; } -//======================================================================= -//function : GetStateNumber -//purpose : -//======================================================================= - -Standard_Integer SMESH_Block::GetStateNumber () -{ -// MESSAGE( endl<<"SMESH_Block::GetStateNumber( "< edgeIdVec(4, -1); GetFaceEdgesIDs( iF, edgeIdVec ); - tFace.Set( iF, myEdge[ edgeIdVec [ 0 ]], myEdge[ edgeIdVec [ 1 ]]); + tFace.Set( iF, myEdge[ edgeIdVec [ 0 ] - ID_Ex00], myEdge[ edgeIdVec [ 1 ] - ID_Ex00]); } return true; @@ -1593,4 +1707,3 @@ void SMESH_Block::GetEdgeVertexIDs (const int edgeID, vector< int >& vertexVec ) MESSAGE(" GetEdgeVertexIDs(), wrong edge ID: " << edgeID ); } } - diff --git a/src/SMESH/SMESH_Block.hxx b/src/SMESH/SMESH_Block.hxx index 392160279..c5bbc1e2f 100644 --- a/src/SMESH/SMESH_Block.hxx +++ b/src/SMESH/SMESH_Block.hxx @@ -27,22 +27,19 @@ #include "SMESH_SMESH.hxx" -#include -#include -#include +//#include +//#include +//#include + #include #include #include #include #include #include -#include -#include #include #include #include -#include -#include #include #include @@ -53,6 +50,7 @@ class SMDS_MeshNode; class Adaptor3d_Surface; class Adaptor2d_Curve2d; class Adaptor3d_Curve; +class gp_Pnt; // ========================================================= // class calculating coordinates of 3D points by normalized @@ -147,7 +145,7 @@ class SMESH_EXPORT SMESH_Block: public math_FunctionSetWithDerivatives // Initialization // --------------- - SMESH_Block (): myNbIterations(0), mySumDist(0.) {} + SMESH_Block(); bool LoadBlockShapes(const TopoDS_Shell& theShell, const TopoDS_Vertex& theVertex000, @@ -242,7 +240,8 @@ public: bool ComputeParameters (const gp_Pnt& thePoint, gp_XYZ& theParams, - const int theShapeID = ID_Shell); + const int theShapeID = ID_Shell, + const gp_XYZ& theParamsHint = gp_XYZ(-1,-1,-1)); // compute point parameters in the block. // Note: for edges, it is better to use EdgeParameters() @@ -362,14 +361,21 @@ public: // for param computation + enum { SQUARE_DIST = 0, DRV_1, DRV_2, DRV_3 }; + double distance () const { return sqrt( myValues[ SQUARE_DIST ]); } + double funcValue(double sqDist) const { return mySquareFunc ? sqDist : sqrt(sqDist); } + bool computeParameters(const gp_Pnt& thePoint, gp_XYZ& theParams, const gp_XYZ& theParamsHint); + int myFaceIndex; double myFaceParam; int myNbIterations; double mySumDist; + double myTolerance; + bool mySquareFunc; gp_XYZ myPoint; // the given point gp_XYZ myParam; // the best parameters guess - double myValues[ 4 ]; // values computed at myParam: function value and 3 derivatives + double myValues[ 4 ]; // values computed at myParam: square distance and 3 derivatives typedef pair TxyzPair; TxyzPair my3x3x3GridNodes[ 27 ]; // to compute the first param guess diff --git a/src/SMESH/SMESH_Gen.cxx b/src/SMESH/SMESH_Gen.cxx index 3c34f2e63..f3f25d9e2 100644 --- a/src/SMESH/SMESH_Gen.cxx +++ b/src/SMESH/SMESH_Gen.cxx @@ -322,7 +322,11 @@ static bool checkMissing(SMESH_Gen* aGen, if ( status == SMESH_Hypothesis::HYP_BAD_PARAMETER ) { INFOS( "ERROR: hypothesis of " << (IsGlobalHypothesis ? "Global " : "Local ") << "<" << algo->GetName() << "> has a bad parameter value"); - errName = SMESH_Hypothesis::HYP_BAD_PARAMETER; + errName = status; + } else if ( status == SMESH_Hypothesis::HYP_BAD_GEOMETRY ) { + INFOS( "ERROR: " << (IsGlobalHypothesis ? "Global " : "Local ") + << "<" << algo->GetName() << "> assigned to mismatching geometry"); + errName = status; } else { INFOS( "ERROR: " << (IsGlobalHypothesis ? "Global " : "Local ") << "<" << algo->GetName() << "> misses some hypothesis"); diff --git a/src/SMESH/SMESH_HypoFilter.hxx b/src/SMESH/SMESH_HypoFilter.hxx index ca883167e..041166d41 100644 --- a/src/SMESH/SMESH_HypoFilter.hxx +++ b/src/SMESH/SMESH_HypoFilter.hxx @@ -78,9 +78,15 @@ class SMESH_EXPORT SMESH_HypoFilter: public SMESH_HypoPredicate static SMESH_HypoPredicate* HasDim(const int theDim); static SMESH_HypoPredicate* HasType(const int theHypType); + /*! + * \brief check aHyp or/and aShape it is assigned to + */ bool IsOk (const SMESH_Hypothesis* aHyp, const TopoDS_Shape& aShape) const; - // check aHyp or/and aShape it is assigned to + /*! + * \brief return true if contains no predicates + */ + bool IsAny() const { return myPredicates.empty(); } ~SMESH_HypoFilter(); diff --git a/src/SMESH/SMESH_Mesh.cxx b/src/SMESH/SMESH_Mesh.cxx index 0f464bf0f..a2a4dcbb5 100644 --- a/src/SMESH/SMESH_Mesh.cxx +++ b/src/SMESH/SMESH_Mesh.cxx @@ -153,7 +153,6 @@ void SMESH_Mesh::ShapeToMesh(const TopoDS_Shape & aShape) i_gr++; } _mapAncestors.Clear(); - _mapPropagationChains.Clear(); // clear SMESHDS TopoDS_Shape aNullShape; @@ -363,6 +362,10 @@ SMESH_Hypothesis::Hypothesis_Status if ( ret < aBestRet ) aBestRet = ret; } + // bind hypotheses to a group just to know + SMESH_Hypothesis *anHyp = _gen->GetStudyContext(_studyId)->mapHypothesis[anHypId]; + GetMeshDS()->AddHypothesis( aSubShape, anHyp ); + if ( SMESH_Hypothesis::IsStatusFatal( aBestRet )) return aBestRet; return aWorstNotFatal; @@ -466,6 +469,9 @@ SMESH_Hypothesis::Hypothesis_Status if ( ret < aBestRet ) aBestRet = ret; } + SMESH_Hypothesis *anHyp = _gen->GetStudyContext(_studyId)->mapHypothesis[anHypId]; + GetMeshDS()->RemoveHypothesis( aSubShape, anHyp ); + if ( SMESH_Hypothesis::IsStatusFatal( aBestRet )) return aBestRet; return aWorstNotFatal; @@ -859,9 +865,6 @@ void SMESH_Mesh::NotifySubMeshesHypothesisModification(const SMESH_Hypothesis* h { aSubMesh->AlgoStateEngine(SMESH_subMesh::MODIF_HYP, const_cast< SMESH_Hypothesis*>( hyp )); - - if ( algo->GetDim() == 1 && IsPropagationHypothesis( aSubShape )) - CleanMeshOnPropagationChain( aSubShape ); } } } @@ -1289,279 +1292,6 @@ void SMESH_Mesh::RemoveGroup (const int theGroupID) _mapGroup.erase (theGroupID); } -//============================================================================= -/*! - * IsLocal1DHypothesis - * Returns a local 1D hypothesis used for theEdge - */ -//============================================================================= -const SMESH_Hypothesis* SMESH_Mesh::IsLocal1DHypothesis (const TopoDS_Shape& theEdge) -{ - SMESH_HypoFilter hypo ( SMESH_HypoFilter::HasDim( 1 )); - hypo.AndNot( hypo.IsAlgo() ).AndNot( hypo.IsAssignedTo( GetMeshDS()->ShapeToMesh() )); - - return GetHypothesis( theEdge, hypo, true ); -} - -//============================================================================= -/*! - * IsPropagationHypothesis - */ -//============================================================================= -bool SMESH_Mesh::IsPropagationHypothesis (const TopoDS_Shape& theEdge) -{ - return _mapPropagationChains.Contains(theEdge); -} - -//============================================================================= -/*! - * IsPropagatedHypothesis - */ -//============================================================================= -bool SMESH_Mesh::IsPropagatedHypothesis (const TopoDS_Shape& theEdge, - TopoDS_Shape& theMainEdge) -{ - int nbChains = _mapPropagationChains.Extent(); - for (int i = 1; i <= nbChains; i++) { - //const TopTools_IndexedMapOfShape& aChain = _mapPropagationChains.FindFromIndex(i); - const SMESH_IndexedMapOfShape& aChain = _mapPropagationChains.FindFromIndex(i); - if (aChain.Contains(theEdge)) { - theMainEdge = _mapPropagationChains.FindKey(i); - return true; - } - } - - return false; -} -//============================================================================= -/*! - * IsReversedInChain - */ -//============================================================================= - -bool SMESH_Mesh::IsReversedInChain (const TopoDS_Shape& theEdge, - const TopoDS_Shape& theMainEdge) -{ - if ( !theMainEdge.IsNull() && !theEdge.IsNull() && - _mapPropagationChains.Contains( theMainEdge )) - { - const SMESH_IndexedMapOfShape& aChain = - _mapPropagationChains.FindFromKey( theMainEdge ); - int index = aChain.FindIndex( theEdge ); - if ( index ) - return aChain(index).Orientation() == TopAbs_REVERSED; - } - return false; -} - -//============================================================================= -/*! - * CleanMeshOnPropagationChain - */ -//============================================================================= -void SMESH_Mesh::CleanMeshOnPropagationChain (const TopoDS_Shape& theMainEdge) -{ - const SMESH_IndexedMapOfShape& aChain = _mapPropagationChains.FindFromKey(theMainEdge); - int i, nbEdges = aChain.Extent(); - for (i = 1; i <= nbEdges; i++) { - TopoDS_Shape anEdge = aChain.FindKey(i); - SMESH_subMesh *subMesh = GetSubMesh(anEdge); - SMESHDS_SubMesh *subMeshDS = subMesh->GetSubMeshDS(); - if (subMeshDS && subMeshDS->NbElements() > 0) { - subMesh->ComputeStateEngine(SMESH_subMesh::CLEAN); - } - } -} - -//============================================================================= -/*! - * RebuildPropagationChains - * Rebuild all existing propagation chains. - * Have to be used, if 1D hypothesis have been assigned/removed to/from any edge - */ -//============================================================================= -bool SMESH_Mesh::RebuildPropagationChains() -{ - bool ret = true; - - // Clean all chains, because they can be not up-to-date - int i, nbChains = _mapPropagationChains.Extent(); - for (i = 1; i <= nbChains; i++) { - TopoDS_Shape aMainEdge = _mapPropagationChains.FindKey(i); - CleanMeshOnPropagationChain(aMainEdge); - _mapPropagationChains.ChangeFromIndex(i).Clear(); - } - - // Build all chains - for (i = 1; i <= nbChains; i++) { - TopoDS_Shape aMainEdge = _mapPropagationChains.FindKey(i); - if (!BuildPropagationChain(aMainEdge)) - ret = false; - CleanMeshOnPropagationChain(aMainEdge); - } - - return ret; -} - -//============================================================================= -/*! - * RemovePropagationChain - * Have to be used, if Propagation hypothesis is removed from - */ -//============================================================================= -bool SMESH_Mesh::RemovePropagationChain (const TopoDS_Shape& theMainEdge) -{ - if (!_mapPropagationChains.Contains(theMainEdge)) - return false; - - // Clean mesh elements and nodes, built on the chain - CleanMeshOnPropagationChain(theMainEdge); - - // Clean the chain - _mapPropagationChains.ChangeFromKey(theMainEdge).Clear(); - - // Remove the chain from the map - int i = _mapPropagationChains.FindIndex(theMainEdge); - if ( i == _mapPropagationChains.Extent() ) - _mapPropagationChains.RemoveLast(); - else { - TopoDS_Vertex anEmptyShape; - BRep_Builder BB; - BB.MakeVertex(anEmptyShape, gp_Pnt(0,0,0), 0.1); - SMESH_IndexedMapOfShape anEmptyMap; - _mapPropagationChains.Substitute(i, anEmptyShape, anEmptyMap); - } - - return true; -} - -//============================================================================= -/*! - * BuildPropagationChain - */ -//============================================================================= -bool SMESH_Mesh::BuildPropagationChain (const TopoDS_Shape& theMainEdge) -{ - if (theMainEdge.ShapeType() != TopAbs_EDGE) return true; - - // Add new chain, if there is no - if (!_mapPropagationChains.Contains(theMainEdge)) { - SMESH_IndexedMapOfShape aNewChain; - _mapPropagationChains.Add(theMainEdge, aNewChain); - } - - // Check presence of 1D hypothesis to be propagated - const SMESH_Hypothesis* aMainHyp = IsLocal1DHypothesis(theMainEdge); - if (!aMainHyp) { - MESSAGE("Warning: There is no 1D hypothesis to propagate. Please, assign."); - return true; - } - - // Edges, on which the 1D hypothesis will be propagated from - SMESH_IndexedMapOfShape& aChain = _mapPropagationChains.ChangeFromKey(theMainEdge); - if (aChain.Extent() > 0) { - CleanMeshOnPropagationChain(theMainEdge); - aChain.Clear(); - } - - // At first put in the chain - aChain.Add(theMainEdge); - - // List of edges, added to chain on the previous cycle pass - TopTools_ListOfShape listPrevEdges; - listPrevEdges.Append(theMainEdge.Oriented( TopAbs_FORWARD )); - -// 5____4____3____4____5____6 -// | | | | | | -// | | | | | | -// 4____3____2____3____4____5 -// | | | | | | Number in the each knot of -// | | | | | | grid indicates cycle pass, -// 3____2____1____2____3____4 on which corresponding edge -// | | | | | | (perpendicular to the plane -// | | | | | | of view) will be found. -// 2____1____0____1____2____3 -// | | | | | | -// | | | | | | -// 3____2____1____2____3____4 - - // Collect all edges pass by pass - while (listPrevEdges.Extent() > 0) { - // List of edges, added to chain on this cycle pass - TopTools_ListOfShape listCurEdges; - - // Find the next portion of edges - TopTools_ListIteratorOfListOfShape itE (listPrevEdges); - for (; itE.More(); itE.Next()) { - TopoDS_Shape anE = itE.Value(); - - // Iterate on faces, having edge - TopTools_ListIteratorOfListOfShape itA (GetAncestors(anE)); - for (; itA.More(); itA.Next()) { - TopoDS_Shape aW = itA.Value(); - - // There are objects of different type among the ancestors of edge - if (aW.ShapeType() == TopAbs_WIRE) { - TopoDS_Shape anOppE; - - BRepTools_WireExplorer aWE (TopoDS::Wire(aW)); - Standard_Integer nb = 1, found = 0; - TopTools_Array1OfShape anEdges (1,4); - for (; aWE.More(); aWE.Next(), nb++) { - if (nb > 4) { - found = 0; - break; - } - anEdges(nb) = aWE.Current(); - if (!_mapAncestors.Contains(anEdges(nb))) { - MESSAGE("WIRE EXPLORER HAVE GIVEN AN INVALID EDGE !!!"); - break; - } - if (anEdges(nb).IsSame(anE)) found = nb; - } - - if (nb == 5 && found > 0) { - // Quadrangle face found, get an opposite edge - Standard_Integer opp = found + 2; - if (opp > 4) opp -= 4; - anOppE = anEdges(opp); - - // add anOppE to aChain if ... - if (!aChain.Contains(anOppE)) { // ... anOppE is not in aChain - if (!IsLocal1DHypothesis(anOppE)) { // ... no other 1d hyp on anOppE - TopoDS_Shape aMainEdgeForOppEdge; // ... no other hyp is propagated to anOppE - if (!IsPropagatedHypothesis(anOppE, aMainEdgeForOppEdge)) - { - // Add found edge to the chain oriented so that to - // have it co-directed with a forward MainEdge - TopAbs_Orientation ori = anE.Orientation(); - if ( anEdges(opp).Orientation() == anEdges(found).Orientation() ) - ori = TopAbs::Reverse( ori ); - anOppE.Orientation( ori ); - aChain.Add(anOppE); - listCurEdges.Append(anOppE); - } - else { - // Collision! - MESSAGE("Error: Collision between propagated hypotheses"); - CleanMeshOnPropagationChain(theMainEdge); - aChain.Clear(); - return ( aMainHyp == IsLocal1DHypothesis(aMainEdgeForOppEdge) ); - } - } - } - } // if (nb == 5 && found > 0) - } // if (aF.ShapeType() == TopAbs_WIRE) - } // for (; itF.More(); itF.Next()) - } // for (; itE.More(); itE.Next()) - - listPrevEdges = listCurEdges; - } // while (listPrevEdges.Extent() > 0) - - CleanMeshOnPropagationChain(theMainEdge); - return true; -} - //======================================================================= //function : GetAncestors //purpose : return list of ancestors of theSubShape in the order @@ -1581,6 +1311,7 @@ const TopTools_ListOfShape& SMESH_Mesh::GetAncestors(const TopoDS_Shape& theS) c //function : Dump //purpose : dumps contents of mesh to stream [ debug purposes ] //======================================================================= + ostream& SMESH_Mesh::Dump(ostream& save) { int clause = 0; @@ -1653,6 +1384,7 @@ ostream& SMESH_Mesh::Dump(ostream& save) //function : GetElementType //purpose : Returns type of mesh element with certain id //======================================================================= + SMDSAbs_ElementType SMESH_Mesh::GetElementType( const int id, const bool iselem ) { return _myMeshDS->GetElementType( id, iselem ); diff --git a/src/SMESH/SMESH_Mesh.hxx b/src/SMESH/SMESH_Mesh.hxx index d9538fe86..ba122d08b 100644 --- a/src/SMESH/SMESH_Mesh.hxx +++ b/src/SMESH/SMESH_Mesh.hxx @@ -237,30 +237,7 @@ public: void RemoveGroup (const int theGroupID); - // Propagation hypothesis management - - const SMESH_Hypothesis* IsLocal1DHypothesis (const TopoDS_Shape& theEdge); - // Returns a local 1D hypothesis used for theEdge. - - bool IsPropagationHypothesis (const TopoDS_Shape& theEdge); - // Returns true, if a local Propagation hypothesis is set directly on - - bool IsPropagatedHypothesis (const TopoDS_Shape& theEdge, - TopoDS_Shape& theMainEdge); - // Returns true, if a local 1D hypothesis is - // propagated on from some other edge. - // Returns through the edge, from - // which the 1D hypothesis is propagated on - - bool IsReversedInChain (const TopoDS_Shape& theEdge, - const TopoDS_Shape& theMainEdge); - // Returns true if theEdge should be reversed to be - // co-directed with theMainEdge - - bool RebuildPropagationChains(); - bool RemovePropagationChain (const TopoDS_Shape& theMainEdge); - bool BuildPropagationChain (const TopoDS_Shape& theMainEdge); - + SMDSAbs_ElementType GetElementType( const int id, const bool iselem ); // @@ -268,9 +245,6 @@ public: ostream& Dump(ostream & save); private: - // Propagation hypothesis management - void CleanMeshOnPropagationChain(const TopoDS_Shape& theMainEdge); - // protected: int _id; // id given by creator (unique within the creator instance) @@ -287,8 +261,6 @@ protected: TopTools_IndexedDataMapOfShapeListOfShape _mapAncestors; - IndexedMapOfChain _mapPropagationChains; // Propagation hypothesis management - protected: SMESH_Mesh() {}; SMESH_Mesh(const SMESH_Mesh&) {}; diff --git a/src/SMESH/SMESH_MeshEditor.cxx b/src/SMESH/SMESH_MeshEditor.cxx index 5ff5f6d17..8c2eec106 100644 --- a/src/SMESH/SMESH_MeshEditor.cxx +++ b/src/SMESH/SMESH_MeshEditor.cxx @@ -269,18 +269,26 @@ bool SMESH_MeshEditor::Remove (const list< int >& theIDs, if ( !elem ) continue; - // Find sub-meshes to notify about modification - SMDS_ElemIteratorPtr nodeIt = elem->nodesIterator(); - while ( nodeIt->more() ) { - const SMDS_MeshNode* node = static_cast( nodeIt->next() ); - const SMDS_PositionPtr& aPosition = node->GetPosition(); - if ( aPosition.get() ) { - if ( int aShapeID = aPosition->GetShapeId() ) { + // Notify VERTEX sub-meshes about modification + if ( isNodes ) { + const SMDS_MeshNode* node = cast2Node( elem ); + if ( node->GetPosition()->GetTypeOfPosition() == SMDS_TOP_VERTEX ) + if ( int aShapeID = node->GetPosition()->GetShapeId() ) if ( SMESH_subMesh * sm = GetMesh()->GetSubMeshContaining( aShapeID ) ) smmap.insert( sm ); - } - } } + // Find sub-meshes to notify about modification +// SMDS_ElemIteratorPtr nodeIt = elem->nodesIterator(); +// while ( nodeIt->more() ) { +// const SMDS_MeshNode* node = static_cast( nodeIt->next() ); +// const SMDS_PositionPtr& aPosition = node->GetPosition(); +// if ( aPosition.get() ) { +// if ( int aShapeID = aPosition->GetShapeId() ) { +// if ( SMESH_subMesh * sm = GetMesh()->GetSubMeshContaining( aShapeID ) ) +// smmap.insert( sm ); +// } +// } +// } // Do remove if ( isNodes ) @@ -296,9 +304,9 @@ bool SMESH_MeshEditor::Remove (const list< int >& theIDs, (*smIt)->ComputeStateEngine( SMESH_subMesh::MESH_ENTITY_REMOVED ); } - // Check if the whole mesh becomes empty - if ( SMESH_subMesh * sm = GetMesh()->GetSubMeshContaining( 1 ) ) - sm->ComputeStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE ); +// // Check if the whole mesh becomes empty +// if ( SMESH_subMesh * sm = GetMesh()->GetSubMeshContaining( 1 ) ) +// sm->ComputeStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE ); return true; } @@ -5729,7 +5737,7 @@ SMESH_MeshEditor::Sew_Error { nodeGroupsToMerge.push_back( list() ); nodeGroupsToMerge.back().push_back( *nIt[1] ); // to keep - nodeGroupsToMerge.back().push_back( *nIt[0] ); // tp remove + nodeGroupsToMerge.back().push_back( *nIt[0] ); // to remove } } else { @@ -7249,7 +7257,9 @@ SMESH_MeshEditor::Sew_Error */ //================================================================================ +#ifdef _DEBUG_ //#define DEBUG_MATCHING_NODES +#endif SMESH_MeshEditor::Sew_Error SMESH_MeshEditor::FindMatchingNodes(set& theSide1, diff --git a/src/SMESH/SMESH_MesherHelper.cxx b/src/SMESH/SMESH_MesherHelper.cxx index 6afe18300..024a93e5d 100644 --- a/src/SMESH/SMESH_MesherHelper.cxx +++ b/src/SMESH/SMESH_MesherHelper.cxx @@ -73,6 +73,7 @@ bool SMESH_MesherHelper::IsQuadraticSubMesh(const TopoDS_Shape& aSh) // also we have to fill myNLinkNodeMap myCreateQuadratic = true; mySeamShapeIds.clear(); + myDegenShapeIds.clear(); TopAbs_ShapeEnum subType( aSh.ShapeType()==TopAbs_FACE ? TopAbs_EDGE : TopAbs_FACE ); SMDSAbs_ElementType elemType( subType==TopAbs_FACE ? SMDSAbs_Face : SMDSAbs_Edge ); @@ -150,6 +151,7 @@ void SMESH_MesherHelper::SetSubShape(const TopoDS_Shape& aSh) myShape = aSh; mySeamShapeIds.clear(); + myDegenShapeIds.clear(); if ( myShape.IsNull() ) { myShapeID = -1; @@ -165,8 +167,9 @@ void SMESH_MesherHelper::SetSubShape(const TopoDS_Shape& aSh) BRepAdaptor_Surface surface( face ); if ( surface.IsUPeriodic() || surface.IsVPeriodic() ) { - // look for a seam edge - for ( TopExp_Explorer exp( face, TopAbs_EDGE ); exp.More(); exp.Next()) { + for ( TopExp_Explorer exp( face, TopAbs_EDGE ); exp.More(); exp.Next()) + { + // look for a seam edge const TopoDS_Edge& edge = TopoDS::Edge( exp.Current() ); if ( BRep_Tool::IsClosed( edge, face )) { // initialize myPar1, myPar2 and myParIndex @@ -186,10 +189,17 @@ void SMESH_MesherHelper::SetSubShape(const TopoDS_Shape& aSh) } } // store shapes indices - mySeamShapeIds.insert( meshDS->ShapeToIndex( exp.Current() )); - for ( TopExp_Explorer v( exp.Current(), TopAbs_VERTEX ); v.More(); v.Next() ) + mySeamShapeIds.insert( meshDS->ShapeToIndex( edge )); + for ( TopExp_Explorer v( edge, TopAbs_VERTEX ); v.More(); v.Next() ) mySeamShapeIds.insert( meshDS->ShapeToIndex( v.Current() )); } + + // look for a degenerated edge + if ( BRep_Tool::Degenerated( edge )) { + myDegenShapeIds.insert( meshDS->ShapeToIndex( edge )); + for ( TopExp_Explorer v( edge, TopAbs_VERTEX ); v.More(); v.Next() ) + myDegenShapeIds.insert( meshDS->ShapeToIndex( v.Current() )); + } } } } diff --git a/src/SMESH/SMESH_MesherHelper.hxx b/src/SMESH/SMESH_MesherHelper.hxx index 7798a0e12..ad3a1e8f8 100644 --- a/src/SMESH/SMESH_MesherHelper.hxx +++ b/src/SMESH/SMESH_MesherHelper.hxx @@ -244,6 +244,15 @@ public: */ bool GetNodeUVneedInFaceNode(const TopoDS_Face& F = TopoDS_Face()) const; + /*! + * \brief Check if shape is a degenerated edge or it's vertex + * \param subShape - edge or vertex index in SMESHDS + * \retval bool - true if subShape is a degenerated shape + * + * It works only if IsQuadraticSubMesh() or SetSubShape() has been called + */ + bool IsDegenShape(const int subShape) const + { return myDegenShapeIds.find( subShape ) != myDegenShapeIds.end(); } /*! * \brief Check if shape is a seam edge or it's vertex * \param subShape - edge or vertex index in SMESHDS @@ -312,9 +321,10 @@ protected: // Forbiden copy constructor SMESH_MesherHelper (const SMESH_MesherHelper& theOther) {}; - // special map for using during creation quadratic faces + // special map for using during creation of quadratic elements NLinkNodeMap myNLinkNodeMap; + std::set< int > myDegenShapeIds; std::set< int > mySeamShapeIds; double myPar1, myPar2; // bounds of a closed periodic surface int myParIndex; // bounds' index (1-U, 2-V) diff --git a/src/SMESH/SMESH_Pattern.cxx b/src/SMESH/SMESH_Pattern.cxx index 44396d2af..5054f5549 100644 --- a/src/SMESH/SMESH_Pattern.cxx +++ b/src/SMESH/SMESH_Pattern.cxx @@ -962,7 +962,13 @@ static bool intersectIsolines(const gp_XY& uv11, const gp_XY& uv12, const double gp_XY loc1 = uv11 * ( 1 - r1 ) + uv12 * r1; gp_XY loc2 = uv21 * ( 1 - r2 ) + uv22 * r2; resUV = 0.5 * ( loc1 + loc2 ); - isDeformed = ( loc1 - loc2 ).SquareModulus() > 1e-8; + //isDeformed = ( loc1 - loc2 ).SquareModulus() > 1e-8; + // SKL 26.07.2007 for NPAL16567 + double d1 = (uv11-uv12).Modulus(); + double d2 = (uv21-uv22).Modulus(); + double delta = d1*d2*1e-6; + isDeformed = ( loc1 - loc2 ).SquareModulus() > delta; + // double len1 = ( uv11 - uv12 ).Modulus(); // double len2 = ( uv21 - uv22 ).Modulus(); // resUV = loc1 * len2 / ( len1 + len2 ) + loc2 * len1 / ( len1 + len2 ); @@ -2659,6 +2665,162 @@ bool SMESH_Pattern::Apply (const SMDS_MeshFace* theFace, return setErrorCode( ERR_OK ); } +//======================================================================= +//function : Apply +//purpose : Compute nodes coordinates applying +// the loaded pattern to . The first key-point +// will be mapped into -th node +//======================================================================= + +bool SMESH_Pattern::Apply (SMESH_Mesh* theMesh, + const SMDS_MeshFace* theFace, + const TopoDS_Shape& theSurface, + const int theNodeIndexOnKeyPoint1, + const bool theReverse) +{ +// MESSAGE(" ::Apply(MeshFace) " ); + if ( theSurface.IsNull() || theSurface.ShapeType() != TopAbs_FACE ) { + return Apply( theFace, theNodeIndexOnKeyPoint1, theReverse); + } + const TopoDS_Face& face = TopoDS::Face( theSurface ); + TopLoc_Location loc; + Handle(Geom_Surface) surface = BRep_Tool::Surface( face, loc ); + const gp_Trsf & aTrsf = loc.Transformation(); + + if ( !IsLoaded() ) { + MESSAGE( "Pattern not loaded" ); + return setErrorCode( ERR_APPL_NOT_LOADED ); + } + + // check nb of nodes + if (theFace->NbNodes() != myNbKeyPntInBoundary.front() ) { + MESSAGE( myKeyPointIDs.size() << " != " << theFace->NbNodes() ); + return setErrorCode( ERR_APPL_BAD_NB_VERTICES ); + } + + // find points on edges, it fills myNbKeyPntInBoundary + if ( !findBoundaryPoints() ) + return false; + + // check that there are no holes in a pattern + if (myNbKeyPntInBoundary.size() > 1 ) { + return setErrorCode( ERR_APPL_BAD_NB_VERTICES ); + } + + // Define the nodes order + + list< const SMDS_MeshNode* > nodes; + list< const SMDS_MeshNode* >::iterator n = nodes.end(); + SMDS_ElemIteratorPtr noIt = theFace->nodesIterator(); + int iSub = 0; + while ( noIt->more() ) { + const SMDS_MeshNode* node = smdsNode( noIt->next() ); + nodes.push_back( node ); + if ( iSub++ == theNodeIndexOnKeyPoint1 ) + n = --nodes.end(); + } + if ( n != nodes.end() ) { + if ( theReverse ) { + if ( n != --nodes.end() ) + nodes.splice( nodes.begin(), nodes, ++n, nodes.end() ); + nodes.reverse(); + } + else if ( n != nodes.begin() ) + nodes.splice( nodes.end(), nodes, nodes.begin(), n ); + } + + // find a node not on a seam edge, if necessary + SMESH_MesherHelper helper( *theMesh ); + helper.SetSubShape( theSurface ); + const SMDS_MeshNode* inFaceNode = 0; + if ( helper.GetNodeUVneedInFaceNode() ) + { + SMESH_MeshEditor editor( theMesh ); + for ( n = nodes.begin(); ( !inFaceNode && n != nodes.end()); ++n ) { + int shapeID = editor.FindShape( *n ); + if ( !shapeID ) + return Apply( theFace, theNodeIndexOnKeyPoint1, theReverse); + if ( !helper.IsSeamShape( shapeID )) + inFaceNode = *n; + } + } + + // Set UV of key-points (i.e. of nodes of theFace ) + vector< gp_XY > keyUV( theFace->NbNodes() ); + myOrderedNodes.resize( theFace->NbNodes() ); + for ( iSub = 1, n = nodes.begin(); n != nodes.end(); ++n, ++iSub ) + { + TPoint* p = getShapePoints( iSub ).front(); + p->myUV = helper.GetNodeUV( face, *n, inFaceNode ); + p->myXYZ = gp_XYZ( (*n)->X(), (*n)->Y(), (*n)->Z() ); + + keyUV[ iSub-1 ] = p->myUV; + myOrderedNodes[ iSub-1 ] = *n; + } + + // points on edges to be used for UV computation of in-face points + list< list< TPoint* > > edgesPointsList; + edgesPointsList.push_back( list< TPoint* >() ); + list< TPoint* > * edgesPoints = & edgesPointsList.back(); + list< TPoint* >::iterator pIt; + + // compute UV and XYZ of points on edges + + for ( int i = 0; i < myOrderedNodes.size(); ++i, ++iSub ) + { + gp_XY& uv1 = keyUV[ i ]; + gp_XY& uv2 = ( i+1 < keyUV.size() ) ? keyUV[ i+1 ] : keyUV[ 0 ]; + + list< TPoint* > & ePoints = getShapePoints( iSub ); + ePoints.back()->myInitU = 1.0; + list< TPoint* >::const_iterator pIt = ++ePoints.begin(); + while ( *pIt != ePoints.back() ) + { + TPoint* p = *pIt++; + p->myUV = uv1 * ( 1 - p->myInitU ) + uv2 * p->myInitU; + p->myXYZ = surface->Value( p->myUV.X(), p->myUV.Y() ); + if ( !loc.IsIdentity() ) + aTrsf.Transforms( p->myXYZ.ChangeCoord() ); + } + // collect on-edge points (excluding the last one) + edgesPoints->insert( edgesPoints->end(), ePoints.begin(), --ePoints.end()); + } + + // Compute UV and XYZ of in-face points + + // try to use a simple algo to compute UV + list< TPoint* > & fPoints = getShapePoints( iSub ); + bool isDeformed = false; + for ( pIt = fPoints.begin(); !isDeformed && pIt != fPoints.end(); pIt++ ) + if ( !compUVByIsoIntersection( edgesPointsList, (*pIt)->myInitUV, + (*pIt)->myUV, isDeformed )) { + MESSAGE("cant Apply(face)"); + return false; + } + // try to use a complex algo if it is a difficult case + if ( isDeformed && !compUVByElasticIsolines( edgesPointsList, fPoints )) + { + for ( ; pIt != fPoints.end(); pIt++ ) // continue with the simple algo + if ( !compUVByIsoIntersection( edgesPointsList, (*pIt)->myInitUV, + (*pIt)->myUV, isDeformed )) { + MESSAGE("cant Apply(face)"); + return false; + } + } + + for ( pIt = fPoints.begin(); pIt != fPoints.end(); pIt++ ) + { + TPoint * point = *pIt; + point->myXYZ = surface->Value( point->myUV.X(), point->myUV.Y() ); + if ( !loc.IsIdentity() ) + aTrsf.Transforms( point->myXYZ.ChangeCoord() ); + } + + myIsComputed = true; + + return setErrorCode( ERR_OK ); +} + //======================================================================= //function : undefinedXYZ //purpose : @@ -2687,7 +2849,8 @@ inline static bool isDefined(const gp_XYZ& theXYZ) // will be mapped into -th node //======================================================================= -bool SMESH_Pattern::Apply (std::set& theFaces, +bool SMESH_Pattern::Apply (SMESH_Mesh* theMesh, + std::set& theFaces, const int theNodeIndexOnKeyPoint1, const bool theReverse) { @@ -2725,11 +2888,29 @@ bool SMESH_Pattern::Apply (std::set& theFaces, int ind1 = 0; // lowest point index for a face + // meshed geometry + TopoDS_Shape shape; +// int shapeID = 0; +// SMESH_MeshEditor editor( theMesh ); + // apply to each face in theFaces set set::iterator face = theFaces.begin(); for ( ; face != theFaces.end(); ++face ) { - if ( !Apply( *face, theNodeIndexOnKeyPoint1, theReverse )) { +// int curShapeId = editor.FindShape( *face ); +// if ( curShapeId != shapeID ) { +// if ( curShapeId ) +// shape = theMesh->GetMeshDS()->IndexToShape( curShapeId ); +// else +// shape.Nullify(); +// shapeID = curShapeId; +// } + bool ok; + if ( shape.IsNull() ) + ok = Apply( *face, theNodeIndexOnKeyPoint1, theReverse ); + else + ok = Apply( theMesh, *face, shape, theNodeIndexOnKeyPoint1, theReverse ); + if ( !ok ) { MESSAGE( "Failed on " << *face ); continue; } @@ -3905,7 +4086,7 @@ void SMESH_Pattern::createElements(SMESH_Mesh* theMes SMESH_subMesh * subMesh; if ( !myShape.IsNull() ) { - subMesh = theMesh->GetSubMeshContaining( myShape ); + subMesh = theMesh->GetSubMesh( myShape ); if ( subMesh ) subMesh->ComputeStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE ); } diff --git a/src/SMESH/SMESH_Pattern.hxx b/src/SMESH/SMESH_Pattern.hxx index 9699064ad..df1ccd0eb 100644 --- a/src/SMESH/SMESH_Pattern.hxx +++ b/src/SMESH/SMESH_Pattern.hxx @@ -103,7 +103,17 @@ class SMESH_EXPORT SMESH_Pattern { // the loaded pattern to . The first key-point // will be mapped into -th node - bool Apply (std::set& theFaces, + bool Apply (SMESH_Mesh* theMesh, + const SMDS_MeshFace* theFace, + const TopoDS_Shape& theSurface, + const int theNodeIndexOnKeyPoint1, + const bool theReverse); + // Compute nodes coordinates applying + // the loaded pattern to . The first key-point + // will be mapped into -th node + + bool Apply (SMESH_Mesh* theMesh, + std::set& theFaces, const int theNodeIndexOnKeyPoint1, const bool theReverse); // Compute nodes coordinates applying diff --git a/src/SMESH/SMESH_subMesh.cxx b/src/SMESH/SMESH_subMesh.cxx index 6b358d329..e766df8ef 100644 --- a/src/SMESH/SMESH_subMesh.cxx +++ b/src/SMESH/SMESH_subMesh.cxx @@ -53,11 +53,26 @@ #include #include -#include +#include #include using namespace std; +//============================================================================= +/*! + * \brief Allocate some memory at construction and release it at destruction. + * Is used to be able to continue working after mesh generation breaks due to + * lack of memory + */ +//============================================================================= + +struct MemoryReserve +{ + char* myBuf; + MemoryReserve(): myBuf( new char[1024*1024*2] ){} + ~MemoryReserve() { delete [] myBuf; } +}; + //============================================================================= /*! * default constructor: @@ -608,49 +623,6 @@ SMESH_Hypothesis::Hypothesis_Status if ( !meshDS->AddHypothesis(_subShape, anHyp)) return SMESH_Hypothesis::HYP_ALREADY_EXIST; - - // Serve Propagation of 1D hypothesis - // NOTE: it is possible to re-implement Propagation using EventListener - if (event == ADD_HYP) { - bool isPropagationOk = true; - bool isPropagationHyp = ( strcmp( "Propagation", anHyp->GetName() ) == 0 ); - - if ( isPropagationHyp ) { - TopExp_Explorer exp (_subShape, TopAbs_EDGE); - TopTools_MapOfShape aMap; - for (; exp.More(); exp.Next()) { - if (aMap.Add(exp.Current())) { - if (!_father->BuildPropagationChain(exp.Current())) { - isPropagationOk = false; - } - } - } - } - else if (anHyp->GetDim() == 1) { // Only 1D hypothesis can be propagated - TopExp_Explorer exp (_subShape, TopAbs_EDGE); - TopTools_MapOfShape aMap; - for (; exp.More(); exp.Next()) { - if (aMap.Add(exp.Current())) { - TopoDS_Shape aMainEdge; - if (_father->IsPropagatedHypothesis(exp.Current(), aMainEdge)) { - isPropagationOk = _father->RebuildPropagationChains(); - } else if (_father->IsPropagationHypothesis(exp.Current())) { - isPropagationOk = _father->BuildPropagationChain(exp.Current()); - } else { - } - } - } - } else { - } - - if ( isPropagationOk ) { - if ( isPropagationHyp ) - return ret; // nothing more to do for "Propagation" hypothesis - } - else if ( ret < SMESH_Hypothesis::HYP_CONCURENT) { - ret = SMESH_Hypothesis::HYP_CONCURENT; - } - } // Serve Propagation of 1D hypothesis } // -------------------------- @@ -661,45 +633,7 @@ SMESH_Hypothesis::Hypothesis_Status if (!meshDS->RemoveHypothesis(_subShape, anHyp)) return SMESH_Hypothesis::HYP_OK; // nothing changes - // Serve Propagation of 1D hypothesis - // NOTE: it is possible to re-implement Propagation using EventListener - if (event == REMOVE_HYP) - { - bool isPropagationOk = true; - SMESH_HypoFilter propagFilter( SMESH_HypoFilter::HasName( "Propagation" )); - bool isPropagationHyp = propagFilter.IsOk( anHyp, _subShape ); - - if ( isPropagationHyp ) - { - TopExp_Explorer exp (_subShape, TopAbs_EDGE); - TopTools_MapOfShape aMap; - for (; exp.More(); exp.Next()) { - if (aMap.Add(exp.Current()) && - !_father->GetHypothesis( exp.Current(), propagFilter, true )) { - // no more Propagation on the current edge - if (!_father->RemovePropagationChain(exp.Current())) { - return SMESH_Hypothesis::HYP_UNKNOWN_FATAL; - } - } - } - // rebuild propagation chains, because removing one - // chain can resolve concurention, existing before - isPropagationOk = _father->RebuildPropagationChains(); - } - else if (anHyp->GetDim() == 1) // Only 1D hypothesis can be propagated - { - isPropagationOk = _father->RebuildPropagationChains(); - } - - if ( isPropagationOk ) { - if ( isPropagationHyp ) - return ret; // nothing more to do for "Propagation" hypothesis - } - else if ( ret < SMESH_Hypothesis::HYP_CONCURENT) { - ret = SMESH_Hypothesis::HYP_CONCURENT; - } - } // Serve Propagation of 1D hypothesis - else // event == REMOVE_ALGO + if (event == REMOVE_ALGO) { algo = dynamic_cast (anHyp); if (!algo->NeedDescretBoundary()) @@ -1365,7 +1299,8 @@ bool SMESH_subMesh::ComputeStateEngine(int event) _computeState = FAILED_TO_COMPUTE; if ( !algo->NeedDescretBoundary() ) _computeError = - SMESH_ComputeError::New(COMPERR_BAD_INPUT_MESH,"Unexpected submesh",algo); + SMESH_ComputeError::New(COMPERR_BAD_INPUT_MESH, + "Unexpected computed submesh",algo); break; } } @@ -1380,11 +1315,12 @@ bool SMESH_subMesh::ComputeStateEngine(int event) #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100 OCC_CATCH_SIGNALS; #endif + MemoryReserve aMemoryReserve; algo->InitComputeError(); if ( !_father->HasShapeToMesh() ) // no shape { SMESH_MesherHelper helper( *_father ); - helper.SetSubShape( _subShape ); + helper.SetSubShape( shape ); helper.SetElementsOnShape( true ); ret = algo->Compute(*_father, &helper ); } @@ -1393,34 +1329,43 @@ bool SMESH_subMesh::ComputeStateEngine(int event) if (!algo->OnlyUnaryInput()) { shape = GetCollection( gen, algo ); } - if (!algo->NeedDescretBoundary() && !algo->OnlyUnaryInput()) { - ret = ApplyToCollection( algo, shape ); - break; - } - else { - ret = algo->Compute((*_father), shape); - } + ret = algo->Compute((*_father), shape); } if ( !ret ) _computeError = algo->GetComputeError(); } - catch (Standard_Failure& exc) { + catch ( std::bad_alloc& exc ) { + printf("std::bad_alloc\n"); + if ( _computeError ) { + _computeError->myName = COMPERR_MEMORY_PB; + //_computeError->myComment = exc.what(); + } + cleanSubMesh( this ); + throw exc; + } + catch ( Standard_OutOfMemory& exc ) { + printf("Standard_OutOfMemory\n"); + if ( _computeError ) { + _computeError->myName = COMPERR_MEMORY_PB; + //_computeError->myComment = exc.what(); + } + cleanSubMesh( this ); + throw std::bad_alloc(); + } + catch (Standard_Failure& ex) { if ( !_computeError ) _computeError = SMESH_ComputeError::New(); _computeError->myName = COMPERR_OCC_EXCEPTION; - _computeError->myComment = exc.GetMessageString(); + _computeError->myComment += ex.DynamicType()->Name(); + if ( ex.GetMessageString() && strlen( ex.GetMessageString() )) { + _computeError->myComment += ": "; + _computeError->myComment += ex.GetMessageString(); + } } catch ( SALOME_Exception& S_ex ) { if ( !_computeError ) _computeError = SMESH_ComputeError::New(); _computeError->myName = COMPERR_SLM_EXCEPTION; _computeError->myComment = S_ex.what(); } - catch ( std::bad_alloc& exc ) { - if ( _computeError ) { - _computeError->myName = COMPERR_MEMORY_PB; - _computeError->myComment = exc.what(); - } - throw exc; - } catch ( std::exception& exc ) { if ( !_computeError ) _computeError = SMESH_ComputeError::New(); _computeError->myName = COMPERR_STD_EXCEPTION; @@ -1432,28 +1377,25 @@ bool SMESH_subMesh::ComputeStateEngine(int event) else ret = false; } - if ( ret && _computeError && !_computeError->IsOK() ) { - ret = false; - } if (ret && !_alwaysComputed) { // check if anything was built ret = ( GetSubMeshDS() && ( GetSubMeshDS()->NbElements() || GetSubMeshDS()->NbNodes() )); } - if (!ret) + bool isComputeErrorSet = !CheckComputeError( algo, shape ); + if (!ret && !isComputeErrorSet) { // Set _computeError if ( !_computeError ) _computeError = SMESH_ComputeError::New(); if ( _computeError->IsOK() ) _computeError->myName = COMPERR_ALGO_FAILED; + _computeState = FAILED_TO_COMPUTE; } - else + if (ret) { _computeError.reset(); //UpdateDependantsState( SUBMESH_COMPUTED ); // send event SUBMESH_COMPUTED } - //if ( !algo->NeedDescretBoundary() ) - // UpdateSubMeshState( ret ? COMPUTE_OK : FAILED_TO_COMPUTE ); - CheckComputeError( algo, shape ); + UpdateDependantsState( SUBMESH_COMPUTED ); // send event SUBMESH_COMPUTED } break; case CLEAN: @@ -1596,54 +1538,78 @@ bool SMESH_subMesh::ComputeStateEngine(int event) /*! * \brief Update compute_state by _computeError and send proper events to * dependent submeshes + * \retval bool - true if _computeError is NOT set */ //======================================================================= bool SMESH_subMesh::CheckComputeError(SMESH_Algo* theAlgo, const TopoDS_Shape& theShape) { - bool noErrors = ( !_computeError || _computeError->IsOK() ); - if ( !noErrors ) + bool noErrors = true; + + if ( !theShape.IsNull() ) + { + // Check state of submeshes + if ( !theAlgo->NeedDescretBoundary()) + { + SMESH_subMeshIteratorPtr smIt = getDependsOnIterator(false,false); + while ( smIt->more() ) + if ( !smIt->next()->CheckComputeError( theAlgo )) + noErrors = false; + } + + // Check state of neighbours + if ( !theAlgo->OnlyUnaryInput() && + theShape.ShapeType() == TopAbs_COMPOUND && + !theShape.IsSame( _subShape )) + { + for (TopoDS_Iterator subIt( theShape ); subIt.More(); subIt.Next()) { + SMESH_subMesh* sm = _father->GetSubMesh( subIt.Value() ); + if ( sm != this ) { + if ( !sm->CheckComputeError( theAlgo )) + noErrors = false; + UpdateDependantsState( SUBMESH_COMPUTED ); // send event SUBMESH_COMPUTED + } + } + } + } { - if ( !_computeError->myAlgo ) - _computeError->myAlgo = theAlgo; - - // Show error - SMESH_Comment text; - text << theAlgo->GetName() << " failed on subshape " << _Id << " with error "; - if (_computeError->IsCommon() ) - text << _computeError->CommonName(); + // Check my state + if ( !_computeError || _computeError->IsOK() ) + { + _computeState = COMPUTE_OK; + } else - text << _computeError->myName; - if ( _computeError->myComment.size() > 0 ) - text << " \"" << _computeError->myComment << "\""; + { + if ( !_computeError->myAlgo ) + _computeError->myAlgo = theAlgo; + + // Show error + SMESH_Comment text; + text << theAlgo->GetName() << " failed on subshape #" << _Id << " with error "; + if (_computeError->IsCommon() ) + text << _computeError->CommonName(); + else + text << _computeError->myName; + if ( _computeError->myComment.size() > 0 ) + text << " \"" << _computeError->myComment << "\""; #ifdef _DEBUG_ - cout << text << endl; - // Show vertices location of a failed shape - cout << "Subshape vertices (first 10):" << endl; - TopTools_IndexedMapOfShape vMap; - TopExp::MapShapes( _subShape, TopAbs_VERTEX, vMap ); - for ( int iv = 1; iv <= vMap.Extent() && iv < 11; ++iv ) { - gp_Pnt P( BRep_Tool::Pnt( TopoDS::Vertex( vMap( iv ) ))); - cout << P.X() << " " << P.Y() << " " << P.Z() << " " << endl; - } + cout << text << endl; + // Show vertices location of a failed shape + TopTools_IndexedMapOfShape vMap; + TopExp::MapShapes( _subShape, TopAbs_VERTEX, vMap ); + cout << "Subshape vertices " << ( vMap.Extent()>10 ? "(first 10):" : ":") << endl; + for ( int iv = 1; iv <= vMap.Extent() && iv < 11; ++iv ) { + gp_Pnt P( BRep_Tool::Pnt( TopoDS::Vertex( vMap( iv ) ))); + cout << "#" << _father->GetMeshDS()->ShapeToIndex( vMap( iv )) << " "; + cout << P.X() << " " << P.Y() << " " << P.Z() << " " << endl; + } #else - INFOS( text ); + INFOS( text ); #endif - _computeState = FAILED_TO_COMPUTE; - } - else - { - _computeState = COMPUTE_OK; - UpdateDependantsState( SUBMESH_COMPUTED ); // send event SUBMESH_COMPUTED - } - // Check state of submeshes - if ( !theAlgo->NeedDescretBoundary() ) - { - SMESH_subMeshIteratorPtr smIt = getDependsOnIterator(false,false); - while ( smIt->more() ) - if ( !smIt->next()->CheckComputeError( theAlgo )) - noErrors = false; + _computeState = FAILED_TO_COMPUTE; + noErrors = false; + } } if ( !theAlgo->OnlyUnaryInput() && !theShape.IsNull() && theShape.ShapeType() == TopAbs_COMPOUND ) diff --git a/src/SMESHDS/SMESHDS_SubMesh.hxx b/src/SMESHDS/SMESHDS_SubMesh.hxx index 1231c490c..fa885cefd 100644 --- a/src/SMESHDS/SMESHDS_SubMesh.hxx +++ b/src/SMESHDS/SMESHDS_SubMesh.hxx @@ -48,6 +48,7 @@ class SMESHDS_EXPORT SMESHDS_SubMesh void AddSubMesh( const SMESHDS_SubMesh* theSubMesh ); bool RemoveSubMesh( const SMESHDS_SubMesh* theSubMesh ); bool ContainsSubMesh( const SMESHDS_SubMesh* theSubMesh ) const; + int NbSubMeshes() const { return mySubMeshes.size(); } // for both types int NbElements() const; diff --git a/src/SMESHDS/SMESH_SMESHDS.hxx b/src/SMESHDS/SMESH_SMESHDS.hxx index fdef18da9..6747798ef 100755 --- a/src/SMESHDS/SMESH_SMESHDS.hxx +++ b/src/SMESHDS/SMESH_SMESHDS.hxx @@ -36,4 +36,4 @@ #define SMESHDS_EXPORT #endif -#endif \ No newline at end of file +#endif diff --git a/src/SMESHGUI/SMESHGUI.cxx b/src/SMESHGUI/SMESHGUI.cxx index 89ce6fe7a..9cedb02fa 100644 --- a/src/SMESHGUI/SMESHGUI.cxx +++ b/src/SMESHGUI/SMESHGUI.cxx @@ -308,7 +308,7 @@ using namespace std; there must be check on others mesh elements not equal triangles */ if (aMesh->NbTriangles() < 1) { - int aRet = SUIT_MessageBox::warn1 + SUIT_MessageBox::warn1 (SMESHGUI::desktop(), QObject::tr("SMESH_WRN_WARNING"), QObject::tr("SMESH_EXPORT_STL1").arg(anIObject->getName()), @@ -1857,17 +1857,18 @@ bool SMESHGUI::OnGUIEvent( int theCommandID ) int nbSel = selected.Extent(); if (nbSel == 1) { - SMESH::SMESH_Hypothesis_var Hyp = SMESH::IObjectToInterface(selected.First()); + Handle(SALOME_InteractiveObject) anIObject = selected.First(); + SMESH::SMESH_Hypothesis_var aHypothesis = SMESH::IObjectToInterface(anIObject); /* Look for all mesh objects that have this hypothesis affected in order to flag as ModifiedMesh */ /* At end below '...->updateObjBrowser(true)' will change icon of mesh objects */ /* Warning : however by internal mechanism all subMeshes icons are changed ! */ - if ( !Hyp->_is_nil() ) + if ( !aHypothesis->_is_nil() ) { - char* sName = Hyp->GetName(); - SMESHGUI_GenericHypothesisCreator* aCreator = SMESH::GetHypothesisCreator(sName); + CORBA::String_var aHypType = aHypothesis->GetName(); + SMESHGUI_GenericHypothesisCreator* aCreator = SMESH::GetHypothesisCreator(aHypType); if (aCreator) - aCreator->edit( Hyp.in(), desktop() ); + aCreator->edit( aHypothesis.in(), anIObject->getName(), desktop() ); else { // report error @@ -3097,7 +3098,7 @@ void SMESHGUI::createPreferences() int exportgroup = addPreference( tr( "PREF_GROUP_EXPORT" ), genTab ); addPreference( tr( "PREF_AUTO_GROUPS" ), exportgroup, LightApp_Preferences::Bool, "SMESH", "auto_groups" ); - int renumber=addPreference( tr( "PREF_RENUMBER" ), exportgroup, LightApp_Preferences::Bool, "SMESH", "renumbering" ); + addPreference( tr( "PREF_RENUMBER" ), exportgroup, LightApp_Preferences::Bool, "SMESH", "renumbering" ); int meshTab = addPreference( tr( "PREF_TAB_MESH" ) ); int nodeGroup = addPreference( tr( "PREF_GROUP_NODES" ), meshTab ); diff --git a/src/SMESHGUI/SMESHGUI_ComputeDlg.cxx b/src/SMESHGUI/SMESHGUI_ComputeDlg.cxx index 5ce986876..6c856bb78 100644 --- a/src/SMESHGUI/SMESHGUI_ComputeDlg.cxx +++ b/src/SMESHGUI/SMESHGUI_ComputeDlg.cxx @@ -77,6 +77,7 @@ #include #include #include +#include #include @@ -109,6 +110,21 @@ using namespace SMESH; namespace SMESH { + //============================================================================= + /*! + * \brief Allocate some memory at construction and release it at destruction. + * Is used to be able to continue working after mesh generation or visualization + * break due to lack of memory + */ + //============================================================================= + + struct MemoryReserve + { + char* myBuf; + MemoryReserve(): myBuf( new char[1024*1024*1] ){} // 1M + ~MemoryReserve() { delete [] myBuf; } + }; + // ========================================================================================= /*! * \brief Class showing shapes without publishing @@ -573,7 +589,7 @@ void SMESHGUI_MeshInfosBox::SetInfoByMesh(SMESH::SMESH_Mesh_var mesh) // faces nbTot = mesh->NbFaces(), nbLin = mesh->NbFacesOfOrder(lin); myNbFace ->setText( QString("%1").arg( nbTot )); - myNbLinFace ->setText( QString("%1").arg( nbLin )); + myNbLinFace ->setText( QString("%1").arg( nbLin )); myNbQuadFace ->setText( QString("%1").arg( nbTot - nbLin )); // volumes @@ -706,12 +722,22 @@ QFrame* SMESHGUI_ComputeDlg::createMainFrame (QWidget* theParent) grpLayout->addWidget ( myPublishBtn, 1, 1 ); grpLayout->setRowStretch( 2, 1 ); + // Memory Lack Label + + myMemoryLackGroup = new QVGroupBox(tr("ERRORS"), aFrame, "memlackGrBox"); + QLabel* memLackLabel = new QLabel(tr("MEMORY_LACK"), myMemoryLackGroup); + QFont bold = memLackLabel->font(); bold.setBold(true); + memLackLabel->setFont( bold ); + memLackLabel->setMinimumWidth(300); + + // add all widgets to aFrame QVBoxLayout* aLay = new QVBoxLayout(aFrame); aLay->addWidget( aPixGrp ); aLay->addWidget( nameBox ); aLay->addWidget( myBriefInfo ); aLay->addWidget( myFullInfo ); aLay->addWidget( myErrorGroup ); + aLay->addWidget( myMemoryLackGroup ); aLay->setStretchFactor( myErrorGroup, 1 ); return aFrame; @@ -751,7 +777,7 @@ void SMESHGUI_ComputeOp::startOperation() // COMPUTE MESH - bool computeFailed = true; + bool computeFailed = true, memoryLack = false; int nbNodes = 0, nbEdges = 0, nbFaces = 0, nbVolums = 0; LightApp_SelectionMgr *Sel = selectionMgr(); @@ -769,9 +795,14 @@ void SMESHGUI_ComputeOp::startOperation() Handle(SALOME_InteractiveObject) IObject = selected.First(); aMesh = SMESH::GetMeshByIO(IObject); - if (!aMesh->_is_nil()) { + if (!aMesh->_is_nil()) + { + MemoryReserve aMemoryReserve; + _PTR(SObject) aMeshSObj = SMESH::FindSObject(aMesh); myMainShape = aMesh->GetShapeToMesh(); - if ( !myMainShape->_is_nil() ) { + if ( !myMainShape->_is_nil() && aMeshSObj ) + { + myDlg->myMeshName->setText( aMeshSObj->GetName() ); SMESH::SMESH_Gen_var gen = getSMESHGUI()->GetSMESHGen(); SMESH::algo_error_array_var errors = gen->GetAlgoState(aMesh,myMainShape); if ( errors->length() > 0 ) { @@ -783,49 +814,62 @@ void SMESHGUI_ComputeOp::startOperation() } SUIT_OverrideCursor aWaitCursor; try { - if (gen->Compute(aMesh, myMainShape)) { + if (gen->Compute(aMesh, myMainShape)) computeFailed = false; - } - else { - anErrors = gen->GetComputeErrors( aMesh, myMainShape ); -// if ( anErrors->length() == 0 ) { -// SUIT_MessageBox::warn1(desktop(), -// tr("SMESH_WRN_WARNING"), -// tr("SMESH_WRN_COMPUTE_FAILED"), -// tr("SMESH_BUT_OK")); -// onCancel(); -// return; -// } - } } catch(const SALOME::SALOME_Exception & S_ex){ - SalomeApp_Tools::QtCatchCorbaException(S_ex); + memoryLack = true; + //SalomeApp_Tools::QtCatchCorbaException(S_ex); } - if ( _PTR(SObject) aMeshSObj = SMESH::FindSObject(aMesh)) { - myDlg->myMeshName->setText( aMeshSObj->GetName() ); - SMESH::ModifiedMesh(aMeshSObj, !computeFailed, aMesh->NbNodes() == 0); + try { + anErrors = gen->GetComputeErrors( aMesh, myMainShape ); + // if ( anErrors->length() == 0 ) { + // SUIT_MessageBox::warn1(desktop(), + // tr("SMESH_WRN_WARNING"), + // tr("SMESH_WRN_COMPUTE_FAILED"), + // tr("SMESH_BUT_OK")); + // onCancel(); + // return; + // } + // check if there are memory problems + for ( int i = 0; i < anErrors->length() && !memoryLack; ++i ) + memoryLack = ( anErrors[ i ].code == SMESH::COMPERR_MEMORY_PB ); } - update( UF_ObjBrowser | UF_Model ); - - // SHOW MESH - - if ( getSMESHGUI()->automaticUpdate() ) { - SVTK_ViewWindow* aVTKView = SMESH::GetViewWindow(getSMESHGUI(), true); - if (aVTKView) { - int anId = study()->id(); - TVisualObjPtr aVisualObj = SMESH::GetVisualObj(anId, IObject->getEntry()); - if (aVisualObj) { - aVisualObj->Update(); - SMESH_Actor* anActor = SMESH::FindActorByEntry(IObject->getEntry()); - if (!anActor) { - anActor = SMESH::CreateActor(studyDS(), IObject->getEntry()); - if (anActor) { - SMESH::DisplayActor(aVTKView, anActor); //apo - SMESH::FitAll(); + catch(const SALOME::SALOME_Exception & S_ex){ + memoryLack = true; + } + + // NPAL16631: if ( !memoryLack ) + { + SMESH::ModifiedMesh(aMeshSObj, !computeFailed, aMesh->NbNodes() == 0); + update( UF_ObjBrowser | UF_Model ); + + // SHOW MESH + // NPAL16631: if ( getSMESHGUI()->automaticUpdate() ) { + if ( !memoryLack && getSMESHGUI()->automaticUpdate() ) // NPAL16631 + { + try { + SVTK_ViewWindow* aVTKView = SMESH::GetViewWindow(getSMESHGUI(), true); + if (aVTKView) { + int anId = study()->id(); + TVisualObjPtr aVisualObj = SMESH::GetVisualObj(anId, IObject->getEntry()); + if (aVisualObj) { + aVisualObj->Update(); + SMESH_Actor* anActor = SMESH::FindActorByEntry(IObject->getEntry()); + if (!anActor) { + anActor = SMESH::CreateActor(studyDS(), IObject->getEntry()); + if (anActor) { + SMESH::DisplayActor(aVTKView, anActor); //apo + SMESH::FitAll(); + } + } + SMESH::RepaintCurrentView(); + Sel->setSelectedObjects( selected ); } } - SMESH::RepaintCurrentView(); - Sel->setSelectedObjects( selected ); + } + catch (...) { + memoryLack = true; } } } @@ -839,18 +883,22 @@ void SMESHGUI_ComputeOp::startOperation() onCancel(); return; } - myDlg->setCaption(tr( computeFailed ? "SMESH_WRN_COMPUTE_FAILED" : "SMESH_COMPUTE_SUCCEED")); + myDlg->myMemoryLackGroup->hide(); // SHOW ERRORS bool noError = ( !anErrors.operator->() || anErrors->length() == 0 ); - QTable* tbl = myDlg->myTable; - - if ( noError ) + if ( memoryLack ) + { + myDlg->myMemoryLackGroup->show(); + myDlg->myFullInfo->hide(); + myDlg->myBriefInfo->hide(); + myDlg->myErrorGroup->hide(); + } + else if ( noError ) { - //tbl->setNumRows(0); myDlg->myFullInfo->SetInfoByMesh( aMesh ); myDlg->myFullInfo->show(); myDlg->myBriefInfo->hide(); @@ -858,6 +906,7 @@ void SMESHGUI_ComputeOp::startOperation() } else { + QTable* tbl = myDlg->myTable; myDlg->myBriefInfo->SetInfoByMesh( aMesh ); myDlg->myBriefInfo->show(); myDlg->myFullInfo->hide(); @@ -892,7 +941,6 @@ void SMESHGUI_ComputeOp::startOperation() tbl->setCurrentCell(0,0); currentCellChanged(); // to update buttons } - myDlg->show(); } diff --git a/src/SMESHGUI/SMESHGUI_ComputeDlg.h b/src/SMESHGUI/SMESHGUI_ComputeDlg.h index bb4252475..5e22e2b5a 100644 --- a/src/SMESHGUI/SMESHGUI_ComputeDlg.h +++ b/src/SMESHGUI/SMESHGUI_ComputeDlg.h @@ -130,6 +130,7 @@ private: QFrame* createMainFrame (QWidget*); QLabel* myMeshName; + QGroupBox* myMemoryLackGroup; QGroupBox* myErrorGroup; QTable* myTable; QPushButton* myShowBtn; diff --git a/src/SMESHGUI/SMESHGUI_FilterDlg.cxx b/src/SMESHGUI/SMESHGUI_FilterDlg.cxx index 2b75ac0c4..59a3eda1a 100755 --- a/src/SMESHGUI/SMESHGUI_FilterDlg.cxx +++ b/src/SMESHGUI/SMESHGUI_FilterDlg.cxx @@ -2540,7 +2540,8 @@ void SMESHGUI_FilterDlg::onSelectionDone() if (!anObj->_is_nil()) { myTable->SetThreshold(aRow, GEOMBase::GetName(anObj)); - myTable->SetID( aRow, GEOMBase::GetIORFromObject(anObj)); + //myTable->SetID( aRow, GEOMBase::GetIORFromObject(anObj)); + myTable->SetID(aRow, anIO->getEntry()); } } diff --git a/src/SMESHGUI/SMESHGUI_Hypotheses.cxx b/src/SMESHGUI/SMESHGUI_Hypotheses.cxx index e94a8a993..7414bf5ff 100644 --- a/src/SMESHGUI/SMESHGUI_Hypotheses.cxx +++ b/src/SMESHGUI/SMESHGUI_Hypotheses.cxx @@ -45,8 +45,8 @@ #include -SMESHGUI_GenericHypothesisCreator::SMESHGUI_GenericHypothesisCreator( const QString& aHypType ) - : myHypType( aHypType ), myIsCreate( false ), myDlg( 0 ) +SMESHGUI_GenericHypothesisCreator::SMESHGUI_GenericHypothesisCreator( const QString& theHypType ) + : myHypType( theHypType ), myIsCreate( false ), myDlg( 0 ) { } @@ -55,63 +55,62 @@ SMESHGUI_GenericHypothesisCreator::~SMESHGUI_GenericHypothesisCreator() } void SMESHGUI_GenericHypothesisCreator::create( SMESH::SMESH_Hypothesis_ptr initParamsHyp, + const QString& theHypName, QWidget* parent) { MESSAGE( "Creation of hypothesis with initial params" ); if ( !CORBA::is_nil( initParamsHyp ) && hypType() == initParamsHyp->GetName() ) myInitParamsHypo = SMESH::SMESH_Hypothesis::_duplicate( initParamsHyp ); - create( false, parent ); + create( false, theHypName, parent ); } -void SMESHGUI_GenericHypothesisCreator::create( const bool isAlgo, QWidget* parent ) +void SMESHGUI_GenericHypothesisCreator::create( bool isAlgo, + const QString& theHypName, + QWidget* theParent ) { MESSAGE( "Creation of hypothesis" ); - // Get default name for hypothesis/algorithm creation - HypothesisData* aHypData = SMESH::GetHypothesisData( hypType().latin1() ); - QString aHypName = aHypData ? aHypData->Label : hypType(); - myIsCreate = true; // Create hypothesis/algorithm if (isAlgo) - SMESH::CreateHypothesis( hypType(), aHypName, isAlgo ); - + SMESH::CreateHypothesis( hypType(), theHypName, isAlgo ); else { - SMESH::SMESH_Hypothesis_var newHypo = SMESH::SMESH_Hypothesis::_narrow - ( SMESH::CreateHypothesis( hypType(), aHypName, false ) ); - - if( !editHypothesis( newHypo.in(), parent ) ) + SMESH::SMESH_Hypothesis_var aHypothesis = + SMESH::CreateHypothesis( hypType(), theHypName, false ); + if( !editHypothesis( aHypothesis.in(), theHypName, theParent ) ) { //remove just created hypothesis - _PTR(SObject) SHyp = SMESH::FindSObject( newHypo.in() ); + _PTR(SObject) aHypSObject = SMESH::FindSObject( aHypothesis.in() ); _PTR(Study) aStudy = SMESH::GetActiveStudyDocument(); if( aStudy && !aStudy->GetProperties()->IsLocked() ) { _PTR(StudyBuilder) aBuilder = aStudy->NewBuilder(); - aBuilder->RemoveObjectWithChildren( SHyp ); + aBuilder->RemoveObjectWithChildren( aHypSObject ); } } } SMESHGUI::GetSMESHGUI()->updateObjBrowser( true, 0 ); } -void SMESHGUI_GenericHypothesisCreator::edit( SMESH::SMESH_Hypothesis_ptr h, QWidget* parent ) +void SMESHGUI_GenericHypothesisCreator::edit( SMESH::SMESH_Hypothesis_ptr theHypothesis, + const QString& theHypName, + QWidget* theParent ) { - if( CORBA::is_nil( h ) ) + if( CORBA::is_nil( theHypothesis ) ) return; MESSAGE("Edition of hypothesis"); myIsCreate = false; - if( !editHypothesis( h, parent ) ) + if( !editHypothesis( theHypothesis, theHypName, theParent ) ) return; - SMESH::SObjectList listSOmesh = SMESH::GetMeshesUsingAlgoOrHypothesis( h ); + SMESH::SObjectList listSOmesh = SMESH::GetMeshesUsingAlgoOrHypothesis( theHypothesis ); if( listSOmesh.size() > 0 ) - for( int i=0; i( submSO ); @@ -124,29 +123,30 @@ void SMESHGUI_GenericHypothesisCreator::edit( SMESH::SMESH_Hypothesis_ptr h, QWi SMESHGUI::GetSMESHGUI()->updateObjBrowser( true, 0 ); } -bool SMESHGUI_GenericHypothesisCreator::editHypothesis( SMESH::SMESH_Hypothesis_ptr h, QWidget* parent ) +bool SMESHGUI_GenericHypothesisCreator::editHypothesis( SMESH::SMESH_Hypothesis_ptr h, + const QString& theHypName, + QWidget* theParent ) { if( CORBA::is_nil( h ) ) return false; bool res = true; + myHypName = theHypName; myHypo = SMESH::SMESH_Hypothesis::_duplicate( h ); - SMESHGUI_HypothesisDlg* Dlg = - new SMESHGUI_HypothesisDlg( const_cast( this ), parent ); + SMESHGUI_HypothesisDlg* Dlg = new SMESHGUI_HypothesisDlg( this, theParent ); myDlg = Dlg; QFrame* fr = buildFrame(); if( fr ) { Dlg->setCustomFrame( fr ); Dlg->setCaption( caption() ); + Dlg->setName( theHypName ); Dlg->setHIcon( icon() ); Dlg->setType( type() ); retrieveParams(); Dlg->show(); - //connect(myDlg, SIGNAL( closed() ), this, SLOT( onDlgClosed() )); qApp->enter_loop(); // make myDlg not modal -// res = myDlg->exec()==QDialog::Accepted; res = myDlg->result(); if( res ) { QString paramValues = storeParams(); @@ -332,6 +332,11 @@ QString SMESHGUI_GenericHypothesisCreator::hypType() const return myHypType; } +QString SMESHGUI_GenericHypothesisCreator::hypName() const +{ + return myHypName; +} + const SMESHGUI_GenericHypothesisCreator::ListOfWidgets& SMESHGUI_GenericHypothesisCreator::widgets() const { return myParamWidgets; diff --git a/src/SMESHGUI/SMESHGUI_Hypotheses.h b/src/SMESHGUI/SMESHGUI_Hypotheses.h index c76e409e1..b411cf7b8 100644 --- a/src/SMESHGUI/SMESHGUI_Hypotheses.h +++ b/src/SMESHGUI/SMESHGUI_Hypotheses.h @@ -47,18 +47,19 @@ class SMESHGUI_EXPORT SMESHGUI_GenericHypothesisCreator : public QObject Q_OBJECT public: - SMESHGUI_GenericHypothesisCreator( const QString& ); + SMESHGUI_GenericHypothesisCreator( const QString& theHypType ); virtual ~SMESHGUI_GenericHypothesisCreator(); - void create( const bool isAlgo, QWidget* ); - void edit( SMESH::SMESH_Hypothesis_ptr, QWidget* ); - void create( SMESH::SMESH_Hypothesis_ptr, QWidget* ); + void create( SMESH::SMESH_Hypothesis_ptr, const QString&, QWidget*); + void create( bool isAlgo, const QString&, QWidget*); + void edit( SMESH::SMESH_Hypothesis_ptr, const QString&, QWidget*); virtual bool checkParams() const = 0; virtual void onReject(); - QString hypType() const; - bool isCreation() const; + QString hypType() const; + QString hypName() const; + bool isCreation() const; protected: typedef struct @@ -95,10 +96,11 @@ protected slots: virtual void onValueChanged(); private: - bool editHypothesis( SMESH::SMESH_Hypothesis_ptr, QWidget* ); + bool editHypothesis( SMESH::SMESH_Hypothesis_ptr, const QString&, QWidget* ); private: SMESH::SMESH_Hypothesis_var myHypo, myInitParamsHypo; + QString myHypName; QString myHypType; ListOfWidgets myParamWidgets; bool myIsCreate; @@ -113,9 +115,9 @@ public: SMESHGUI_HypothesisDlg( SMESHGUI_GenericHypothesisCreator*, QWidget* ); virtual ~SMESHGUI_HypothesisDlg(); - void setHIcon( const QPixmap& ); - void setCustomFrame( QFrame* ); - void setType( const QString& ); + void setHIcon( const QPixmap& ); + void setCustomFrame( QFrame* ); + void setType( const QString& ); protected slots: virtual void accept(); @@ -125,7 +127,8 @@ protected slots: private: SMESHGUI_GenericHypothesisCreator* myCreator; QVBoxLayout* myLayout; - QLabel *myIconLabel, *myTypeLabel; + QLabel* myIconLabel; + QLabel* myTypeLabel; QString myHelpFileName; }; diff --git a/src/SMESHGUI/SMESHGUI_HypothesesUtils.cxx b/src/SMESHGUI/SMESHGUI_HypothesesUtils.cxx index 114b8dbc3..4be1a4cbb 100644 --- a/src/SMESHGUI/SMESHGUI_HypothesesUtils.cxx +++ b/src/SMESHGUI/SMESHGUI_HypothesesUtils.cxx @@ -388,30 +388,21 @@ namespace SMESH{ const bool isAlgo) { if(MYDEBUG) MESSAGE("Create " << aHypType << " with name " << aHypName); - - SMESH::SMESH_Hypothesis_var Hyp; - HypothesisData* aHypData = GetHypothesisData(aHypType); QString aServLib = aHypData->ServerLibName; - try { - Hyp = SMESHGUI::GetSMESHGen()->CreateHypothesis(aHypType, aServLib); - if (!Hyp->_is_nil()) { - _PTR(SObject) SHyp = SMESH::FindSObject(Hyp.in()); - if (SHyp) { - //if (strcmp(aHypName,"") != 0) + SMESH::SMESH_Hypothesis_var aHypothesis; + aHypothesis = SMESHGUI::GetSMESHGen()->CreateHypothesis(aHypType, aServLib); + if (!aHypothesis->_is_nil()) { + _PTR(SObject) aHypSObject = SMESH::FindSObject(aHypothesis.in()); + if (aHypSObject) { if (strlen(aHypName) > 0) - SMESH::SetName(SHyp, aHypName); - //SalomeApp_Application* app = - // dynamic_cast(SUIT_Session::session()->activeApplication()); - //if (app) - // app->objectBrowser()->updateTree(); - SMESHGUI::GetSMESHGUI()->updateObjBrowser(); - return Hyp._retn(); + SMESH::SetName(aHypSObject, aHypName); + SMESHGUI::GetSMESHGUI()->updateObjBrowser(); + return aHypothesis._retn(); } } - } - catch (const SALOME::SALOME_Exception & S_ex) { + } catch (const SALOME::SALOME_Exception & S_ex) { SalomeApp_Tools::QtCatchCorbaException(S_ex); } @@ -621,6 +612,7 @@ namespace SMESH{ CASE2MESSAGE( HYP_MISSING ); CASE2MESSAGE( HYP_NOTCONFORM ); CASE2MESSAGE( HYP_BAD_PARAMETER ); + CASE2MESSAGE( HYP_BAD_GEOMETRY ); default: continue; } // apply args to message: diff --git a/src/SMESHGUI/SMESHGUI_MakeNodeAtPointDlg.cxx b/src/SMESHGUI/SMESHGUI_MakeNodeAtPointDlg.cxx index b21ad3260..22cbb7293 100644 --- a/src/SMESHGUI/SMESHGUI_MakeNodeAtPointDlg.cxx +++ b/src/SMESHGUI/SMESHGUI_MakeNodeAtPointDlg.cxx @@ -138,16 +138,18 @@ QFrame* SMESHGUI_MakeNodeAtPointDlg::createMainFrame (QWidget* theParent) myX = new SMESHGUI_SpinBox(aCoordGrp); QLabel* aYLabel = new QLabel(tr("SMESH_Y"), aCoordGrp); - aYLabel->setAlignment( Qt::AlignRight | Qt::AlignVCenter | Qt::ExpandTabs ); + //aYLabel->setAlignment( Qt::AlignRight | Qt::AlignVCenter | Qt::ExpandTabs ); + aYLabel->setSizePolicy( QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed ) ); myY = new SMESHGUI_SpinBox(aCoordGrp); QLabel* aZLabel = new QLabel(tr("SMESH_Z"), aCoordGrp); - aZLabel->setAlignment( Qt::AlignRight | Qt::AlignVCenter | Qt::ExpandTabs ); + //aZLabel->setAlignment( Qt::AlignRight | Qt::AlignVCenter | Qt::ExpandTabs ); + aZLabel->setSizePolicy( QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed ) ); myZ = new SMESHGUI_SpinBox(aCoordGrp); - myX->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, 3); - myY->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, 3); - myZ->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, 3); + myX->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, DBL_DIGITS_DISPLAY); + myY->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, DBL_DIGITS_DISPLAY); + myZ->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, DBL_DIGITS_DISPLAY); // Method selection diff --git a/src/SMESHGUI/SMESHGUI_MeshOp.cxx b/src/SMESHGUI/SMESHGUI_MeshOp.cxx index 9aa469e68..ca82f9dd3 100644 --- a/src/SMESHGUI/SMESHGUI_MeshOp.cxx +++ b/src/SMESHGUI/SMESHGUI_MeshOp.cxx @@ -693,7 +693,6 @@ void SMESHGUI_MeshOp::availableHyps( const int theDim, * \param theHypType - specifies whether algorims or hypotheses or additional ones * are retrieved (possible values are in HypType enumeration) * \param theFather - start object for finding ( may be component, mesh, or sub-mesh ) - * \param theDataList - output list of hypotheses data * \param theHyps - output list of names. * \param theHypVars - output list of variables. * \param theAlgoData - to select hypos able to be used by this algo (optional) @@ -706,12 +705,12 @@ void SMESHGUI_MeshOp::existingHyps( const int theDim, const int theHypType, _PTR(SObject) theFather, QStringList& theHyps, - QValueList& theHypVars, + THypList& theHypList, HypothesisData* theAlgoData) { // Clear hypoheses list theHyps.clear(); - theHypVars.clear(); + theHypList.clear(); if ( !theFather ) return; @@ -754,15 +753,15 @@ void SMESHGUI_MeshOp::existingHyps( const int theDim, SMESH::SMESH_Hypothesis_var aHypVar = SMESH::SMESH_Hypothesis::_narrow( aVar ); if ( !aHypVar->_is_nil() ) { - QString aHypType( aHypVar->GetName() ); + CORBA::String_var aHypType( aHypVar->GetName() ); HypothesisData* aData = SMESH::GetHypothesisData( aHypType ); if ( ( theDim == -1 || aData->Dim.contains( theDim ) ) && ( isCompatible ( theAlgoData, aData, theHypType )) && ( isAux == aData->IsAux )) { - //theDataList.append( aData ); - theHyps.append( aName->Value().c_str() ); - theHypVars.append( aHypVar ); + std::string aHypName = aName->Value(); + theHyps.append( aHypName.c_str() ); + theHypList.append( THypItem( aHypVar, aHypName.c_str() ) ); } } } @@ -884,6 +883,19 @@ void SMESHGUI_MeshOp::onCreateHyp( const int theHypType, const int theIndex ) * \param theTypeName - specifies hypothesis to be created */ //================================================================================ +namespace +{ + QString GetUniqueName (const QStringList& theHypNames, + const QString& theName, + size_t theIteration = 1) + { + QString aName = theName + "_" + QString::number( theIteration ); + if ( theHypNames.contains( aName ) ) + return GetUniqueName( theHypNames, theName, ++theIteration ); + return aName; + } +} + void SMESHGUI_MeshOp::createHypothesis (const int theDim, const int theType, const QString& theTypeName) @@ -896,13 +908,30 @@ void SMESHGUI_MeshOp::createHypothesis (const int theDim, if (!aData) return; + QStringList aHypNames; + TDim2Type2HypList::const_iterator aDimIter = myExistingHyps.begin(); + for( ; aDimIter != myExistingHyps.end(); aDimIter++ ) { + const TType2HypList& aType2HypList = aDimIter.data(); + TType2HypList::const_iterator aTypeIter = aType2HypList.begin(); + for( ; aTypeIter != aType2HypList.end(); aTypeIter++ ) { + const THypList& aHypList = aTypeIter.data(); + THypList::const_iterator anIter = aHypList.begin(); + for( ; anIter != aHypList.end(); anIter++ ) { + const THypItem& aHypItem = *anIter; + const QString& aHypName = aHypItem.second; + aHypNames.append(aHypName); + } + } + } + QString aHypName = GetUniqueName( aHypNames, aData->Label); + // existing hypos int nbHyp = myExistingHyps[theDim][theType].count(); QString aClientLibName = aData->ClientLibName; if (aClientLibName == "") { // Call hypothesis creation server method (without GUI) - SMESH::CreateHypothesis(theTypeName, aData->Label, false); + SMESH::CreateHypothesis(theTypeName, aHypName, false); } else { // Get hypotheses creator client (GUI) SMESHGUI_GenericHypothesisCreator* aCreator = SMESH::GetHypothesisCreator(theTypeName); @@ -914,10 +943,10 @@ void SMESHGUI_MeshOp::createHypothesis (const int theDim, SMESH::SMESH_Hypothesis_var initParamHyp = getInitParamsHypothesis(theTypeName, aData->ServerLibName); myDlg->setEnabled( false ); - aCreator->create(initParamHyp, myDlg); + aCreator->create(initParamHyp, aHypName, myDlg); myDlg->setEnabled( true ); } else { - SMESH::CreateHypothesis(theTypeName, aData->Label, false); + SMESH::CreateHypothesis(theTypeName, aHypName, false); } } @@ -949,18 +978,19 @@ void SMESHGUI_MeshOp::onEditHyp( const int theHypType, const int theIndex ) if (aDim == -1) return; - QValueList aList = myExistingHyps[ aDim ][ theHypType ]; + const THypList& aList = myExistingHyps[ aDim ][ theHypType ]; if ( theIndex < 0 || theIndex >= aList.count() ) return; - SMESH::SMESH_Hypothesis_var aHyp = aList[ theIndex ]; + const THypItem& aHypItem = aList[ theIndex ]; + SMESH::SMESH_Hypothesis_var aHyp = aHypItem.first; if ( aHyp->_is_nil() ) return; - char* aTypeName = aHyp->GetName(); + CORBA::String_var aTypeName = aHyp->GetName(); SMESHGUI_GenericHypothesisCreator* aCreator = SMESH::GetHypothesisCreator( aTypeName ); if ( aCreator ) { myDlg->setEnabled( false ); - aCreator->edit( aHyp.in(), dlg() ); + aCreator->edit( aHyp.in(), aHypItem.second, dlg() ); myDlg->setEnabled( true ); } } @@ -1093,17 +1123,18 @@ void SMESHGUI_MeshOp::onAlgoSelected( const int theIndex, SMESH::SMESH_Hypothesis_var curHyp; if ( hypIndex >= 0 && hypIndex < myExistingHyps[ dim ][ type ].count() ) - curHyp = myExistingHyps[ dim ][ type ][ hypIndex ]; + curHyp = myExistingHyps[ dim ][ type ][ hypIndex ].first; if ( !myToCreate && !curAlgo && !curHyp->_is_nil() ) { // edition, algo not selected // try to find algo by selected hypothesis in order to keep it selected bool algoDeselectedByUser = ( theDim < 0 && aDim == dim ); - QString curHypType = curHyp->GetName(); + CORBA::String_var curHypType = curHyp->GetName(); if ( !algoDeselectedByUser && myObjHyps[ dim ][ type ].count() > 0 && - curHypType == myObjHyps[ dim ][ type ][ 0 ]->GetName()) + curHypType == myObjHyps[ dim ][ type ].first().first->GetName()) { - HypothesisData* hypData = SMESH::GetHypothesisData( curHyp->GetName() ); + CORBA::String_var aName = curHyp->GetName(); + HypothesisData* hypData = SMESH::GetHypothesisData( aName ); for ( int i = 0 ; i < myAvailableHypData[ dim ][ Algo ].count(); ++i ) { curAlgo = myAvailableHypData[ dim ][ Algo ][ i ]; if ( curAlgo && hypData && isCompatible( curAlgo, hypData, type )) @@ -1118,7 +1149,8 @@ void SMESHGUI_MeshOp::onAlgoSelected( const int theIndex, { // check if a selected hyp is compatible with the curAlgo if ( !curHyp->_is_nil() ) { - HypothesisData* hypData = SMESH::GetHypothesisData( curHyp->GetName() ); + CORBA::String_var aName = curHyp->GetName(); + HypothesisData* hypData = SMESH::GetHypothesisData( aName ); if ( !isCompatible( curAlgo, hypData, type )) curHyp = SMESH::SMESH_Hypothesis::_nil(); } @@ -1136,10 +1168,10 @@ void SMESHGUI_MeshOp::onAlgoSelected( const int theIndex, hypIndex = -1; if ( !isSubmesh && hypIndex < 0 && anExisting.count() == 1 ) { // none is yet selected => select the sole existing if it is not optional - QString hypTypeName = myExistingHyps[ dim ][ type ][ 0 ]->GetName(); + CORBA::String_var hypTypeName = myExistingHyps[ dim ][ type ].first().first->GetName(); bool isOptional = true; if ( algoByDim[ dim ] && - SMESH::IsAvailableHypothesis( algoByDim[ dim ], hypTypeName, isOptional ) && + SMESH::IsAvailableHypothesis( algoByDim[ dim ], hypTypeName.in(), isOptional ) && !isOptional ) hypIndex = 0; } @@ -1251,7 +1283,7 @@ bool SMESHGUI_MeshOp::createMesh( QString& theMess ) for ( int aHypType = MainHyp; aHypType <= AddHyp; aHypType++ ) { int aHypIndex = currentHyp( aDim, aHypType ); if ( aHypIndex >= 0 && aHypIndex < myExistingHyps[ aDim ][ aHypType ].count() ) { - SMESH::SMESH_Hypothesis_var aHypVar = myExistingHyps[ aDim ][ aHypType ][ aHypIndex ]; + SMESH::SMESH_Hypothesis_var aHypVar = myExistingHyps[ aDim ][ aHypType ][ aHypIndex ].first; if ( !aHypVar->_is_nil() ) SMESH::AddHypothesisOnMesh( aMeshVar, aHypVar ); } @@ -1379,7 +1411,7 @@ bool SMESHGUI_MeshOp::createSubMesh( QString& theMess ) if ( aHypIndex >= 0 && aHypIndex < myExistingHyps[ aDim ][ aHypType ].count() ) { SMESH::SMESH_Hypothesis_var aHypVar = - myExistingHyps[ aDim ][ aHypType ][ aHypIndex ]; + myExistingHyps[ aDim ][ aHypType ][ aHypIndex ].first; if ( !aHypVar->_is_nil() ) SMESH::AddHypothesisOnSubMesh( aSubMeshVar, aHypVar ); } @@ -1493,12 +1525,13 @@ SMESH::SMESH_Hypothesis_var SMESHGUI_MeshOp::getAlgo( const int theDim ) existingHyps( theDim, Algo, pObj, tmp, myExistingHyps[ theDim ][ Algo ]); // look for anexisting algo of such a type - QValueList& aHypVarList = myExistingHyps[ theDim ][ Algo ]; - QValueList::iterator anIter; - for ( anIter = aHypVarList.begin(); anIter != aHypVarList.end(); anIter++ ) + THypList& aHypVarList = myExistingHyps[ theDim ][ Algo ]; + THypList::iterator anIter = aHypVarList.begin(); + for ( ; anIter != aHypVarList.end(); anIter++ ) { - SMESH::SMESH_Hypothesis_var aHypVar = *anIter; - if ( !aHypVar->_is_nil() && aHypName == aHypVar->GetName() ) + SMESH::SMESH_Hypothesis_var aHypVar = (*anIter).first; + CORBA::String_var aName = aHypVar->GetName(); + if ( !aHypVar->_is_nil() && aHypName == aName ) { anAlgoVar = aHypVar; break; @@ -1518,7 +1551,7 @@ SMESH::SMESH_Hypothesis_var SMESHGUI_MeshOp::getAlgo( const int theDim ) // Create algorithm if (aCreator) - aCreator->create(true, myDlg); + aCreator->create(true, aHypName, myDlg); else SMESH::CreateHypothesis(aHypName, aHypData->Label, true); } @@ -1527,11 +1560,12 @@ SMESH::SMESH_Hypothesis_var SMESHGUI_MeshOp::getAlgo( const int theDim ) existingHyps( theDim, Algo, aFather, tmpList, myExistingHyps[ theDim ][ Algo ] ); } - QValueList& aNewHypVarList = myExistingHyps[ theDim ][ Algo ]; + THypList& aNewHypVarList = myExistingHyps[ theDim ][ Algo ]; for ( anIter = aNewHypVarList.begin(); anIter != aNewHypVarList.end(); ++anIter ) { - SMESH::SMESH_Hypothesis_var aHypVar = *anIter; - if ( !aHypVar->_is_nil() && aHypName == aHypVar->GetName() ) + SMESH::SMESH_Hypothesis_var aHypVar = (*anIter).first; + CORBA::String_var aName = aHypVar->GetName(); + if ( !aHypVar->_is_nil() && aHypName == aName ) { anAlgoVar = aHypVar; break; @@ -1590,8 +1624,8 @@ void SMESHGUI_MeshOp::readMesh() int aHypIndex = -1; if ( myObjHyps[ dim ][ Algo ].count() > 0 ) { - SMESH::SMESH_Hypothesis_var aVar = myObjHyps[ dim ][ Algo ].first(); - QString aHypTypeName = aVar->GetName(); + SMESH::SMESH_Hypothesis_var aVar = myObjHyps[ dim ][ Algo ].first().first; + CORBA::String_var aHypTypeName = aVar->GetName(); HypothesisData* algoData = SMESH::GetHypothesisData( aHypTypeName ); aHypIndex = myAvailableHypData[ dim ][ Algo ].findIndex ( algoData ); // if ( aHypIndex < 0 && algoData ) { @@ -1616,7 +1650,7 @@ void SMESHGUI_MeshOp::readMesh() // find index of requered hypothesis among existing ones for this dimension and type int aHypIndex = -1; if ( myObjHyps[ dim ][ hypType ].count() > 0 ) { - aHypIndex = find( myObjHyps[ dim ][ hypType ].first(), + aHypIndex = find( myObjHyps[ dim ][ hypType ].first().first, myExistingHyps[ dim ][ hypType ] ); if ( aHypIndex < 0 ) { // assigned hypothesis is incompatible with the algorithm @@ -1673,16 +1707,16 @@ QString SMESHGUI_MeshOp::name( _PTR(SObject) theSO ) const */ //================================================================================ int SMESHGUI_MeshOp::find( const SMESH::SMESH_Hypothesis_var& theHyp, - const QValueList& theHypList ) const + const THypList& theHypList ) const { int aRes = -1; if ( !theHyp->_is_nil() ) { int i = 0; - QValueList::const_iterator anIter; - for ( anIter = theHypList.begin(); anIter != theHypList.end(); ++ anIter ) + THypList::const_iterator anIter = theHypList.begin(); + for ( ; anIter != theHypList.end(); ++ anIter ) { - if ( theHyp->_is_equivalent( *anIter ) ) + if ( theHyp->_is_equivalent( (*anIter).first ) ) { aRes = i; break; @@ -1718,20 +1752,23 @@ bool SMESHGUI_MeshOp::editMeshOrSubMesh( QString& theMess ) SUIT_OverrideCursor aWaitCursor; // Set new name - SMESH::SetName( pObj, myDlg->objectText( SMESHGUI_MeshDlg::Obj ).latin1() ); + QString aName = myDlg->objectText( SMESHGUI_MeshDlg::Obj ); + SMESH::SetName( pObj, aName.latin1() ); // First, remove old algos in order to avoid messages on algorithm hiding for ( int dim = SMESH::DIM_0D; dim <= SMESH::DIM_3D; dim++ ) { if ( isAccessibleDim( dim ) && myObjHyps[ dim ][ Algo ].count() > 0 ) { - SMESH::SMESH_Hypothesis_var anOldAlgo = myObjHyps[ dim ][ Algo ].first(); + SMESH::SMESH_Hypothesis_var anOldAlgo = myObjHyps[ dim ][ Algo ].first().first; + CORBA::String_var anOldName = anOldAlgo->GetName(); SMESH::SMESH_Hypothesis_var anAlgoVar = getAlgo( dim ); + CORBA::String_var anAlgoName = anAlgoVar->GetName(); if ( anAlgoVar->_is_nil() || // no new algo selected or - strcmp(anOldAlgo->GetName(), anAlgoVar->GetName()) ) // algo change + strcmp(anOldName.in(), anAlgoName.in()) ) // algo change { // remove old algorithm - SMESH::RemoveHypothesisOrAlgorithmOnMesh ( pObj, myObjHyps[ dim ][ Algo ].first() ); + SMESH::RemoveHypothesisOrAlgorithmOnMesh ( pObj, myObjHyps[ dim ][ Algo ].first().first ); myObjHyps[ dim ][ Algo ].clear(); } } @@ -1749,8 +1786,9 @@ bool SMESHGUI_MeshOp::editMeshOrSubMesh( QString& theMess ) if ( !anAlgoVar->_is_nil() && // some algo selected and myObjHyps[ dim ][ Algo ].count() == 0 ) // no algo assigned { - SMESH::SMESH_Mesh_var aMeshVar = - SMESH::SMESH_Mesh::_narrow( _CAST(SObject,pObj)->GetObject() ); + SALOMEDS_SObject* aSObject = _CAST(SObject, pObj); + CORBA::Object_var anObject = aSObject->GetObject(); + SMESH::SMESH_Mesh_var aMeshVar = SMESH::SMESH_Mesh::_narrow( anObject ); bool isMesh = !aMeshVar->_is_nil(); if ( isMesh ) { SMESH::AddHypothesisOnMesh( aMeshVar, anAlgoVar ); @@ -1760,7 +1798,7 @@ bool SMESHGUI_MeshOp::editMeshOrSubMesh( QString& theMess ) if ( !aVar->_is_nil() ) SMESH::AddHypothesisOnSubMesh( aVar, anAlgoVar ); } - myObjHyps[ dim ][ Algo ].append( anAlgoVar ); + myObjHyps[ dim ][ Algo ].append( THypItem( anAlgoVar, aName) ); } // assign hypotheses @@ -1772,13 +1810,13 @@ bool SMESHGUI_MeshOp::editMeshOrSubMesh( QString& theMess ) // remove old hypotheses if ( myObjHyps[ dim ][ hypType ].count() > 0 ) { - anOldHypIndex = find( myObjHyps[ dim ][ hypType ].first(), + anOldHypIndex = find( myObjHyps[ dim ][ hypType ].first().first , myExistingHyps[ dim ][ hypType ] ); if ( aNewHypIndex != anOldHypIndex || // different hyps anOldHypIndex == -1 ) // hyps of different algos { SMESH::RemoveHypothesisOrAlgorithmOnMesh - ( pObj, myObjHyps[ dim ][ hypType ].first() ); + ( pObj, myObjHyps[ dim ][ hypType ].first().first ); myObjHyps[ dim ][ hypType ].clear(); } } @@ -1792,7 +1830,7 @@ bool SMESHGUI_MeshOp::editMeshOrSubMesh( QString& theMess ) if ( isMesh ) { SMESH::AddHypothesisOnMesh - (aMeshVar, myExistingHyps[ dim ][ hypType ][ aNewHypIndex ] ); + (aMeshVar, myExistingHyps[ dim ][ hypType ][ aNewHypIndex ].first ); } else { @@ -1800,7 +1838,7 @@ bool SMESHGUI_MeshOp::editMeshOrSubMesh( QString& theMess ) SMESH::SMESH_subMesh::_narrow( _CAST(SObject,pObj)->GetObject() ); if ( !aVar->_is_nil() ) SMESH::AddHypothesisOnSubMesh - ( aVar, myExistingHyps[ dim ][ hypType ][ aNewHypIndex ] ); + ( aVar, myExistingHyps[ dim ][ hypType ][ aNewHypIndex ].first ); } } // reread all hypotheses of mesh if necessary diff --git a/src/SMESHGUI/SMESHGUI_MeshOp.h b/src/SMESHGUI/SMESHGUI_MeshOp.h index 190c386dd..23365fd1a 100644 --- a/src/SMESHGUI/SMESHGUI_MeshOp.h +++ b/src/SMESHGUI/SMESHGUI_MeshOp.h @@ -35,12 +35,13 @@ #include "SMESH_SMESHGUI.hxx" #include "SMESHGUI_SelectionOp.h" -#include #include #include CORBA_SERVER_HEADER(GEOM_Gen) #include CORBA_SERVER_HEADER(SMESH_Mesh) +#include + class SMESHGUI_MeshDlg; class SMESHGUI_ShapeByMeshOp; class HypothesisData; @@ -58,6 +59,15 @@ public: enum HypType{ Algo = 0, MainHyp, AddHyp, NbHypTypes }; + typedef std::pair THypItem; + typedef QValueList< THypItem > THypList; + + typedef int THypType; + typedef QMap< THypType, THypList > TType2HypList; + + typedef int THypDim; + typedef QMap< THypDim, TType2HypList > TDim2Type2HypList; + SMESHGUI_MeshOp( const bool theToCreate, const bool theIsMesh = true ); virtual ~SMESHGUI_MeshOp(); @@ -94,7 +104,7 @@ private: const int theHypType, _PTR(SObject) theFather, QStringList& theHyps, - QValueList& theHypVars, + THypList& theHypList, HypothesisData* theAlgoData = 0); HypothesisData* hypData( const int theDim, const int theHypType, @@ -115,7 +125,7 @@ private: void readMesh(); QString name( _PTR(SObject) ) const; int find( const SMESH::SMESH_Hypothesis_var&, - const QValueList& ) const; + const THypList& theHypList) const; SMESH::SMESH_Hypothesis_var getInitParamsHypothesis( const QString& aHypType, const QString& aServerLib ) const; bool isSubshapeOk() const; @@ -123,16 +133,13 @@ private: void selectObject( _PTR(SObject) ) const; private: - typedef QMap< int, QValueList > IdToHypListMap; - typedef QMap< int, IdToHypListMap > DimToHypMap; - SMESHGUI_MeshDlg* myDlg; SMESHGUI_ShapeByMeshOp* myShapeByMeshOp; bool myToCreate; bool myIsMesh; - DimToHypMap myExistingHyps; //!< all hypothesis of SMESH module - DimToHypMap myObjHyps; //!< hypothesis assigned to the current + TDim2Type2HypList myExistingHyps; //!< all hypothesis of SMESH module + TDim2Type2HypList myObjHyps; //!< hypothesis assigned to the current // edited mesh/sub-mesh // hypdata corresponding to hypotheses present in myDlg diff --git a/src/SMESHGUI/SMESHGUI_MoveNodesDlg.cxx b/src/SMESHGUI/SMESHGUI_MoveNodesDlg.cxx index 8eb5e67ce..2c69a8161 100644 --- a/src/SMESHGUI/SMESHGUI_MoveNodesDlg.cxx +++ b/src/SMESHGUI/SMESHGUI_MoveNodesDlg.cxx @@ -184,16 +184,18 @@ QFrame* SMESHGUI_MoveNodesDlg::createMainFrame (QWidget* theParent) myX = new SMESHGUI_SpinBox(aCoordGrp); QLabel* aYLabel = new QLabel(tr("SMESH_Y"), aCoordGrp); - aYLabel->setAlignment( Qt::AlignRight | Qt::AlignVCenter | Qt::ExpandTabs ); + //aYLabel->setAlignment( Qt::AlignRight | Qt::AlignVCenter | Qt::ExpandTabs ); + aYLabel->setSizePolicy( QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed ) ); myY = new SMESHGUI_SpinBox(aCoordGrp); QLabel* aZLabel = new QLabel(tr("SMESH_Z"), aCoordGrp); - aZLabel->setAlignment( Qt::AlignRight | Qt::AlignVCenter | Qt::ExpandTabs ); + //aZLabel->setAlignment( Qt::AlignRight | Qt::AlignVCenter | Qt::ExpandTabs ); + aZLabel->setSizePolicy( QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed ) ); myZ = new SMESHGUI_SpinBox(aCoordGrp); - myX->RangeStepAndValidator(COORD_MIN, COORD_MAX, 25.0, 3); - myY->RangeStepAndValidator(COORD_MIN, COORD_MAX, 25.0, 3); - myZ->RangeStepAndValidator(COORD_MIN, COORD_MAX, 25.0, 3); + myX->RangeStepAndValidator(COORD_MIN, COORD_MAX, 25.0, DBL_DIGITS_DISPLAY); + myY->RangeStepAndValidator(COORD_MIN, COORD_MAX, 25.0, DBL_DIGITS_DISPLAY); + myZ->RangeStepAndValidator(COORD_MIN, COORD_MAX, 25.0, DBL_DIGITS_DISPLAY); QVBoxLayout* aLay = new QVBoxLayout(aFrame); aLay->addWidget(aPixGrp); diff --git a/src/SMESHGUI/SMESHGUI_NodesDlg.cxx b/src/SMESHGUI/SMESHGUI_NodesDlg.cxx index b89009898..357ee5889 100644 --- a/src/SMESHGUI/SMESHGUI_NodesDlg.cxx +++ b/src/SMESHGUI/SMESHGUI_NodesDlg.cxx @@ -310,17 +310,21 @@ SMESHGUI_NodesDlg::SMESHGUI_NodesDlg (SMESHGUI* theModule, GroupCoordinatesLayout->setAlignment(Qt::AlignTop); GroupCoordinatesLayout->setSpacing(6); GroupCoordinatesLayout->setMargin(11); + TextLabel_X = new QLabel(GroupCoordinates, "TextLabel_X"); TextLabel_X->setSizePolicy( QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed ) ); TextLabel_X->setText(tr("SMESH_X" )); GroupCoordinatesLayout->addWidget(TextLabel_X, 0, 0); + TextLabel_Y = new QLabel(GroupCoordinates, "TextLabel_Y"); - TextLabel_Y->setAlignment( Qt::AlignRight | Qt::AlignVCenter | Qt::ExpandTabs ); + //TextLabel_Y->setAlignment( Qt::AlignRight | Qt::AlignVCenter | Qt::ExpandTabs ); + TextLabel_Y->setSizePolicy( QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed ) ); TextLabel_Y->setText(tr("SMESH_Y" )); GroupCoordinatesLayout->addWidget(TextLabel_Y, 0, 2); TextLabel_Z = new QLabel(GroupCoordinates, "TextLabel_Z"); - TextLabel_Z->setAlignment( Qt::AlignRight | Qt::AlignVCenter | Qt::ExpandTabs ); + //TextLabel_Z->setAlignment( Qt::AlignRight | Qt::AlignVCenter | Qt::ExpandTabs ); + TextLabel_Z->setSizePolicy( QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed ) ); TextLabel_Z->setText(tr("SMESH_Z" )); GroupCoordinatesLayout->addWidget(TextLabel_Z, 0, 4); @@ -363,9 +367,9 @@ void SMESHGUI_NodesDlg::Init () step = 25.0; /* min, max, step and decimals for spin boxes */ - SpinBox_X->RangeStepAndValidator(COORD_MIN, COORD_MAX, step, 3); - SpinBox_Y->RangeStepAndValidator(COORD_MIN, COORD_MAX, step, 3); - SpinBox_Z->RangeStepAndValidator(COORD_MIN, COORD_MAX, step, 3); + SpinBox_X->RangeStepAndValidator(COORD_MIN, COORD_MAX, step, DBL_DIGITS_DISPLAY); + SpinBox_Y->RangeStepAndValidator(COORD_MIN, COORD_MAX, step, DBL_DIGITS_DISPLAY); + SpinBox_Z->RangeStepAndValidator(COORD_MIN, COORD_MAX, step, DBL_DIGITS_DISPLAY); SpinBox_X->SetValue(0.0); SpinBox_Y->SetValue(0.0); SpinBox_Z->SetValue(0.0); diff --git a/src/SMESHGUI/SMESHGUI_SpinBox.h b/src/SMESHGUI/SMESHGUI_SpinBox.h index cc5c99689..53069b718 100644 --- a/src/SMESHGUI/SMESHGUI_SpinBox.h +++ b/src/SMESHGUI/SMESHGUI_SpinBox.h @@ -36,6 +36,7 @@ // like in GEOM_SRC/src/DlgRef/DlgRef_SpinBox.h #define COORD_MIN -1e+15 #define COORD_MAX +1e+15 +#define DBL_DIGITS_DISPLAY 14 //================================================================================= // class : SMESHGUI_SpinBox diff --git a/src/SMESHGUI/SMESHGUI_TranslationDlg.cxx b/src/SMESHGUI/SMESHGUI_TranslationDlg.cxx index bf4fd6d98..c00e097d7 100644 --- a/src/SMESHGUI/SMESHGUI_TranslationDlg.cxx +++ b/src/SMESHGUI/SMESHGUI_TranslationDlg.cxx @@ -264,12 +264,12 @@ SMESHGUI_TranslationDlg::SMESHGUI_TranslationDlg( SMESHGUI* theModule, const cha SMESHGUI_TranslationDlgLayout->addWidget(GroupArguments, 1, 0); /* Initialisations */ - SpinBox1_1->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, 3); - SpinBox1_2->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, 3); - SpinBox1_3->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, 3); - SpinBox2_1->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, 3); - SpinBox2_2->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, 3); - SpinBox2_3->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, 3); + SpinBox1_1->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, DBL_DIGITS_DISPLAY); + SpinBox1_2->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, DBL_DIGITS_DISPLAY); + SpinBox1_3->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, DBL_DIGITS_DISPLAY); + SpinBox2_1->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, DBL_DIGITS_DISPLAY); + SpinBox2_2->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, DBL_DIGITS_DISPLAY); + SpinBox2_3->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, DBL_DIGITS_DISPLAY); GroupArguments->show(); RadioButton1->setChecked(TRUE); diff --git a/src/SMESHGUI/SMESH_msg_en.po b/src/SMESHGUI/SMESH_msg_en.po index 4ef2f345a..df115b105 100644 --- a/src/SMESHGUI/SMESH_msg_en.po +++ b/src/SMESHGUI/SMESH_msg_en.po @@ -1328,6 +1328,9 @@ msgstr "Hypothesis of %3 %2D algorithm \"%1\" has a bad parameter value" msgid "STATE_HYP_NOTCONFORM" msgstr "%3 %2D algorithm \"%1\" would produce not conform mesh: global \"Not Conform Mesh Allowed\" hypotesis is missing" +msgid "STATE_HYP_BAD_GEOMETRY" +msgstr "%3 %2D algorithm \"%1\" is assigned to geometry mismatching its expectation" + msgid "GLOBAL_ALGO" msgstr "Global" @@ -3407,6 +3410,9 @@ msgstr "Show SubShape" msgid "SMESHGUI_ComputeDlg::PUBLISH_SHAPE" msgstr "Publish SubShape" +msgid "SMESHGUI_ComputeDlg::MEMORY_LACK" +msgstr "Memory allocation problem" + msgid "COMPERR_OK" msgstr "No errors" diff --git a/src/SMESH_I/SMESH_2smeshpy.cxx b/src/SMESH_I/SMESH_2smeshpy.cxx index 3cd0dd18a..998266806 100644 --- a/src/SMESH_I/SMESH_2smeshpy.cxx +++ b/src/SMESH_I/SMESH_2smeshpy.cxx @@ -46,6 +46,7 @@ IMPLEMENT_STANDARD_HANDLE (_pyObject ,Standard_Transient); IMPLEMENT_STANDARD_HANDLE (_pyCommand ,Standard_Transient); IMPLEMENT_STANDARD_HANDLE (_pyGen ,_pyObject); IMPLEMENT_STANDARD_HANDLE (_pyMesh ,_pyObject); +IMPLEMENT_STANDARD_HANDLE (_pyMeshEditor ,_pyObject); IMPLEMENT_STANDARD_HANDLE (_pyHypothesis ,_pyObject); IMPLEMENT_STANDARD_HANDLE (_pyAlgorithm ,_pyHypothesis); IMPLEMENT_STANDARD_HANDLE (_pyComplexParamHypo,_pyHypothesis); @@ -55,6 +56,7 @@ IMPLEMENT_STANDARD_RTTIEXT(_pyObject ,Standard_Transient); IMPLEMENT_STANDARD_RTTIEXT(_pyCommand ,Standard_Transient); IMPLEMENT_STANDARD_RTTIEXT(_pyGen ,_pyObject); IMPLEMENT_STANDARD_RTTIEXT(_pyMesh ,_pyObject); +IMPLEMENT_STANDARD_RTTIEXT(_pyMeshEditor ,_pyObject); IMPLEMENT_STANDARD_RTTIEXT(_pyHypothesis ,_pyObject); IMPLEMENT_STANDARD_RTTIEXT(_pyAlgorithm ,_pyHypothesis); IMPLEMENT_STANDARD_RTTIEXT(_pyComplexParamHypo,_pyHypothesis); @@ -79,11 +81,39 @@ static TCollection_AsciiString theEmptyString; #undef DUMP_CONVERSION #endif +namespace { + + //================================================================================ + /*! + * \brief Set of TCollection_AsciiString initialized by C array of C strings + */ + //================================================================================ + + struct TStringSet: public set + { + /*! + * \brief Filling. The last string must be "" + */ + void Insert(const char* names[]) { + for ( int i = 0; names[i][0] ; ++i ) + insert( (char*) names[i] ); + } + /*! + * \brief Check if a string is in + */ + bool Contains(const TCollection_AsciiString& name ) { + return find( name ) != end(); + } + }; +} + //================================================================================ /*! * \brief Convert python script using commands of smesh.py * \param theScript - Input script * \retval TCollection_AsciiString - Convertion result + * + * Class SMESH_2smeshpy declared in SMESH_PythonDump.hxx */ //================================================================================ @@ -152,6 +182,17 @@ _pyGen::_pyGen(Resource_DataMapOfAsciiStringAsciiString& theEntry2AccessorMethod GetCreationCmd()->GetString() += "="; } +//================================================================================ +/*! + * \brief name of SMESH_Gen in smesh.py + */ +//================================================================================ + +const char* _pyGen::AccessorMethod() const +{ + return SMESH_2smeshpy::GenName(); +} + //================================================================================ /*! * \brief Convert a command using a specific converter @@ -182,9 +223,21 @@ Handle(_pyCommand) _pyGen::AddCommand( const TCollection_AsciiString& theCommand // SMESH_Mesh method? map< _pyID, Handle(_pyMesh) >::iterator id_mesh = myMeshes.find( objID ); if ( id_mesh != myMeshes.end() ) { + if ( aCommand->GetMethod() == "GetMeshEditor" ) { // MeshEditor creation + _pyID editorID = aCommand->GetResultValue(); + Handle(_pyMeshEditor) editor = new _pyMeshEditor( aCommand ); + myMeshEditors.insert( make_pair( editorID, editor )); + return aCommand; + } id_mesh->second->Process( aCommand ); return aCommand; } + // SMESH_MeshEditor method? + map< _pyID, Handle(_pyMeshEditor) >::iterator id_editor = myMeshEditors.find( objID ); + if ( id_editor != myMeshEditors.end() ) { + id_editor->second->Process( aCommand ); + return aCommand; + } // SMESH_Hypothesis method? list< Handle(_pyHypothesis) >::iterator hyp = myHypos.begin(); for ( ; hyp != myHypos.end(); ++hyp ) @@ -235,6 +288,7 @@ void _pyGen::Process( const Handle(_pyCommand)& theCommand ) // CreateHypothesis( theHypType, theLibName ) // Compute( mesh, geom ) + // mesh creation if ( theCommand->GetMethod() == "CreateMesh" || theCommand->GetMethod() == "CreateEmptyMesh" ) { @@ -272,14 +326,29 @@ void _pyGen::Process( const Handle(_pyCommand)& theCommand ) myHasPattern = true; } - // smeshgen.Method() --> smesh.smesh.Method() - theCommand->SetObject( SMESH_2smeshpy::GenName() ); - // Concatenate( [mesh1, ...], ... ) if ( theCommand->GetMethod() == "Concatenate" ) { AddMeshAccessorMethod( theCommand ); } + + // Replace name of SMESH_Gen + + // names of SMESH_Gen methods fully equal to methods defined in smesh.py + static TStringSet smeshpyMethods; + if ( smeshpyMethods.empty() ) { + const char * names[] = + { "SetEmbeddedMode","IsEmbeddedMode","SetCurrentStudy","GetCurrentStudy", + "GetPattern","GetSubShapesId", + "" }; // <- mark of array end + smeshpyMethods.Insert( names ); + } + if ( smeshpyMethods.Contains( theCommand->GetMethod() )) + // smeshgen.Method() --> smesh.Method() + theCommand->SetObject( SMESH_2smeshpy::SmeshpyName() ); + else + // smeshgen.Method() --> smesh.smesh.Method() + theCommand->SetObject( SMESH_2smeshpy::GenName() ); } //================================================================================ @@ -372,13 +441,13 @@ Handle(_pyHypothesis) _pyGen::FindHyp( const _pyID& theHypID ) //================================================================================ Handle(_pyHypothesis) _pyGen::FindAlgo( const _pyID& theGeom, const _pyID& theMesh, - const TCollection_AsciiString& theAlgoType ) + const Handle(_pyHypothesis)& theHypothesis ) { list< Handle(_pyHypothesis) >::iterator hyp = myHypos.begin(); for ( ; hyp != myHypos.end(); ++hyp ) if ( !hyp->IsNull() && (*hyp)->IsAlgo() && - (*hyp)->GetType() == theAlgoType && + theHypothesis->CanBeCreatedBy( (*hyp)->GetAlgoType() ) && (*hyp)->GetGeom() == theGeom && (*hyp)->GetMesh() == theMesh ) return *hyp; @@ -472,7 +541,7 @@ static bool sameGroupType( const _pyID& grpID, case GEOM::SOLID: case GEOM::SHELL: type = SMESH::VOLUME; break; case GEOM::COMPOUND: { - GEOM::GEOM_Gen_var aGeomGen = SMESH_Gen_i::GetSMESHGen()->GetGeomEngine(); + GEOM::GEOM_Gen_ptr aGeomGen = SMESH_Gen_i::GetSMESHGen()->GetGeomEngine(); if ( !aGeomGen->_is_nil() ) { GEOM::GEOM_IGroupOperations_var aGrpOp = aGeomGen->GetIGroupOperations( study->StudyId() ); @@ -535,7 +604,8 @@ _pyMesh::_pyMesh(const Handle(_pyCommand) theCreationCmd): void _pyMesh::Process( const Handle(_pyCommand)& theCommand ) { - // smesh.py wraps the following methods: + // some methods of SMESH_Mesh interface needs special conversion + // to methods of Mesh python class // // 1. GetSubMesh(geom, name) + AddHypothesis(geom, algo) // --> in Mesh_Algorithm.Create(mesh, geom, hypo, so) @@ -543,21 +613,16 @@ void _pyMesh::Process( const Handle(_pyCommand)& theCommand ) // --> in Mesh_Algorithm.Hypothesis(hyp, args, so) // 3. CreateGroupFromGEOM(type, name, grp) // --> in Mesh.Group(grp, name="") - // 4. ExportToMED(f, opt, version) - // --> in Mesh.ExportToMED( f, version, opt=0 ) - // 5. ExportMED(f, opt) - // --> in Mesh.ExportMED( f,opt=0 ) - // 6. ExportDAT(f) - // --> in Mesh.ExportDAT( f ) - // 7. ExportUNV(f) - // --> in Mesh.ExportUNV(f) - // 8. ExportSTL(f, ascii) - // --> in Mesh.ExportSTL(f, ascii=1) + // 4. ExportToMED(f, auto_groups, version) + // --> in Mesh.ExportMED( f, auto_groups, version ) + // 5. etc const TCollection_AsciiString method = theCommand->GetMethod(); + // ---------------------------------------------------------------------- if ( method == "GetSubMesh" ) { mySubmeshes.push_back( theCommand ); } + // ---------------------------------------------------------------------- else if ( method == "AddHypothesis" ) { // mesh.AddHypothesis(geom, HYPO ) myAddHypCmds.push_back( theCommand ); // set mesh to hypo @@ -569,6 +634,7 @@ void _pyMesh::Process( const Handle(_pyCommand)& theCommand ) hyp->SetMesh( this->GetID() ); } } + // ---------------------------------------------------------------------- else if ( method == "CreateGroupFromGEOM" ) {// (type, name, grp) _pyID grp = theCommand->GetArg( 3 ); if ( sameGroupType( grp, theCommand->GetArg( 1 )) ) { // --> Group(grp) @@ -580,16 +646,18 @@ void _pyMesh::Process( const Handle(_pyCommand)& theCommand ) AddMeshAccess( theCommand ); } } - else if ( method == "ExportToMED" ) {//(f, opt, version) - // --> (f, version, opt) - _pyID opt = theCommand->GetArg( 2 ); - _pyID ver = theCommand->GetArg( 3 ); - theCommand->SetArg( 2, ver ); - theCommand->SetArg( 3, opt ); + // ---------------------------------------------------------------------- + else if ( method == "ExportToMED" ) { // ExportToMED() --> ExportMED() + theCommand->SetMethod( "ExportMED" ); + } + // ---------------------------------------------------------------------- + else if ( method == "CreateGroup" ) { // CreateGroup() --> CreateEmptyGroup() + theCommand->SetMethod( "CreateEmptyGroup" ); } + // ---------------------------------------------------------------------- else if ( method == "RemoveHypothesis" ) // (geom, hyp) { - const _pyID & hypID = theCommand->GetArg( 2 ); + _pyID hypID = theCommand->GetArg( 2 ); // check if this mesh still has corresponding addition command bool hasAddCmd = false; @@ -609,62 +677,55 @@ void _pyMesh::Process( const Handle(_pyCommand)& theCommand ) } Handle(_pyHypothesis) hyp = theGen->FindHyp( hypID ); if ( ! hasAddCmd ) { // hypo addition already wrapped - // access to wrapped mesh - AddMeshAccess( theCommand ); - // access to wrapped algo - if ( !hyp.IsNull() && hyp->IsAlgo() && hyp->IsWrapped() ) - theCommand->SetArg( 2, theCommand->GetArg( 2 ) + ".GetAlgorithm()" ); + // RemoveHypothesis(geom, hyp) --> RemoveHypothesis( hyp, geom=0 ) + _pyID geom = theCommand->GetArg( 1 ); + theCommand->RemoveArgs(); + theCommand->SetArg( 1, hypID ); + if ( geom != GetGeom() ) + theCommand->SetArg( 2, geom ); } // remove hyp from myHypos myHypos.remove( hyp ); } - - // leave only one " mesh_editor_ = mesh.GetMeshEditor()" - else if ( theCommand->GetMethod() == "GetMeshEditor") - { - if ( myHasEditor ) - theCommand->Clear(); - else - AddMeshAccess( theCommand ); - myHasEditor = true; - } - - // apply theCommand to the mesh wrapped by smeshpy mesh + // add accessor method if necessary else { - AddMeshAccess( theCommand ); + if ( NeedMeshAccess( theCommand )) + // apply theCommand to the mesh wrapped by smeshpy mesh + AddMeshAccess( theCommand ); } } -namespace { - - //================================================================================ - /*! - * \brief add addition result treatement command - * \param addCmd - hypothesis addition command - */ - //================================================================================ +//================================================================================ +/*! + * \brief Return True if addition of accesor method is needed + */ +//================================================================================ - void addErrorTreatmentCmd( Handle(_pyCommand) & addCmd, - const bool isAlgo) - { - return; // TO DEBUD - TreatHypoStatus() is not placed right after addCmd - // addCmd: status = mesh.AddHypothesis( geom, hypo ) - // treatement command: - // def TreatHypoStatus(status, hypName, geomName, isAlgo): - TCollection_AsciiString status = addCmd->GetResultValue(); - if ( !status.IsEmpty() ) { - const _pyID& geomID = addCmd->GetArg( 1 ); - const _pyID& hypoID = addCmd->GetArg( 2 ); - TCollection_AsciiString cmdStr = addCmd->GetIndentation() + - SMESH_2smeshpy::SmeshpyName() + ".TreatHypoStatus( " + status + ", " + - SMESH_2smeshpy::SmeshpyName() + ".GetName(" + hypoID + "), " + - SMESH_2smeshpy::SmeshpyName() + ".GetName(" + geomID + "), " + - (char*)( isAlgo ? "True" : "False" ) + " )"; - Handle(_pyCommand) cmd = theGen->AddCommand( cmdStr ); - addCmd->AddDependantCmd( cmd, true ); - } - } +bool _pyMesh::NeedMeshAccess( const Handle(_pyCommand)& theCommand ) +{ + // names of SMESH_Mesh methods fully equal to methods of class Mesh, so + // no conversion is needed for them at all: + static TStringSet sameMethods; + if ( sameMethods.empty() ) { + const char * names[] = + { "ExportDAT","ExportUNV","ExportSTL", "RemoveGroup","RemoveGroupWithContents", + "GetGroups","UnionGroups","IntersectGroups","CutGroups","GetLog","GetId","ClearLog", + "GetStudyId","HasDuplicatedGroupNamesMED","GetMEDMesh","NbNodes","NbElements", + "NbEdges","NbEdgesOfOrder","NbFaces","NbFacesOfOrder","NbTriangles", + "NbTrianglesOfOrder","NbQuadrangles","NbQuadranglesOfOrder","NbPolygons","NbVolumes", + "NbVolumesOfOrder","NbTetras","NbTetrasOfOrder","NbHexas","NbHexasOfOrder", + "NbPyramids","NbPyramidsOfOrder","NbPrisms","NbPrismsOfOrder","NbPolyhedrons", + "NbSubMesh","GetElementsId","GetElementsByType","GetNodesId","GetElementType", + "GetSubMeshElementsId","GetSubMeshNodesId","GetSubMeshElementType","Dump","GetNodeXYZ", + "GetNodeInverseElements","GetShapeID","GetShapeIDForElem","GetElemNbNodes", + "GetElemNode","IsMediumNode","IsMediumNodeOfAnyElem","ElemNbEdges","ElemNbFaces", + "IsPoly","IsQuadratic","BaryCenter","GetHypothesisList", + "" }; // <- mark of end + sameMethods.Insert( names ); + } + + return !sameMethods.Contains( theCommand->GetMethod() ); } //================================================================================ @@ -682,19 +743,19 @@ void _pyMesh::Flush() for ( cmd = myAddHypCmds.begin(); cmd != myAddHypCmds.end(); ++cmd ) { Handle(_pyCommand) addCmd = *cmd; - const _pyID& algoID = addCmd->GetArg( 2 ); + _pyID algoID = addCmd->GetArg( 2 ); Handle(_pyHypothesis) algo = theGen->FindHyp( algoID ); if ( algo.IsNull() || !algo->IsAlgo() ) continue; // try to convert _pyID geom = addCmd->GetArg( 1 ); + bool isLocalAlgo = ( geom != GetGeom() ); if ( algo->Addition2Creation( addCmd, this->GetID() )) // OK { // wrapped algo is created atfer mesh creation GetCreationCmd()->AddDependantCmd( addCmd ); - if ( geom != GetGeom() ) // local algo - { + if ( isLocalAlgo ) { // mesh.AddHypothesis(geom, ALGO ) --> mesh.AlgoMethod(geom) addCmd->SetArg( addCmd->GetNbArgs() + 1, TCollection_AsciiString( "geom=" ) + geom ); @@ -709,15 +770,13 @@ void _pyMesh::Flush() } } } - else // ALGO was already created + else // KO - ALGO was already created { - // mesh.AddHypothesis(geom, ALGO ) --> mesh.GetMesh().AddHypothesis(geom, ALGO ) - AddMeshAccess( addCmd ); - // mesh.GetMesh().AddHypothesis(geom, ALGO ) -> - // mesh.GetMesh().AddHypothesis(geom, ALGO.GetAlgorithm() ) - addCmd->SetArg( 2, addCmd->GetArg( 2 ) + ".GetAlgorithm()" ); - // add addition result treatement cmd - addErrorTreatmentCmd( addCmd, true ); + // mesh.AddHypothesis(geom, ALGO) --> mesh.AddHypothesis(ALGO, geom=0) + addCmd->RemoveArgs(); + addCmd->SetArg( 1, algoID ); + if ( isLocalAlgo ) + addCmd->SetArg( 2, geom ); } } @@ -726,24 +785,27 @@ void _pyMesh::Flush() for ( cmd = myAddHypCmds.begin(); cmd != myAddHypCmds.end(); ++cmd ) { Handle(_pyCommand) addCmd = *cmd; - const _pyID& hypID = addCmd->GetArg( 2 ); + _pyID hypID = addCmd->GetArg( 2 ); Handle(_pyHypothesis) hyp = theGen->FindHyp( hypID ); if ( hyp.IsNull() || hyp->IsAlgo() ) continue; - if ( !hyp->Addition2Creation( addCmd, this->GetID() )) - { - AddMeshAccess( addCmd ); - // add addition result treatement cmd - addErrorTreatmentCmd( addCmd, false ); + bool converted = hyp->Addition2Creation( addCmd, this->GetID() ); + if ( !converted ) { + // mesh.AddHypothesis(geom, HYP) --> mesh.AddHypothesis(HYP, geom=0) + _pyID geom = addCmd->GetArg( 1 ); + addCmd->RemoveArgs(); + addCmd->SetArg( 1, hypID ); + if ( geom != GetGeom() ) + addCmd->SetArg( 2, geom ); } } // sm = mesh.GetSubMesh(geom, name) --> sm = mesh.GetMesh().GetSubMesh(geom, name) - for ( cmd = mySubmeshes.begin(); cmd != mySubmeshes.end(); ++cmd ) { - Handle(_pyCommand) subCmd = *cmd; - if ( subCmd->GetNbArgs() > 0 ) - AddMeshAccess( subCmd ); - } +// for ( cmd = mySubmeshes.begin(); cmd != mySubmeshes.end(); ++cmd ) { +// Handle(_pyCommand) subCmd = *cmd; +// if ( subCmd->GetNbArgs() > 0 ) +// AddMeshAccess( subCmd ); +// } myAddHypCmds.clear(); mySubmeshes.clear(); @@ -753,6 +815,61 @@ void _pyMesh::Flush() (*hyp)->Flush(); } +//================================================================================ +/*! + * \brief MeshEditor convert its commands to ones of mesh + */ +//================================================================================ + +_pyMeshEditor::_pyMeshEditor(const Handle(_pyCommand)& theCreationCmd): + _pyObject( theCreationCmd ) +{ + myMesh = theCreationCmd->GetObject(); + myCreationCmdStr = theCreationCmd->GetString(); + theCreationCmd->Clear(); +} + +//================================================================================ +/*! + * \brief convert its commands to ones of mesh + */ +//================================================================================ + +void _pyMeshEditor::Process( const Handle(_pyCommand)& theCommand) +{ + // names of SMESH_MeshEditor methods fully equal to methods of class Mesh, so + // commands calling this methods are converted to calls of methods of Mesh + static TStringSet sameMethods; + if ( sameMethods.empty() ) { + const char * names[] = { + "RemoveElements","RemoveNodes","AddNode","AddEdge","AddFace","AddPolygonalFace", + "AddVolume","AddPolyhedralVolume","AddPolyhedralVolumeByFaces","MoveNode", + "InverseDiag","DeleteDiag","Reorient","ReorientObject","SplitQuad","SplitQuadObject", + "BestSplit","Smooth","SmoothObject","SmoothParametric","SmoothParametricObject", + "ConvertToQuadratic","ConvertFromQuadratic","RenumberNodes","RenumberElements", + "RotationSweep","RotationSweepObject","ExtrusionSweep","AdvancedExtrusion", + "ExtrusionSweepObject","ExtrusionSweepObject1D","ExtrusionSweepObject2D","Mirror", + "MirrorObject","Translate","TranslateObject","Rotate","RotateObject", + "FindCoincidentNodes","FindCoincidentNodesOnPart","MergeNodes","FindEqualElements", + "MergeElements","MergeEqualElements","SewFreeBorders","SewConformFreeBorders", + "SewBorderToSide","SewSideElements","ChangeElemNodes","GetLastCreatedNodes", + "GetLastCreatedElems", + "" }; // <- mark of end + sameMethods.Insert( names ); + } + + if ( sameMethods.Contains( theCommand->GetMethod() )) { + theCommand->SetObject( myMesh ); + } + else { + // editor creation command is needed only if any editor function is called + if ( !myCreationCmdStr.IsEmpty() ) { + GetCreationCmd()->GetString() = myCreationCmdStr; + myCreationCmdStr.Clear(); + } + } +} + //================================================================================ /*! * \brief _pyHypothesis constructor @@ -855,25 +972,37 @@ Handle(_pyHypothesis) _pyHypothesis::NewHypothesis( const Handle(_pyCommand)& th hyp->AddArgMethod( "SetNumberOfSegments"); hyp->AddArgMethod( "SetPythonLog10RatioFunction"); } - // 2D ---------- - else if ( hypType == "MEFISTO_2D" ) { + // MEFISTO_2D ---------- + else if ( hypType == "MEFISTO_2D" ) { // MEFISTO_2D algo->SetConvMethodAndType( "Triangle", hypType.ToCString()); } else if ( hypType == "MaxElementArea" ) { hyp->SetConvMethodAndType( "MaxElementArea", "MEFISTO_2D"); + hyp->SetConvMethodAndType( "MaxElementArea", "NETGEN_2D_ONLY"); hyp->AddArgMethod( "SetMaxElementArea"); } else if ( hypType == "LengthFromEdges" ) { hyp->SetConvMethodAndType( "LengthFromEdges", "MEFISTO_2D"); + hyp->SetConvMethodAndType( "LengthFromEdges", "NETGEN_2D_ONLY"); } + // Quadrangle_2D ---------- else if ( hypType == "Quadrangle_2D" ) { algo->SetConvMethodAndType( "Quadrangle" , hypType.ToCString()); } else if ( hypType == "QuadranglePreference" ) { hyp->SetConvMethodAndType( "QuadranglePreference", "Quadrangle_2D"); - } - // 3D ---------- - else if ( hypType == "NETGEN_3D") { + hyp->SetConvMethodAndType( "QuadranglePreference", "NETGEN_2D_ONLY"); + } + // NETGEN ---------- +// else if ( hypType == "NETGEN_2D") { // 1D-2D +// algo->SetConvMethodAndType( "Triangle" , hypType.ToCString()); +// algo->myArgs.Append( "algo=smesh.NETGEN" ); +// } + else if ( hypType == "NETGEN_2D_ONLY") { // 2D + algo->SetConvMethodAndType( "Triangle" , hypType.ToCString()); + algo->myArgs.Append( "algo=smesh.NETGEN_2D" ); + } + else if ( hypType == "NETGEN_3D") { // 3D algo->SetConvMethodAndType( "Tetrahedron" , hypType.ToCString()); algo->myArgs.Append( "algo=smesh.NETGEN" ); } @@ -881,14 +1010,16 @@ Handle(_pyHypothesis) _pyHypothesis::NewHypothesis( const Handle(_pyCommand)& th hyp->SetConvMethodAndType( "MaxElementVolume", "NETGEN_3D"); hyp->AddArgMethod( "SetMaxElementVolume" ); } + // GHS3D_3D ---------- else if ( hypType == "GHS3D_3D" ) { algo->SetConvMethodAndType( "Tetrahedron", hypType.ToCString()); algo->myArgs.Append( "algo=smesh.GHS3D" ); } + // Hexa_3D --------- else if ( hypType == "Hexa_3D" ) { algo->SetConvMethodAndType( "Hexahedron", hypType.ToCString()); } - // Repetitive --------- + // Repetitive Projection_1D --------- else if ( hypType == "Projection_1D" ) { algo->SetConvMethodAndType( "Projection1D", hypType.ToCString()); } @@ -899,6 +1030,7 @@ Handle(_pyHypothesis) _pyHypothesis::NewHypothesis( const Handle(_pyCommand)& th // 2 args of SetVertexAssociation() will become the 3-th and 4-th args of hyp creation command hyp->AddArgMethod( "SetVertexAssociation", 2 ); } + // Projection_2D --------- else if ( hypType == "Projection_2D" ) { algo->SetConvMethodAndType( "Projection2D", hypType.ToCString()); } @@ -908,6 +1040,7 @@ Handle(_pyHypothesis) _pyHypothesis::NewHypothesis( const Handle(_pyCommand)& th hyp->AddArgMethod( "SetSourceMesh"); hyp->AddArgMethod( "SetVertexAssociation", 4 ); } + // Projection_3D --------- else if ( hypType == "Projection_3D" ) { algo->SetConvMethodAndType( "Projection3D", hypType.ToCString()); } @@ -917,9 +1050,11 @@ Handle(_pyHypothesis) _pyHypothesis::NewHypothesis( const Handle(_pyCommand)& th hyp->AddArgMethod( "SetSourceMesh"); hyp->AddArgMethod( "SetVertexAssociation", 4 ); } + // Prism_3D --------- else if ( hypType == "Prism_3D" ) { algo->SetConvMethodAndType( "Prism", hypType.ToCString()); } + // RadialPrism_3D --------- else if ( hypType == "RadialPrism_3D" ) { algo->SetConvMethodAndType( "Prism", hypType.ToCString()); } @@ -932,7 +1067,7 @@ Handle(_pyHypothesis) _pyHypothesis::NewHypothesis( const Handle(_pyCommand)& th hyp->SetConvMethodAndType( "LayerDistribution", "RadialPrism_3D"); } - if ( !algo->GetCreationMethod().IsEmpty() ) { + if ( algo->IsValid() ) { return algo; } return hyp; @@ -960,7 +1095,7 @@ bool _pyHypothesis::Addition2Creation( const Handle(_pyCommand)& theCmd, Handle(_pyHypothesis) algo; if ( !IsAlgo() ) { // find algo created on myGeom in theMesh - algo = theGen->FindAlgo( myGeom, theMesh, GetType() ); + algo = theGen->FindAlgo( myGeom, theMesh, this ); if ( algo.IsNull() ) return false; algo->GetCreationCmd()->AddDependantCmd( theCmd ); @@ -970,7 +1105,7 @@ bool _pyHypothesis::Addition2Creation( const Handle(_pyCommand)& theCmd, // mesh.AddHypothesis(geom,hyp) --> hyp = .myCreationMethod(args) theCmd->SetResultValue( GetID() ); theCmd->SetObject( IsAlgo() ? theMesh : algo->GetID()); - theCmd->SetMethod( myCreationMethod ); + theCmd->SetMethod( IsAlgo() ? GetAlgoCreationMethod() : GetCreationMethod( algo->GetAlgoType() )); // set args theCmd->RemoveArgs(); for ( int i = 1; i <= myArgs.Length(); ++i ) { @@ -1190,7 +1325,7 @@ bool _pyLayerDistributionHypo::Addition2Creation( const Handle(_pyCommand)& theA // Convert my creation => me = RadialPrismAlgo.Get3DHypothesis() // find RadialPrism algo created on for theMesh - Handle(_pyHypothesis) algo = theGen->FindAlgo( geom, theMesh, this->GetType() ); + Handle(_pyHypothesis) algo = theGen->FindAlgo( geom, theMesh, this ); if ( !algo.IsNull() ) { GetCreationCmd()->SetObject( algo->GetID() ); GetCreationCmd()->SetMethod( "Get3DHypothesis" ); @@ -1306,7 +1441,7 @@ bool _pySegmentLengthAroundVertexHyp::Addition2Creation( const Handle(_pyCommand while ( algo.IsNull() && !geom.IsEmpty()) { // try to find geom as a father of geom = FatherID( geom ); - algo = theGen->FindAlgo( geom, theMeshID, GetType() ); + algo = theGen->FindAlgo( geom, theMeshID, this ); } if ( algo.IsNull() ) return false; // also possible to find geom as brother of veretex... diff --git a/src/SMESH_I/SMESH_2smeshpy.hxx b/src/SMESH_I/SMESH_2smeshpy.hxx index 2f1bc027c..a09a84cd6 100644 --- a/src/SMESH_I/SMESH_2smeshpy.hxx +++ b/src/SMESH_I/SMESH_2smeshpy.hxx @@ -36,46 +36,23 @@ // =========================================================================================== /*! - * \brief Tool converting SMESH engine calls into commands defined in smesh.py - * * This file was created in order to respond to requirement of bug PAL10494: * SMESH python dump uses idl interface. * * The creation reason is that smesh.py commands defining hypotheses encapsulate * several SMESH engine method calls. As well, the dependencies between smesh.py - * classes differ from ones between SMESH IDL interfaces. + * classes differ from ones between corresponding SMESH IDL interfaces. * - * The only API method here is SMESH_2smeshpy::ConvertScript(), the rest ones are - * for internal usage + * Everything here is for internal usage by SMESH_2smeshpy::ConvertScript() + * declared in SMESH_PythonDump.hxx * - * See comments to _pyHypothesis class to know how to assure convertion of a new hypothesis + * See comments to _pyHypothesis class to know how to assure convertion of a new + * type of hypothesis */ // =========================================================================================== class Resource_DataMapOfAsciiStringAsciiString; -class SMESH_2smeshpy -{ -public: - /*! - * \brief Convert a python script using commands of smesh.py - * \param theScript - Input script - * \param theEntry2AccessorMethod - The returning method names to access to - * objects wrapped with python class - * \retval TCollection_AsciiString - Convertion result - */ - static TCollection_AsciiString - ConvertScript(const TCollection_AsciiString& theScript, - Resource_DataMapOfAsciiStringAsciiString& theEntry2AccessorMethod); - - /*! - * \brief Return the name of the python file wrapping IDL API - * \retval TCollection_AsciiString - The file name - */ - static char* SmeshpyName() { return "smesh"; } - static char* GenName() { return "smesh.smesh"; } -}; - // =========================================================================================== // ===================== // INTERNAL STUFF @@ -93,6 +70,7 @@ DEFINE_STANDARD_HANDLE (_pyCommand ,Standard_Transient); DEFINE_STANDARD_HANDLE (_pyObject ,Standard_Transient); DEFINE_STANDARD_HANDLE (_pyGen ,_pyObject); DEFINE_STANDARD_HANDLE (_pyMesh ,_pyObject); +DEFINE_STANDARD_HANDLE (_pyMeshEditor,_pyObject); DEFINE_STANDARD_HANDLE (_pyHypothesis,_pyObject); DEFINE_STANDARD_HANDLE (_pyAlgorithm ,_pyHypothesis); @@ -198,20 +176,21 @@ public: void Flush(); Handle(_pyHypothesis) FindHyp( const _pyID& theHypID ); Handle(_pyHypothesis) FindAlgo( const _pyID& theGeom, const _pyID& theMesh, - const TCollection_AsciiString& theAlgoType); + const Handle(_pyHypothesis)& theHypothesis); void ExchangeCommands( Handle(_pyCommand) theCmd1, Handle(_pyCommand) theCmd2 ); void SetCommandAfter( Handle(_pyCommand) theCmd, Handle(_pyCommand) theAfterCmd ); std::list< Handle(_pyCommand) >& GetCommands() { return myCommands; } void SetAccessorMethod(const _pyID& theID, const char* theMethod ); bool AddMeshAccessorMethod( Handle(_pyCommand) theCmd ) const; bool AddAlgoAccessorMethod( Handle(_pyCommand) theCmd ) const; - const char* AccessorMethod() const { return SMESH_2smeshpy::GenName(); } + const char* AccessorMethod() const; private: - std::map< _pyID, Handle(_pyMesh) > myMeshes; - std::list< Handle(_pyHypothesis) > myHypos; - std::list< Handle(_pyCommand) > myCommands; - int myNbCommands; - bool myHasPattern; + std::map< _pyID, Handle(_pyMesh) > myMeshes; + std::map< _pyID, Handle(_pyMeshEditor) > myMeshEditors; + std::list< Handle(_pyHypothesis) > myHypos; + std::list< Handle(_pyCommand) > myCommands; + int myNbCommands; + bool myHasPattern; Resource_DataMapOfAsciiStringAsciiString& myID2AccessorMethod; DEFINE_STANDARD_RTTI (_pyGen) @@ -236,6 +215,7 @@ public: void Flush(); const char* AccessorMethod() const { return _pyMesh_ACCESS_METHOD; } private: + static bool NeedMeshAccess( const Handle(_pyCommand)& theCommand ); static void AddMeshAccess( const Handle(_pyCommand)& theCommand ) { theCommand->SetObject( theCommand->GetObject() + "." _pyMesh_ACCESS_METHOD ); } @@ -243,20 +223,36 @@ private: }; #undef _pyMesh_ACCESS_METHOD +// ------------------------------------------------------------------------------------- +/*! + * \brief MeshEditor convert its commands to ones of mesh + */ +// ------------------------------------------------------------------------------------- +class _pyMeshEditor: public _pyObject +{ + _pyID myMesh; + TCollection_AsciiString myCreationCmdStr; +public: + _pyMeshEditor(const Handle(_pyCommand)& theCreationCmd); + void Process( const Handle(_pyCommand)& theCommand); + virtual void Flush() {} + + DEFINE_STANDARD_RTTI (_pyMesh) +}; + // ------------------------------------------------------------------------------------- /*! * \brief Root class for hypothesis * - * HOWTO assure convertion of a new hypothesis - * In NewHypothesis(): - * 1. add a case for the name of the new hypothesis and - * 2. initialize _pyHypothesis fields: - * . myDim - hypothesis dimention; - * . myType - type name of the algorithm creating the hypothesis; - * . myCreationMethod - method name of the algorithm creating the hypothesis; - * . append to myArgMethods interface methods setting param values in the - * order they are used when myCreationMethod is called. It is supposed that - * each interface method sets only one parameter, if it is not so, you are + * HOWTO assure convertion of a new type of hypothesis + * In _pyHypothesis::NewHypothesis(): + * 1. add a case for the name of the new hypothesis + * 2. use SetConvMethodAndType() to set + * . for algo: algorithm name and method of Mesh creating the algo + * . for hypo: name of the algorithm and method creating the hypothesis + * 3. append to myArgMethods interface methods setting param values in the + * order they are used when creation method is called. If arguments of + * the creation method can't be easily got from calls of hypothesis methods, you are * to derive a specific class from _pyHypothesis that would redefine Process(), * see _pyComplexParamHypo for example */ @@ -264,41 +260,43 @@ private: class _pyHypothesis: public _pyObject { protected: - bool myIsAlgo, myIsWrapped; //myIsLocal, myIsConverted; - //int myDim/*, myAdditionCmdNb*/; - _pyID myGeom, myMesh; - TCollection_AsciiString myCreationMethod, myType; - TColStd_SequenceOfAsciiString myArgs; - TColStd_SequenceOfAsciiString myArgMethods; - TColStd_SequenceOfInteger myNbArgsByMethod; + bool myIsAlgo, myIsWrapped; + _pyID myGeom, myMesh; + // a hypothesis can be used and created by different algos by different methods + std::map myType2CreationMethod; + //TCollection_AsciiString myCreationMethod, myType; + TColStd_SequenceOfAsciiString myArgs; // creation arguments + TColStd_SequenceOfAsciiString myArgMethods; // hypo methods setting myArgs + TColStd_SequenceOfInteger myNbArgsByMethod; // nb args set by each method std::list myArgCommands; std::list myUnknownCommands; public: _pyHypothesis(const Handle(_pyCommand)& theCreationCmd); - void SetConvMethodAndType(const char* creationMethod, const char* type=0) - { myCreationMethod = (char*)creationMethod; if ( type ) myType = (char*)type; } -// void SetDimMethodType(const int dim, const char* creationMethod, const char* type=0) -// { myDim = dim; myCreationMethod = (char*)creationMethod; if ( type ) myType = (char*)type; } + void SetConvMethodAndType(const char* creationMethod, const char* type) + { myType2CreationMethod[ (char*)type ] = (char*)creationMethod; } void AddArgMethod(const char* method, const int nbArgs = 1) { myArgMethods.Append( (char*)method ); myNbArgsByMethod.Append( nbArgs ); } const TColStd_SequenceOfAsciiString& GetArgs() const { return myArgs; } - const TCollection_AsciiString& GetCreationMethod() const { return myCreationMethod; } const std::list& GetArgCommands() const { return myArgCommands; } void ClearAllCommands(); virtual bool IsAlgo() const { return myIsAlgo; } + bool IsValid() const { return !myType2CreationMethod.empty(); } bool IsWrapped() const { return myIsWrapped; } - //bool & IsConverted() { return myIsConverted; } - //int GetDim() const { return myDim; } const _pyID & GetGeom() const { return myGeom; } void SetMesh( const _pyID& theMeshId) { if ( myMesh.IsEmpty() ) myMesh = theMeshId; } const _pyID & GetMesh() const { return myMesh; } - const TCollection_AsciiString GetType() { return myType; } + const TCollection_AsciiString& GetAlgoType() const + { return myType2CreationMethod.begin()->first; } + const TCollection_AsciiString& GetAlgoCreationMethod() const + { return myType2CreationMethod.begin()->second; } + bool CanBeCreatedBy(const TCollection_AsciiString& algoType ) const + { return myType2CreationMethod.find( algoType ) != myType2CreationMethod.end(); } + const TCollection_AsciiString& GetCreationMethod(const TCollection_AsciiString& algoType) const + { return myType2CreationMethod.find( algoType )->second; } bool IsWrappable(const _pyID& theMesh) { return !myIsWrapped && myMesh == theMesh; } virtual bool Addition2Creation( const Handle(_pyCommand)& theAdditionCmd, const _pyID& theMesh); static Handle(_pyHypothesis) NewHypothesis( const Handle(_pyCommand)& theCreationCmd); - // bool HasMesh() const { return !myMesh.IsEmpty(); } - // void SetGeom( const _pyID& theGeomID ) { myGeom = theGeomID; } void Process( const Handle(_pyCommand)& theCommand); void Flush(); diff --git a/src/SMESH_I/SMESH_Filter_i.cxx b/src/SMESH_I/SMESH_Filter_i.cxx index 85cec50a5..51bc29f22 100644 --- a/src/SMESH_I/SMESH_Filter_i.cxx +++ b/src/SMESH_I/SMESH_Filter_i.cxx @@ -396,48 +396,49 @@ static TopoDS_Shape getShapeByName( const char* theName ) return TopoDS_Shape(); } -static TopoDS_Shape getShapeByID( const char* theID ) +static TopoDS_Shape getShapeByID (const char* theID) { - if ( theID != 0 && theID!="" ) - { + if (theID != 0 && theID != "") { SMESH_Gen_i* aSMESHGen = SMESH_Gen_i::GetSMESHGen(); SALOMEDS::Study_ptr aStudy = aSMESHGen->GetCurrentStudy(); - if ( aStudy != 0 ) - { - CORBA::Object_var obj = aStudy->ConvertIORToObject(theID); - GEOM::GEOM_Object_var aGeomObj = GEOM::GEOM_Object::_narrow( obj ); + if (aStudy != 0) { + SALOMEDS::SObject_var aSObj = aStudy->FindObjectID(theID); + SALOMEDS::GenericAttribute_var anAttr; + if (!aSObj->_is_nil() && aSObj->FindAttribute(anAttr, "AttributeIOR")) { + SALOMEDS::AttributeIOR_var anIOR = SALOMEDS::AttributeIOR::_narrow(anAttr); + CORBA::String_var aVal = anIOR->Value(); + CORBA::Object_var obj = aStudy->ConvertIORToObject(aVal); + GEOM::GEOM_Object_var aGeomObj = GEOM::GEOM_Object::_narrow(obj); - if ( !aGeomObj->_is_nil() ) - { - GEOM::GEOM_Gen_ptr aGEOMGen = SMESH_Gen_i::GetGeomEngine(); + if (!aGeomObj->_is_nil()) { + GEOM::GEOM_Gen_ptr aGEOMGen = SMESH_Gen_i::GetGeomEngine(); TopoDS_Shape aLocShape = aSMESHGen->GetShapeReader()->GetShape( aGEOMGen, aGeomObj ); return aLocShape; } + } } } return TopoDS_Shape(); } -static char* getShapeNameByID ( const char* theID ) +static char* getShapeNameByID (const char* theID) { char* aName = ""; - if ( theID != 0 && theID!="" ) - { - SMESH_Gen_i* aSMESHGen = SMESH_Gen_i::GetSMESHGen(); - SALOMEDS::Study_ptr aStudy = aSMESHGen->GetCurrentStudy(); - if ( aStudy != 0 ) - { - SALOMEDS::SObject_var aSObj = aStudy->FindObjectIOR( theID ); - SALOMEDS::GenericAttribute_var anAttr; - if ( !aSObj->_is_nil() && aSObj->FindAttribute( anAttr, "AttributeName") ) - { - SALOMEDS::AttributeName_var aNameAttr = SALOMEDS::AttributeName::_narrow( anAttr ); - aName = aNameAttr->Value(); - } - } + if (theID != 0 && theID != "") { + SMESH_Gen_i* aSMESHGen = SMESH_Gen_i::GetSMESHGen(); + SALOMEDS::Study_ptr aStudy = aSMESHGen->GetCurrentStudy(); + if (aStudy != 0) { + //SALOMEDS::SObject_var aSObj = aStudy->FindObjectIOR( theID ); + SALOMEDS::SObject_var aSObj = aStudy->FindObjectID(theID); + SALOMEDS::GenericAttribute_var anAttr; + if (!aSObj->_is_nil() && aSObj->FindAttribute(anAttr, "AttributeName")) { + SALOMEDS::AttributeName_var aNameAttr = SALOMEDS::AttributeName::_narrow(anAttr); + aName = aNameAttr->Value(); + } } - + } + return aName; } @@ -2057,9 +2058,10 @@ CORBA::Boolean Filter_i::SetCriteria( const SMESH::Filter::Criteria& theCriteria ElementType aTypeOfElem = theCriteria[ i ].TypeOfElement; long aPrecision = theCriteria[ i ].Precision; - TPythonDump()<<"aCriterion = SMESH.Filter.Criterion("<< - aCriterion<<","<FindOrLoad_Component("FactoryServer","GEOM") ); + //CCRT return aGeomEngine._retn(); + if(CORBA::is_nil(myGeomGen)) { Engines::Component_ptr temp=GetLCC()->FindOrLoad_Component("FactoryServer","GEOM"); - myGeomGen = GEOM::GEOM_Gen::_narrow(temp); + myGeomGen=GEOM::GEOM_Gen::_narrow(temp); } return myGeomGen; } @@ -1233,13 +1235,14 @@ CORBA::Boolean SMESH_Gen_i::Compute( SMESH::SMESH_Mesh_ptr theMesh, // Update Python script TPythonDump() << "isDone = " << this << ".Compute( " << theMesh << ", " << theShapeObject << ")"; - TPythonDump() << "if not isDone: print 'Mesh', " << theMesh << ", ': computation failed'"; try { // get mesh servant SMESH_Mesh_i* meshServant = dynamic_cast( GetServant( theMesh ).in() ); ASSERT( meshServant ); if ( meshServant ) { + // NPAL16168: "geometrical group edition from a submesh don't modifiy mesh computation" + meshServant->CheckGeomGroupModif(); // get local TopoDS_Shape TopoDS_Shape myLocShape = GeomObjectToShape( theShapeObject ); // call implementation compute @@ -1247,9 +1250,8 @@ CORBA::Boolean SMESH_Gen_i::Compute( SMESH::SMESH_Mesh_ptr theMesh, return myGen.Compute( myLocMesh, myLocShape); } } - catch ( std::bad_alloc& exc ) { - THROW_SALOME_CORBA_EXCEPTION( "Memory allocation problem", - SALOME::INTERNAL_ERROR ); + catch ( std::bad_alloc ) { + INFOS( "Compute(): lack of memory" ); } catch ( SALOME_Exception& S_ex ) { INFOS( "Compute(): catch exception "<< S_ex.what() ); @@ -2670,6 +2672,7 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent, } // close hypotheses root HDF group aTopGroup->CloseOnDisk(); + aTopGroup = 0; } // --> then we should read&create algorithms @@ -2769,6 +2772,7 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent, } // close algorithms root HDF group aTopGroup->CloseOnDisk(); + aTopGroup = 0; } // --> the rest groups should be meshes @@ -3410,7 +3414,8 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent, } } // close mesh group - aTopGroup->CloseOnDisk(); + if(aTopGroup) + aTopGroup->CloseOnDisk(); } // close HDF file aFile->CloseOnDisk(); diff --git a/src/SMESH_I/SMESH_Gen_i_1.cxx b/src/SMESH_I/SMESH_Gen_i_1.cxx index e76000901..d179f62d1 100644 --- a/src/SMESH_I/SMESH_Gen_i_1.cxx +++ b/src/SMESH_I/SMESH_Gen_i_1.cxx @@ -32,6 +32,7 @@ #include "SMESH_Hypothesis_i.hxx" #include "SMESH_Algo_i.hxx" #include "SMESH_Group_i.hxx" +#include "SMESH_subMesh_i.hxx" #include "SMESH.hxx" diff --git a/src/SMESH_I/SMESH_Mesh_i.cxx b/src/SMESH_I/SMESH_Mesh_i.cxx index 76e5a9821..d10e90141 100644 --- a/src/SMESH_I/SMESH_Mesh_i.cxx +++ b/src/SMESH_I/SMESH_Mesh_i.cxx @@ -52,6 +52,7 @@ #include "SMESH_MeshEditor.hxx" // OCCT Includes +#include #include #include #include @@ -59,7 +60,8 @@ #include #include #include -#include "TCollection_AsciiString.hxx" +#include +#include // STL Includes #include @@ -956,6 +958,139 @@ SMESH::SMESH_Group_ptr SMESH_Mesh_i::CutGroups( SMESH::SMESH_GroupBase_ptr theGr return aResGrp._retn(); } +//================================================================================ +/*! + * \brief Return group items of a group present in a study + */ +//================================================================================ + +static GEOM::GEOM_Object_ptr getGroupItemsFromStudy(CORBA::Object_ptr theMesh, + SMESH_Gen_i* theGen, + list & theItems) +{ + GEOM::GEOM_Object_var groupObj; + SALOMEDS::Study_var study = theGen->GetCurrentStudy(); + GEOM::GEOM_Gen_var geomGen = theGen->GetGeomEngine(); + if ( study->_is_nil() || geomGen->_is_nil() ) + return groupObj._retn(); + + GEOM::GEOM_IGroupOperations_var groupOp = + geomGen->GetIGroupOperations( theGen->GetCurrentStudyID() ); + GEOM::GEOM_IShapesOperations_var shapeOp = + geomGen->GetIShapesOperations( theGen->GetCurrentStudyID() ); + + SALOMEDS::SObject_var meshOS = theGen->ObjectToSObject(study, theMesh); + if ( meshOS->_is_nil() || groupOp->_is_nil() || shapeOp->_is_nil() ) + return groupObj._retn(); + SALOMEDS::SObject_var fatherSO = meshOS->GetFather(); + if ( fatherSO->_is_nil() || fatherSO->Tag() != theGen->GetSubMeshOnCompoundTag() ) + return groupObj._retn(); // keep only submeshes on groups + + SALOMEDS::ChildIterator_var anIter = study->NewChildIterator(meshOS); + if ( anIter->_is_nil() ) return groupObj._retn(); + for ( ; anIter->More(); anIter->Next()) + { + SALOMEDS::SObject_var aSObject = anIter->Value(); + SALOMEDS::SObject_var aRefSO; + if ( !aSObject->_is_nil() && aSObject->ReferencedObject(aRefSO) ) + { + groupObj = GEOM::GEOM_Object::_narrow(aRefSO->GetObject()); + if ( groupObj->_is_nil() ) break; + GEOM::ListOfLong_var ids = groupOp->GetObjects( groupObj ); + GEOM::GEOM_Object_var mainShape = groupObj->GetMainShape(); + for ( int i = 0; i < ids->length(); ++i ) { + GEOM::GEOM_Object_var subShape = shapeOp->GetSubShape( mainShape, ids[i] ); + TopoDS_Shape S = theGen->GeomObjectToShape( subShape ); + if ( !S.IsNull() ) + theItems.push_back( S ); + } + break; + } + } + return groupObj._retn(); +} + +//============================================================================= +/*! + * \brief Update hypotheses assigned to geom groups if the latter change + * + * NPAL16168: "geometrical group edition from a submesh don't modifiy mesh computation" + */ +//============================================================================= + +void SMESH_Mesh_i::CheckGeomGroupModif() +{ + if ( !_impl->HasShapeToMesh() ) return; + + SALOMEDS::Study_var study = _gen_i->GetCurrentStudy(); + if ( study->_is_nil() ) return; + + // check if items of groups changed + map::iterator i_sm = _mapSubMesh.begin(); + for ( ; i_sm != _mapSubMesh.end(); ++i_sm ) + { + const TopoDS_Shape & oldGroupShape = i_sm->second->GetSubShape(); + SMESHDS_SubMesh * oldDS = i_sm->second->GetSubMeshDS(); + if ( !oldDS /*|| !oldDS->IsComplexSubmesh()*/ ) + continue; + int oldID = i_sm->first; + map::iterator i_smIor = _mapSubMeshIor.find( oldID ); + if ( i_smIor == _mapSubMeshIor.end() ) + continue; + list< TopoDS_Shape> newItems; + GEOM::GEOM_Object_var groupObj = getGroupItemsFromStudy ( i_smIor->second, _gen_i, newItems ); + if ( groupObj->_is_nil() ) + continue; + + int nbOldItems = oldDS->IsComplexSubmesh() ? oldDS->NbSubMeshes() : 1; + int nbNewItems = newItems.size(); + bool groupChanged = ( nbOldItems != nbNewItems); + if ( !groupChanged ) { + if ( !oldDS->IsComplexSubmesh() ) { // old group has one item + groupChanged = ( oldGroupShape != newItems.front() ); + } + else { + list::iterator item = newItems.begin(); + for ( ; item != newItems.end() && !groupChanged; ++item ) + { + SMESHDS_SubMesh * itemDS = _impl->GetMeshDS()->MeshElements( *item ); + groupChanged = ( !itemDS || !oldDS->ContainsSubMesh( itemDS )); + } + } + } + // update hypotheses and submeshes if necessary + if ( groupChanged ) + { + // get a new group shape + GEOM_Client* geomClient = _gen_i->GetShapeReader(); + if ( !geomClient ) continue; + TCollection_AsciiString groupIOR = _gen_i->GetGeomEngine()->GetStringFromIOR( groupObj ); + geomClient->RemoveShapeFromBuffer( groupIOR ); + TopoDS_Shape newGroupShape = _gen_i->GeomObjectToShape( groupObj ); + // update hypotheses + list hyps = _impl->GetHypothesisList(oldGroupShape); + list ::iterator hypIt; + for ( hypIt = hyps.begin(); hypIt != hyps.end(); ++hypIt ) + { + _impl->RemoveHypothesis( oldGroupShape, (*hypIt)->GetID()); + _impl->AddHypothesis ( newGroupShape, (*hypIt)->GetID()); + } + // care of submeshes + SMESH_subMesh* newSubmesh = _impl->GetSubMesh( newGroupShape ); + int newID = newSubmesh->GetId(); + if ( newID != oldID ) { + _mapSubMesh [ newID ] = newSubmesh; + _mapSubMesh_i [ newID ] = _mapSubMesh_i [ oldID ]; + _mapSubMeshIor[ newID ] = _mapSubMeshIor[ oldID ]; + _mapSubMesh.erase (oldID); + _mapSubMesh_i.erase (oldID); + _mapSubMeshIor.erase(oldID); + _mapSubMesh_i [ newID ]->changeLocalId( newID ); + } + } + } +} + //============================================================================= /*! * diff --git a/src/SMESH_I/SMESH_Mesh_i.hxx b/src/SMESH_I/SMESH_Mesh_i.hxx index af50b569b..8ad479376 100644 --- a/src/SMESH_I/SMESH_Mesh_i.hxx +++ b/src/SMESH_I/SMESH_Mesh_i.hxx @@ -40,13 +40,14 @@ #include "SMESH_Hypothesis.hxx" #include "SMESH_Mesh.hxx" -#include "SMESH_subMesh_i.hxx" +//#include "SMESH_subMesh_i.hxx" #include "SMESH_subMesh.hxx" #include "SALOME_GenericObj_i.hh" class SMESH_Gen_i; class SMESH_GroupBase_i; +class SMESH_subMesh_i; #include @@ -312,6 +313,13 @@ public: const map& getGroups() { return _mapGroups; } // return an existing group object. + /*! + * \brief Update hypotheses assigned to geom groups if the latter change + * + * NPAL16168: "geometrical group edition from a submesh don't modifiy mesh computation" + */ + void CheckGeomGroupModif(); + virtual SMESH::long_array* GetIDs(); CORBA::LongLong GetMeshPtr(); diff --git a/src/SMESH_I/SMESH_Pattern_i.cxx b/src/SMESH_I/SMESH_Pattern_i.cxx index 13ed3ac89..4f730b387 100644 --- a/src/SMESH_I/SMESH_Pattern_i.cxx +++ b/src/SMESH_I/SMESH_Pattern_i.cxx @@ -40,6 +40,9 @@ #include #include +#include +#include + #include #include @@ -286,8 +289,24 @@ SMESH::point_array* if ( elem && elem->GetType() == SMDSAbs_Face ) fset.insert( static_cast( elem )); } - if (myPattern.Apply( fset, theNodeIndexOnKeyPoint1, theReverse ) && - myPattern.GetMappedPoints( xyzList )) + bool ok = false; + try { +#if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100 + OCC_CATCH_SIGNALS; +#endif + ok = myPattern.Apply( aMesh, fset, theNodeIndexOnKeyPoint1, theReverse ); + } + catch (Standard_Failure& exc) { + MESSAGE("OCCT Exception in SMESH_Pattern: " << exc.GetMessageString()); + } + catch ( std::exception& exc ) { + MESSAGE("STD Exception in SMESH_Pattern: << exc.what()"); + } + catch ( ... ) { + MESSAGE("Unknown Exception in SMESH_Pattern"); + } + + if ( ok && myPattern.GetMappedPoints( xyzList )) { points->length( xyzList.size() ); list::iterator xyzIt = xyzList.begin(); diff --git a/src/SMESH_I/SMESH_PythonDump.hxx b/src/SMESH_I/SMESH_PythonDump.hxx index 6e65a3d41..518e1be92 100644 --- a/src/SMESH_I/SMESH_PythonDump.hxx +++ b/src/SMESH_I/SMESH_PythonDump.hxx @@ -31,6 +31,37 @@ class SMESH_Gen_i; class SMESH_MeshEditor_i; class TCollection_AsciiString; +class Resource_DataMapOfAsciiStringAsciiString; + +// =========================================================================================== +/*! + * \brief Tool converting SMESH engine calls into commands defined in smesh.py + * + * Implementation is in SMESH_2smeshpy.cxx + */ +// =========================================================================================== + +class SMESH_2smeshpy +{ +public: + /*! + * \brief Convert a python script using commands of smesh.py + * \param theScript - Input script + * \param theEntry2AccessorMethod - The returning method names to access to + * objects wrapped with python class + * \retval TCollection_AsciiString - Convertion result + */ + static TCollection_AsciiString + ConvertScript(const TCollection_AsciiString& theScript, + Resource_DataMapOfAsciiStringAsciiString& theEntry2AccessorMethod); + + /*! + * \brief Return the name of the python file wrapping IDL API + * \retval TCollection_AsciiString - The file name + */ + static char* SmeshpyName() { return "smesh"; } + static char* GenName() { return "smesh.smesh"; } +}; namespace SMESH { @@ -39,6 +70,12 @@ namespace SMESH class Filter_i; class Functor_i; +// =========================================================================================== +/*! + * \brief Utility helping in storing SMESH engine calls as python commands + */ +// =========================================================================================== + class SMESH_I_EXPORT TPythonDump { std::ostringstream myStream; @@ -144,5 +181,4 @@ namespace SMESH }; } - #endif diff --git a/src/SMESH_I/SMESH_subMesh_i.cxx b/src/SMESH_I/SMESH_subMesh_i.cxx index 4df569cb6..da14ee1f7 100644 --- a/src/SMESH_I/SMESH_subMesh_i.cxx +++ b/src/SMESH_I/SMESH_subMesh_i.cxx @@ -458,8 +458,14 @@ GEOM::GEOM_Object_ptr SMESH_subMesh_i::GetSubShape() try { if ( _mesh_i->_mapSubMesh.find( _localId ) != _mesh_i->_mapSubMesh.end()) { TopoDS_Shape S = _mesh_i->_mapSubMesh[ _localId ]->GetSubShape(); - if ( !S.IsNull() ) + if ( !S.IsNull() ) { aShapeObj = _gen_i->ShapeToGeomObject( S ); + //mzn: N7PAL16232, N7PAL16233 + //In some cases it's possible that GEOM_Client contains the shape same to S, but + //with another orientation. + if (aShapeObj->_is_nil()) + aShapeObj = _gen_i->ShapeToGeomObject( S.Reversed() ); + } } } catch(SALOME_Exception & S_ex) { diff --git a/src/SMESH_I/SMESH_subMesh_i.hxx b/src/SMESH_I/SMESH_subMesh_i.hxx index 808b07cb6..154ffd7a2 100644 --- a/src/SMESH_I/SMESH_subMesh_i.hxx +++ b/src/SMESH_I/SMESH_subMesh_i.hxx @@ -38,6 +38,7 @@ #include CORBA_CLIENT_HEADER(MED) #include "SALOME_GenericObj_i.hh" +#include "SMESH_Mesh_i.hxx" class SMESH_Gen_i; class SMESH_Mesh_i; @@ -91,8 +92,11 @@ public: SMESH_Mesh_i* _mesh_i; //NRI protected: + void changeLocalId(int localId) { _localId = localId; } SMESH_Gen_i* _gen_i; int _localId; + + friend void SMESH_Mesh_i::CheckGeomGroupModif(); }; #endif diff --git a/src/SMESH_SWIG/Makefile.am b/src/SMESH_SWIG/Makefile.am index 9092d0811..09ab5553d 100644 --- a/src/SMESH_SWIG/Makefile.am +++ b/src/SMESH_SWIG/Makefile.am @@ -27,87 +27,9 @@ include $(top_srcdir)/adm_local/unix/make_common_starter.am -# =============================================================== -# Swig targets -# =============================================================== -# (cf. http://www.geocities.com/foetsch/python/swig_linux.htm) -# -# Step 1: build the wrapping source files with swig -# -# libSALOME_LifeCycleCORBA.i -- swig --> swig_wrap.cpp -# libSALOME_Swig.py -# -# Step 2: build the dynamic library from cpp built source files and -# dependant libraries. -# -# swig_wrap.cpp -- gcc --> swig_wrap.o |-- link --> _libSALOME_Swig.la -# + | -# dependant libs | -# -# The file libSALOME_Swigcmodule.py will be installed in -# /lib/python/site-package/salome. -# The library will be installed in the same place. -# - -# this option puts it to dist -#BUILT_SOURCES = swig_wrap.cpp - -SWIG_FLAGS = \ - @SWIG_FLAGS@ \ - -I$(srcdir) \ - -I$(srcdir)/../SMESHGUI - -SWIG_SOURCES = libSMESH_Swig.i - -# Libraries targets - -lib_LTLIBRARIES = libSMESH_Swigcmodule.la - -nodist_pkgpython_DATA = libSMESH_Swig.py -libSMESH_Swig.py: swig_wrap.cpp - -libSMESH_Swigcmodule_la_SOURCES = \ - $(BUILT_SOURCES) \ - $(SWIG_SOURCES) \ - ../SMESHGUI/SMESHGUI_Swig.cxx - -nodist_libSMESH_Swigcmodule_la_SOURCES = \ - swig_wrap.cpp - -libSMESH_Swigcmodule_la_CPPFLAGS = \ - $(QT_INCLUDES) \ - $(PYTHON_INCLUDES) \ - $(CAS_CPPFLAGS) \ - $(VTK_INCLUDES) \ - $(OGL_INCLUDES) \ - $(KERNEL_CXXFLAGS) \ - $(GUI_CXXFLAGS) \ - $(MED_CXXFLAGS) \ - $(GEOM_CXXFLAGS) \ - $(CORBA_CXXFLAGS) \ - $(CORBA_INCLUDES) \ - $(BOOST_CPPFLAGS) \ - -I$(srcdir)/../SMESHGUI \ - -I$(top_builddir)/idl \ - -I$(top_builddir)/salome_adm/unix - -libSMESH_Swigcmodule_la_LDFLAGS = \ - ../SMESHGUI/libSMESH.la \ - $(KERNEL_LDFLAGS) -lSalomeGenericObj -lSALOMELocalTrace \ - $(GUI_LDFLAGS) -lCAM -lsuit -lqtx -lSalomeApp -lstd -lEvent \ - $(PYTHON_LIBS) \ - $(QT_MT_LIBS) - - -swig_wrap.cpp : $(SWIG_SOURCES) - $(SWIG) $(SWIG_FLAGS) -o $@ $< - -CLEANFILES = \ - swig_wrap.cpp # Scripts to be installed. dist_salomescript_DATA= \ - libSMESH_Swig.py \ smesh.py \ smeshDC.py \ batchmode_smesh.py \ @@ -173,8 +95,3 @@ dist_salomescript_DATA= \ EXPORT_SHAREDPYSCRIPTS = \ SMESH_shared_modules.py - -install-exec-hook: $(libdir)/_libSMESH_Swig.so - -$(libdir)/_libSMESH_Swig.so: - ( cd $(libdir); ln -sf libSMESH_Swigcmodule.so _libSMESH_Swig.so; ) diff --git a/src/SMESH_SWIG/smeshDC.py b/src/SMESH_SWIG/smeshDC.py index 5b6ee694b..d9881a6a7 100644 --- a/src/SMESH_SWIG/smeshDC.py +++ b/src/SMESH_SWIG/smeshDC.py @@ -29,7 +29,7 @@ import salome import geompyDC -import SMESH +import SMESH # necessary for back compatibility from SMESH import * import StdMeshers @@ -49,10 +49,14 @@ REGULAR = 1 PYTHON = 2 COMPOSITE = 3 -MEFISTO = 3 -NETGEN = 4 -GHS3D = 5 -FULL_NETGEN = 6 +MEFISTO = 3 +NETGEN = 4 +GHS3D = 5 +FULL_NETGEN = 6 +NETGEN_2D = 7 +NETGEN_1D2D = NETGEN +NETGEN_1D2D3D = FULL_NETGEN +NETGEN_FULL = FULL_NETGEN # MirrorType enumeration POINT = SMESH_MeshEditor.POINT @@ -413,6 +417,13 @@ class Mesh_Algorithm: self.geom = 0 self.subm = 0 self.algo = 0 + hypos = {} + + def FindHypothesis(self,hypname, args): + key = "%s %s %s" % (self.__class__.__name__, hypname, args) + if Mesh_Algorithm.hypos.has_key( key ): + return Mesh_Algorithm.hypos[ key ] + return None ## If the algorithm is global, return 0; \n # else return the submesh associated to this algorithm. @@ -444,41 +455,57 @@ class Mesh_Algorithm: ## Private method. def Create(self, mesh, geom, hypo, so="libStdMeshersEngine.so"): + if geom is None: + raise RuntimeError, "Attemp to create " + hypo + " algoritm on None shape" + algo = smesh.CreateHypothesis(hypo, so) + self.Assign(algo, mesh, geom) + return self.algo + + ## Private method + def Assign(self, algo, mesh, geom): if geom is None: raise RuntimeError, "Attemp to create " + hypo + " algoritm on None shape" self.mesh = mesh piece = mesh.geom - if geom==0: + if not geom: self.geom = piece - name = GetName(piece) else: self.geom = geom name = GetName(geom) if name==NO_NAME: name = mesh.geompyD.SubShapeName(geom, piece) mesh.geompyD.addToStudyInFather(piece, geom, name) - self.subm = mesh.mesh.GetSubMesh(geom, hypo) + self.subm = mesh.mesh.GetSubMesh(geom, algo.GetName()) - self.algo = mesh.smeshpyD.CreateHypothesis(hypo, so) - SetName(self.algo, name + "/" + hypo) + self.algo = algo status = mesh.mesh.AddHypothesis(self.geom, self.algo) - TreatHypoStatus( status, hypo, name, 1 ) - + TreatHypoStatus( status, algo.GetName(), GetName(algo), True ) + ## Private method - def Hypothesis(self, hyp, args=[], so="libStdMeshersEngine.so"): - hypo = self.mesh.smeshpyD.CreateHypothesis(hyp, so) - a = "" - s = "=" - i = 0 - n = len(args) - while i-th node of each volume, the (0,0,1) # key-point will be mapped into -th node of each volume. # The (0,0,0) key-point of used pattern corresponds to not split corner. - # @param @return TRUE in case of success, FALSE otherwise. + # @return TRUE in case of success, FALSE otherwise. def SplitHexaToTetras (self, theObject, theNode000, theNode001): # Pattern: 5.---------.6 # /|#* /| @@ -2142,7 +2384,7 @@ class Mesh: # will be mapped into -th node of each volume, the (0,0,1) # key-point will be mapped into -th node of each volume. # The edge (0,0,0)-(0,0,1) of used pattern connects two not split corners. - # @param @return TRUE in case of success, FALSE otherwise. + # @return TRUE in case of success, FALSE otherwise. def SplitHexaToPrisms (self, theObject, theNode000, theNode001): # Pattern: 5.---------.6 # /|# /| @@ -2219,7 +2461,7 @@ class Mesh: # @param MaxNbOfIterations maximum number of iterations # @param MaxAspectRatio varies in range [1.0, inf] # @param Method is Laplacian(LAPLACIAN_SMOOTH) or Centroidal(CENTROIDAL_SMOOTH) - def SmoothParametric(self,IDsOfElements, IDsOfFixedNodes, + def SmoothParametric(self, IDsOfElements, IDsOfFixedNodes, MaxNbOfIterations, MaxAspectRatio, Method): if IDsOfElements == []: IDsOfElements = self.GetElementsId() diff --git a/src/SMESH_SWIG_WITHIHM/Makefile.am b/src/SMESH_SWIG_WITHIHM/Makefile.am new file mode 100644 index 000000000..7988a23ea --- /dev/null +++ b/src/SMESH_SWIG_WITHIHM/Makefile.am @@ -0,0 +1,115 @@ +# Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +# CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +# +# +# +# File : Makefile.in +# Author : Nicolas REJNERI, Paul RASCLE +# Modified by : Alexander BORODIN (OCN) - autotools usage +# Module : SMESH +# $Header$ + +include $(top_srcdir)/adm_local/unix/make_common_starter.am + +# =============================================================== +# Swig targets +# =============================================================== +# (cf. http://www.geocities.com/foetsch/python/swig_linux.htm) +# +# Step 1: build the wrapping source files with swig +# +# libSALOME_LifeCycleCORBA.i -- swig --> swig_wrap.cpp +# libSALOME_Swig.py +# +# Step 2: build the dynamic library from cpp built source files and +# dependant libraries. +# +# swig_wrap.cpp -- gcc --> swig_wrap.o |-- link --> _libSALOME_Swig.la +# + | +# dependant libs | +# +# The file libSALOME_Swigcmodule.py will be installed in +# /lib/python/site-package/salome. +# The library will be installed in the same place. +# + +# this option puts it to dist +#BUILT_SOURCES = swig_wrap.cpp + +SWIG_FLAGS = \ + @SWIG_FLAGS@ \ + -I$(srcdir) \ + -I$(srcdir)/../SMESHGUI + +SWIG_SOURCES = libSMESH_Swig.i + +# Libraries targets + +lib_LTLIBRARIES = libSMESH_Swigcmodule.la + +nodist_pkgpython_DATA = libSMESH_Swig.py +libSMESH_Swig.py: swig_wrap.cpp + +libSMESH_Swigcmodule_la_SOURCES = \ + $(BUILT_SOURCES) \ + $(SWIG_SOURCES) \ + ../SMESHGUI/SMESHGUI_Swig.cxx + +nodist_libSMESH_Swigcmodule_la_SOURCES = \ + swig_wrap.cpp + +libSMESH_Swigcmodule_la_CPPFLAGS = \ + $(QT_INCLUDES) \ + $(PYTHON_INCLUDES) \ + $(CAS_CPPFLAGS) \ + $(VTK_INCLUDES) \ + $(OGL_INCLUDES) \ + $(KERNEL_CXXFLAGS) \ + $(GUI_CXXFLAGS) \ + $(MED_CXXFLAGS) \ + $(GEOM_CXXFLAGS) \ + $(CORBA_CXXFLAGS) \ + $(CORBA_INCLUDES) \ + $(BOOST_CPPFLAGS) \ + -I$(srcdir)/../SMESHGUI \ + -I$(top_builddir)/idl \ + -I$(top_builddir)/salome_adm/unix + +libSMESH_Swigcmodule_la_LDFLAGS = \ + ../SMESHGUI/libSMESH.la \ + $(KERNEL_LDFLAGS) -lSalomeGenericObj -lSALOMELocalTrace \ + $(GUI_LDFLAGS) -lCAM -lsuit -lqtx -lSalomeApp -lstd -lEvent \ + $(PYTHON_LIBS) \ + $(QT_MT_LIBS) + + +swig_wrap.cpp : $(SWIG_SOURCES) + $(SWIG) $(SWIG_FLAGS) -o $@ $< + +CLEANFILES = \ + swig_wrap.cpp + +# Scripts to be installed. +dist_salomescript_DATA= \ + libSMESH_Swig.py + +install-exec-hook: $(libdir)/_libSMESH_Swig.so + +$(libdir)/_libSMESH_Swig.so: + ( cd $(libdir); ln -sf libSMESH_Swigcmodule.so _libSMESH_Swig.so; ) diff --git a/src/SMESH_SWIG/libSMESH_Swig.i b/src/SMESH_SWIG_WITHIHM/libSMESH_Swig.i similarity index 100% rename from src/SMESH_SWIG/libSMESH_Swig.i rename to src/SMESH_SWIG_WITHIHM/libSMESH_Swig.i diff --git a/src/StdMeshers/StdMeshers_CompositeSegment_1D.cxx b/src/StdMeshers/StdMeshers_CompositeSegment_1D.cxx index 1820f6fe3..c60cbee61 100644 --- a/src/StdMeshers/StdMeshers_CompositeSegment_1D.cxx +++ b/src/StdMeshers/StdMeshers_CompositeSegment_1D.cxx @@ -91,8 +91,7 @@ namespace { eNext = TopoDS::Edge( ancestor ); } if ( edgeCounter.Extent() < 3 && !eNext.IsNull() ) { - GeomAbs_Shape cont = SMESH_Algo::Continuity( edge, eNext ); - if (cont >= GeomAbs_G1) { + if ( SMESH_Algo::IsContinuous( edge, eNext )) { // care of orientation bool reverse; if ( forward ) diff --git a/src/StdMeshers/StdMeshers_FaceSide.cxx b/src/StdMeshers/StdMeshers_FaceSide.cxx index 85057fb5c..3063577c0 100644 --- a/src/StdMeshers/StdMeshers_FaceSide.cxx +++ b/src/StdMeshers/StdMeshers_FaceSide.cxx @@ -35,6 +35,8 @@ #include "SMESH_Algo.hxx" #include "SMESH_Mesh.hxx" #include "SMESH_MeshEditor.hxx" +#include "SMESH_ComputeError.hxx" +#include "SMESH_Block.hxx" #include #include @@ -464,3 +466,50 @@ gp_Pnt2d StdMeshers_FaceSide::Value2d(double U) const } return gp_Pnt2d( 1e+100, 1e+100 ); } + +//================================================================================ +/*! + * \brief Return wires of a face as StdMeshers_FaceSide's + */ +//================================================================================ + +TSideVector StdMeshers_FaceSide::GetFaceWires(const TopoDS_Face& theFace, + SMESH_Mesh & theMesh, + const bool theIgnoreMediumNodes, + TError & theError) +{ + TopoDS_Vertex V1; + list< TopoDS_Edge > edges; + list< int > nbEdgesInWires; + int nbWires = SMESH_Block::GetOrderedEdges (theFace, V1, edges, nbEdgesInWires); + + // split list of all edges into separate wires + TSideVector wires( nbWires ); + list< int >::iterator nbE = nbEdgesInWires.begin(); + list< TopoDS_Edge >::iterator from, to; + from = to = edges.begin(); + for ( int iW = 0; iW < nbWires; ++iW ) + { + std::advance( to, *nbE++ ); + list< TopoDS_Edge > wireEdges( from, to ); + // assure that there is a node on the first vertex + // as StdMeshers_FaceSide::GetUVPtStruct() requires + while ( !SMESH_Algo::VertexNode( TopExp::FirstVertex( wireEdges.front(), true), + theMesh.GetMeshDS())) + { + wireEdges.splice(wireEdges.end(), wireEdges, + wireEdges.begin(), ++wireEdges.begin()); + if ( from->IsSame( wireEdges.front() )) { + theError = TError + ( new SMESH_ComputeError(COMPERR_BAD_INPUT_MESH,"No nodes on vertices")); + return TSideVector(0); + } + } + StdMeshers_FaceSide* wire = new StdMeshers_FaceSide( theFace, wireEdges, &theMesh, + true, theIgnoreMediumNodes); + wires[ iW ] = StdMeshers_FaceSidePtr( wire ); + from = to; + } + return wires; +} + diff --git a/src/StdMeshers/StdMeshers_FaceSide.hxx b/src/StdMeshers/StdMeshers_FaceSide.hxx index 1463d2d1f..43c92bf2b 100644 --- a/src/StdMeshers/StdMeshers_FaceSide.hxx +++ b/src/StdMeshers/StdMeshers_FaceSide.hxx @@ -45,6 +45,7 @@ class Adaptor2d_Curve2d; class Adaptor3d_Curve; class BRepAdaptor_CompCurve; class TopoDS_Face; +class SMESH_ComputeError; typedef struct uvPtStruct { @@ -61,6 +62,8 @@ typedef struct uvPtStruct class StdMeshers_FaceSide; typedef boost::shared_ptr< StdMeshers_FaceSide > StdMeshers_FaceSidePtr; typedef boost::shared_ptr< uvPtStruct > UVPtStructPtr; +typedef std::vector< StdMeshers_FaceSidePtr > TSideVector; +typedef boost::shared_ptr< SMESH_ComputeError > TError; //================================================================================ /*! @@ -88,6 +91,15 @@ public: SMESH_Mesh* theMesh, const bool theIsForward, const bool theIgnoreMediumNodes); + + /*! + * \brief Return wires of a face as StdMeshers_FaceSide's + */ + static TSideVector GetFaceWires(const TopoDS_Face& theFace, + SMESH_Mesh & theMesh, + const bool theIgnoreMediumNodes, + TError & theError); + /*! * \brief Change orientation of side geometry */ @@ -115,15 +127,15 @@ public: * * Missing nodes are allowed only on internal vertices */ - const vector& GetUVPtStruct(bool isXConst, double constValue) const; + const vector& GetUVPtStruct(bool isXConst =0, double constValue =0) const; /*! * \brief Simulates detailed data on nodes * \param isXConst - true if normalized parameter X is constant * \param constValue - constant parameter value */ const vector& SimulateUVPtStruct(int nbSeg, - bool isXConst, - double constValue) const; + bool isXConst = 0, + double constValue = 0) const; /*! * \brief Return edge and parameter on edge by normalized parameter */ diff --git a/src/StdMeshers/StdMeshers_Hexa_3D.cxx b/src/StdMeshers/StdMeshers_Hexa_3D.cxx index 80cd6caeb..d1567ae08 100644 --- a/src/StdMeshers/StdMeshers_Hexa_3D.cxx +++ b/src/StdMeshers/StdMeshers_Hexa_3D.cxx @@ -118,12 +118,15 @@ bool StdMeshers_Hexa_3D::CheckHypothesis SMESH_Hypothesis::Hypothesis_Status& aStatus) { // check nb of faces in the shape +/* PAL16229 aStatus = SMESH_Hypothesis::HYP_BAD_GEOMETRY; int nbFaces = 0; for (TopExp_Explorer exp(aShape, TopAbs_FACE); exp.More(); exp.Next()) if ( ++nbFaces > 6 ) - return false; - + break; + if ( nbFaces != 6 ) + return false; +*/ aStatus = SMESH_Hypothesis::HYP_OK; return true; } @@ -174,9 +177,10 @@ static bool findIJ (const SMDS_MeshNode* node, const FaceQuadStruct * quad, int& //============================================================================= bool StdMeshers_Hexa_3D::Compute(SMESH_Mesh & aMesh, - const TopoDS_Shape & aShape) throw(SALOME_Exception) + const TopoDS_Shape & aShape)// throw(SALOME_Exception) { - Unexpect aCatch(SalomeException); + // PAL14921. Enable catching std::bad_alloc and Standard_OutOfMemory outside + //Unexpect aCatch(SalomeException); MESSAGE("StdMeshers_Hexa_3D::Compute"); SMESHDS_Mesh * meshDS = aMesh.GetMeshDS(); @@ -190,7 +194,7 @@ bool StdMeshers_Hexa_3D::Compute(SMESH_Mesh & aMesh, meshFaces.push_back(aSubMesh); } if (meshFaces.size() != 6) - return error(COMPERR_BAD_SHAPE, TComm(meshFaces.size())<<" instead of 6 faces in block"); + return error(COMPERR_BAD_SHAPE, TComm(meshFaces.size())<<" instead of 6 faces in a block"); // 0.2 - is each face meshed with Quadrangle_2D? (so, with a wire of 4 edges) @@ -251,6 +255,9 @@ bool StdMeshers_Hexa_3D::Compute(SMESH_Mesh & aMesh, ASSERT(quadAlgo); try { aQuads[i] = quadAlgo->CheckAnd2Dcompute(aMesh, aFace, _quadraticMesh); + if(!aQuads[i]) { + return error( quadAlgo->GetComputeError()); + } } catch(SALOME_Exception & S_ex) { return ClearAndReturn( aQuads, error(COMPERR_SLM_EXCEPTION,TComm(S_ex.what()) << diff --git a/src/StdMeshers/StdMeshers_Hexa_3D.hxx b/src/StdMeshers/StdMeshers_Hexa_3D.hxx index 09aa81303..1f1c4042d 100644 --- a/src/StdMeshers/StdMeshers_Hexa_3D.hxx +++ b/src/StdMeshers/StdMeshers_Hexa_3D.hxx @@ -76,7 +76,7 @@ public: virtual bool Compute(SMESH_Mesh& aMesh, const TopoDS_Shape& aShape) - throw (SALOME_Exception); + /*throw (SALOME_Exception)*/; static TopoDS_Vertex OppositeVertex(const TopoDS_Vertex& aVertex, const TopTools_IndexedMapOfShape& aQuads0Vertices, diff --git a/src/StdMeshers/StdMeshers_MEFISTO_2D.cxx b/src/StdMeshers/StdMeshers_MEFISTO_2D.cxx index cb4e61fc1..ebf208060 100644 --- a/src/StdMeshers/StdMeshers_MEFISTO_2D.cxx +++ b/src/StdMeshers/StdMeshers_MEFISTO_2D.cxx @@ -187,42 +187,29 @@ bool StdMeshers_MEFISTO_2D::Compute(SMESH_Mesh & aMesh, const TopoDS_Shape & aSh const bool ignoreMediumNodes = _quadraticMesh; // get all edges of a face - TopoDS_Vertex V1; - list< TopoDS_Edge > edges; - list< int > nbEdgesInWires; - int nbWires = SMESH_Block::GetOrderedEdges (F, V1, edges, nbEdgesInWires); - - if (_hypLengthFromEdges) _edgeLength = 0; - - // split list of all edges into separate wires - TWireVector wires ( nbWires ); - list< int >::iterator nbE = nbEdgesInWires.begin(); - list< TopoDS_Edge >::iterator from, to; - from = to = edges.begin(); - for ( int iW = 0; iW < nbWires; ++iW ) + TError problem; + TWireVector wires = StdMeshers_FaceSide::GetFaceWires( F, aMesh, ignoreMediumNodes, problem ); + int nbWires = wires.size(); + if ( problem && !problem->IsOK() ) return error( problem ); + if ( nbWires == 0 ) return error( "Problem in StdMeshers_FaceSide::GetFaceWires()"); + if ( wires[0]->NbSegments() < 3 ) // ex: a circle with 2 segments + return error(COMPERR_BAD_INPUT_MESH, + SMESH_Comment("Too few segments: ")<NbSegments()); + + // compute average edge length + if (_hypLengthFromEdges) { - std::advance( to, *nbE++ ); - list< TopoDS_Edge > wireEdges( from, to ); - // assure that there is a node on the first vertex - // as StdMeshers_FaceSide::GetUVPtStruct() requires - while ( !VertexNode( TopExp::FirstVertex( wireEdges.front(), true), - aMesh.GetMeshDS())) + _edgeLength = 0; + int nbSegments = 0; + for ( int iW = 0; iW < nbWires; ++iW ) { - wireEdges.splice(wireEdges.end(), wireEdges, - wireEdges.begin(), ++wireEdges.begin()); - if ( from->IsSame( wireEdges.front() )) - return error(COMPERR_BAD_INPUT_MESH,"No nodes on vertices"); + StdMeshers_FaceSidePtr wire = wires[ iW ]; + _edgeLength += wire->Length(); + nbSegments += wire->NbSegments(); } - StdMeshers_FaceSide* wire = new StdMeshers_FaceSide( F, wireEdges, &aMesh, - true, ignoreMediumNodes); - wires[ iW ] = StdMeshers_FaceSidePtr( wire ); - if (_hypLengthFromEdges && wire->NbSegments() ) - _edgeLength += wire->Length() / wire->NbSegments(); - from = to; + if ( nbSegments ) + _edgeLength /= nbSegments; } - if ( wires[0]->NbSegments() < 3 ) // ex: a circle with 2 segments - return error(COMPERR_BAD_INPUT_MESH, - SMESH_Comment("Too few segments")<NbSegments()); if (_hypLengthFromEdges && _edgeLength < DBL_MIN ) _edgeLength = 100; @@ -502,22 +489,19 @@ bool StdMeshers_MEFISTO_2D::LoadPoints(TWireVector & wires, VWMap.Clear(); // wires have no common vertices } - const bool isXConst = false; // meaningles here - const double constValue = 0; // meaningles here - int m = 0; list< int > mOnVertex; for ( int iW = 0; iW < wires.size(); ++iW ) { - const vector& uvPtVec = wires[ iW ]->GetUVPtStruct(isXConst,constValue); + const vector& uvPtVec = wires[ iW ]->GetUVPtStruct(); if ( uvPtVec.size() != wires[ iW ]->NbPoints() ) { return error(COMPERR_BAD_INPUT_MESH,SMESH_Comment("Unexpected nb of points on wire ") << iW << uvPtVec.size()<<" != "<NbPoints()); } if ( m + uvPtVec.size()-1 > mefistoToDS.size() ) { MESSAGE("Wrong mefistoToDS.size: "<::const_iterator uvPt = uvPtVec.begin(); diff --git a/src/StdMeshers/StdMeshers_Prism_3D.cxx b/src/StdMeshers/StdMeshers_Prism_3D.cxx index 8d87d043f..6d28721e3 100644 --- a/src/StdMeshers/StdMeshers_Prism_3D.cxx +++ b/src/StdMeshers/StdMeshers_Prism_3D.cxx @@ -101,7 +101,7 @@ namespace { const SMDS_MeshNode* & node1, const SMDS_MeshNode* & node2) { - if ( param == 1.0 || column->size() == 1) { + if ( param >= 1.0 || column->size() == 1) { node1 = node2 = column->back(); return 0; } @@ -185,7 +185,7 @@ bool StdMeshers_Prism_3D::CheckHypothesis(SMESH_Mesh& a SMESH_Hypothesis::Hypothesis_Status& aStatus) { // Check shape geometry - +/* PAL16229 aStatus = SMESH_Hypothesis::HYP_BAD_GEOMETRY; // find not quadrangle faces @@ -216,7 +216,7 @@ bool StdMeshers_Prism_3D::CheckHypothesis(SMESH_Mesh& a if ( nbFace != nbEdge + 2 ) RETURN_BAD_RESULT("Bad nb of faces: " << nbFace << " but must be " << nbEdge + 2); } - +*/ // no hypothesis aStatus = SMESH_Hypothesis::HYP_OK; return true; @@ -275,17 +275,20 @@ bool StdMeshers_Prism_3D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& theSh TNodeColumn& column = bot_column->second; // bottom node parameters and coords - gp_XYZ botParams = tBotNode.GetParams(); myShapeXYZ[ ID_BOT_FACE ] = tBotNode.GetCoords(); + gp_XYZ botParams = tBotNode.GetParams(); // compute top node parameters - gp_XYZ topParams; myShapeXYZ[ ID_TOP_FACE ] = gpXYZ( column.back() ); - gp_Pnt topCoords = myShapeXYZ[ ID_TOP_FACE ]; - if ( !myBlock.ComputeParameters( topCoords, topParams, ID_TOP_FACE )) - return error(dfltErr(),TCom("Can't compute normalized parameters ") - << "for node " << column.back()->GetID() - << " on the face #"<< column.back()->GetPosition()->GetShapeId() ); + gp_XYZ topParams = botParams; + topParams.SetZ( 1 ); + if ( column.size() > 2 ) { + gp_Pnt topCoords = myShapeXYZ[ ID_TOP_FACE ]; + if ( !myBlock.ComputeParameters( topCoords, topParams, ID_TOP_FACE, topParams )) + return error(TCom("Can't compute normalized parameters ") + << "for node " << column.back()->GetID() + << " on the face #"<< column.back()->GetPosition()->GetShapeId() ); + } // vertical loop TNodeColumn::iterator columnNodes = column.begin(); @@ -311,7 +314,11 @@ bool StdMeshers_Prism_3D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& theSh // compute coords for a new node gp_XYZ coords; if ( !SMESH_Block::ShellPoint( params, myShapeXYZ, coords )) - return error(dfltErr(),"Can't compute coordinates by normalized parameters"); + return error("Can't compute coordinates by normalized parameters"); + + SHOWYXZ("TOPFacePoint ",myShapeXYZ[ ID_TOP_FACE]); + SHOWYXZ("BOT Node "<< tBotNode.myNode->GetID(),gpXYZ(tBotNode.myNode)); + SHOWYXZ("ShellPoint ",coords); // create a node node = meshDS->AddNode( coords.X(), coords.Y(), coords.Z() ); @@ -344,13 +351,13 @@ bool StdMeshers_Prism_3D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& theSh if ( n->GetPosition()->GetTypeOfPosition() == SMDS_TOP_FACE ) { bot_column = myBotToColumnMap.find( n ); if ( bot_column == myBotToColumnMap.end() ) - return error(dfltErr(),TCom("No nodes found above node ") << n->GetID() ); + return error(TCom("No nodes found above node ") << n->GetID() ); columns[ i ] = & bot_column->second; } else { columns[ i ] = myBlock.GetNodeColumn( n ); if ( !columns[ i ] ) - return error(dfltErr(),TCom("No side nodes found above node ") << n->GetID() ); + return error(TCom("No side nodes found above node ") << n->GetID() ); } } // create prisms @@ -376,12 +383,44 @@ void StdMeshers_Prism_3D::AddPrisms( vector & columns, int shapeID = helper->GetSubShapeID(); int nbNodes = columns.size(); + int nbZ = columns[0]->size(); + if ( nbZ < 2 ) return; + + // find out orientation + bool isForward = true; + SMDS_VolumeTool vTool; + int z = 1; + switch ( nbNodes ) { + case 3: { + const SMDS_MeshNode* botNodes[3] = { (*columns[0])[z-1], + (*columns[1])[z-1], + (*columns[2])[z-1] }; + const SMDS_MeshNode* topNodes[3] = { (*columns[0])[z], + (*columns[1])[z], + (*columns[2])[z] }; + SMDS_VolumeOfNodes tmpVol ( botNodes[0], botNodes[1], botNodes[2], + topNodes[0], topNodes[1], topNodes[2]); + vTool.Set( &tmpVol ); + isForward = vTool.IsForward(); + break; + } + case 4: { + const SMDS_MeshNode* botNodes[4] = { (*columns[0])[z-1], (*columns[1])[z-1], + (*columns[2])[z-1], (*columns[3])[z-1] }; + const SMDS_MeshNode* topNodes[4] = { (*columns[0])[z], (*columns[1])[z], + (*columns[2])[z], (*columns[3])[z] }; + SMDS_VolumeOfNodes tmpVol ( botNodes[0], botNodes[1], botNodes[2], botNodes[3], + topNodes[0], topNodes[1], topNodes[2], topNodes[3]); + vTool.Set( &tmpVol ); + isForward = vTool.IsForward(); + break; + } + } // vertical loop on columns - for ( int z = 1; z < columns[0]->size(); ++z) + for ( z = 1; z < nbZ; ++z ) { SMDS_MeshElement* vol = 0; - SMDS_VolumeTool vTool; switch ( nbNodes ) { case 3: { @@ -391,11 +430,7 @@ void StdMeshers_Prism_3D::AddPrisms( vector & columns, const SMDS_MeshNode* topNodes[3] = { (*columns[0])[z], (*columns[1])[z], (*columns[2])[z] }; - // assure good orientation - SMDS_VolumeOfNodes tmpVol ( botNodes[0], botNodes[1], botNodes[2], - topNodes[0], topNodes[1], topNodes[2]); - vTool.Set( &tmpVol ); - if ( vTool.IsForward() ) + if ( isForward ) vol = helper->AddVolume( botNodes[0], botNodes[1], botNodes[2], topNodes[0], topNodes[1], topNodes[2]); else @@ -408,11 +443,7 @@ void StdMeshers_Prism_3D::AddPrisms( vector & columns, (*columns[2])[z-1], (*columns[3])[z-1] }; const SMDS_MeshNode* topNodes[4] = { (*columns[0])[z], (*columns[1])[z], (*columns[2])[z], (*columns[3])[z] }; - // assure good orientation - SMDS_VolumeOfNodes tmpVol ( botNodes[0], botNodes[1], botNodes[2], botNodes[3], - topNodes[0], topNodes[1], topNodes[2], topNodes[3]); - vTool.Set( &tmpVol ); - if ( vTool.IsForward() ) + if ( isForward ) vol = helper->AddVolume( botNodes[0], botNodes[1], botNodes[2], botNodes[3], topNodes[0], topNodes[1], topNodes[2], topNodes[3]); else @@ -462,7 +493,7 @@ bool StdMeshers_Prism_3D::assocOrProjBottom2Top() SMESHDS_SubMesh * topSMDS = topSM->GetSubMeshDS(); if ( !botSMDS || botSMDS->NbElements() == 0 ) - return error(dfltErr(),TCom("No elememts on face #") << botSM->GetId()); + return error(TCom("No elememts on face #") << botSM->GetId()); bool needProject = false; if ( !topSMDS || @@ -470,13 +501,13 @@ bool StdMeshers_Prism_3D::assocOrProjBottom2Top() botSMDS->NbNodes() != topSMDS->NbNodes()) { if ( myBlock.HasNotQuadElemOnTop() ) - return error(dfltErr(),TCom("Mesh on faces #") << botSM->GetId() + return error(TCom("Mesh on faces #") << botSM->GetId() <<" and #"<< topSM->GetId() << " seems different" ); needProject = true; } if ( 0/*needProject && !myProjectTriangles*/ ) - return error(dfltErr(),TCom("Mesh on faces #") << botSM->GetId() + return error(TCom("Mesh on faces #") << botSM->GetId() <<" and #"<< topSM->GetId() << " seems different" ); ///RETURN_BAD_RESULT("Need to project but not allowed"); @@ -492,7 +523,7 @@ bool StdMeshers_Prism_3D::assocOrProjBottom2Top() if ( !TAssocTool::FindSubShapeAssociation( botFace, myBlock.Mesh(), topFace, myBlock.Mesh(), shape2ShapeMap) ) - return error(dfltErr(),TCom("Topology of faces #") << botSM->GetId() + return error(TCom("Topology of faces #") << botSM->GetId() <<" and #"<< topSM->GetId() << " seems different" ); // Find matching nodes of top and bottom faces @@ -500,12 +531,13 @@ bool StdMeshers_Prism_3D::assocOrProjBottom2Top() if ( ! TAssocTool::FindMatchingNodesOnFaces( botFace, myBlock.Mesh(), topFace, myBlock.Mesh(), shape2ShapeMap, n2nMap )) - return error(dfltErr(),TCom("Mesh on faces #") << botSM->GetId() + return error(TCom("Mesh on faces #") << botSM->GetId() <<" and #"<< topSM->GetId() << " seems different" ); // Fill myBotToColumnMap int zSize = myBlock.VerticalSize(); + TNode prevTNode; TNodeNodeMap::iterator bN_tN = n2nMap.begin(); for ( ; bN_tN != n2nMap.end(); ++bN_tN ) { @@ -515,9 +547,16 @@ bool StdMeshers_Prism_3D::assocOrProjBottom2Top() continue; // wall columns are contained in myBlock // compute bottom node params TNode bN( botNode ); - if ( !myBlock.ComputeParameters( bN.GetCoords(), bN.ChangeParams(), ID_BOT_FACE )) - return error(dfltErr(),TCom("Can't compute normalized parameters ") - << "for node " << botNode->GetID() << " on the face #"<< botSM->GetId() ); + if ( zSize > 2 ) { + gp_XYZ paramHint(-1,-1,-1); + if ( prevTNode.IsNeighbor( bN )) + paramHint = prevTNode.GetParams(); + if ( !myBlock.ComputeParameters( bN.GetCoords(), bN.ChangeParams(), + ID_BOT_FACE, paramHint )) + return error(TCom("Can't compute normalized parameters for node ") + << botNode->GetID() << " on the face #"<< botSM->GetId() ); + prevTNode = bN; + } // create node column TNode2ColumnMap::iterator bN_col = myBotToColumnMap.insert( make_pair ( bN, TNodeColumn() )).first; @@ -555,6 +594,7 @@ bool StdMeshers_Prism_3D::projectBottomToTop() // Fill myBotToColumnMap int zSize = myBlock.VerticalSize(); + TNode prevTNode; SMDS_NodeIteratorPtr nIt = botSMDS->GetNodes(); while ( nIt->more() ) { @@ -563,15 +603,20 @@ bool StdMeshers_Prism_3D::projectBottomToTop() continue; // strange // compute bottom node params TNode bN( botNode ); - if ( !myBlock.ComputeParameters( bN.GetCoords(), bN.ChangeParams(), ID_BOT_FACE )) - return error(dfltErr(),TCom("Can't compute normalized parameters ") - << "for node " << botNode->GetID() << " on the face #"<< botSM->GetId() ); + gp_XYZ paramHint(-1,-1,-1); + if ( prevTNode.IsNeighbor( bN )) + paramHint = prevTNode.GetParams(); + if ( !myBlock.ComputeParameters( bN.GetCoords(), bN.ChangeParams(), + ID_BOT_FACE, paramHint )) + return error(TCom("Can't compute normalized parameters for node ") + << botNode->GetID() << " on the face #"<< botSM->GetId() ); + prevTNode = bN; // compute top node coords gp_XYZ topXYZ; gp_XY topUV; if ( !myBlock.FacePoint( ID_TOP_FACE, bN.GetParams(), topXYZ ) || !myBlock.FaceUV ( ID_TOP_FACE, bN.GetParams(), topUV )) - return error(dfltErr(),TCom("Can't compute coordinates ") - << "by normalized parameters on the face #"<< topSM->GetId() ); + return error(TCom("Can't compute coordinates " + "by normalized parameters on the face #")<< topSM->GetId() ); SMDS_MeshNode * topNode = meshDS->AddNode( topXYZ.X(),topXYZ.Y(),topXYZ.Z() ); meshDS->SetNodeOnFace( topNode, topFaceID, topUV.X(), topUV.Y() ); // create node column @@ -604,13 +649,13 @@ bool StdMeshers_Prism_3D::projectBottomToTop() if ( n->GetPosition()->GetTypeOfPosition() == SMDS_TOP_FACE ) { TNode2ColumnMap::iterator bot_column = myBotToColumnMap.find( n ); if ( bot_column == myBotToColumnMap.end() ) - return error(dfltErr(),TCom("No nodes found above node ") << n->GetID() ); + return error(TCom("No nodes found above node ") << n->GetID() ); nodes[ i ] = bot_column->second.back(); } else { const TNodeColumn* column = myBlock.GetNodeColumn( n ); if ( !column ) - return error(dfltErr(),TCom("No side nodes found above node ") << n->GetID() ); + return error(TCom("No side nodes found above node ") << n->GetID() ); nodes[ i ] = column->back(); } } @@ -673,6 +718,23 @@ bool StdMeshers_Prism_3D::setFaceAndEdgesXYZ( const int faceID, const gp_XYZ& pa return true; } +//================================================================================ +/*! + * \brief Return true if this node and other one belong to one face + */ +//================================================================================ + +bool TNode::IsNeighbor( const TNode& other ) const +{ + if ( !other.myNode || !myNode ) return false; + + SMDS_ElemIteratorPtr fIt = other.myNode->GetInverseElementIterator(SMDSAbs_Face); + while ( fIt->more() ) + if ( fIt->next()->GetNodeIndex( myNode ) >= 0 ) + return true; + return false; +} + //================================================================================ /*! * \brief Constructor. Initialization is needed @@ -813,11 +875,11 @@ bool StdMeshers_PrismAsBlock::Init(SMESH_MesherHelper* helper, // detect bad cases if ( nbNotQuad > 0 && nbNotQuad != 2 ) return error(COMPERR_BAD_SHAPE, - TCom("More than 2 not quadrilateral faces") + TCom("More than 2 not quadrilateral faces: ") < 2 ) return error(COMPERR_BAD_INPUT_MESH, - TCom("More then 2 faces meshed with not quadrangle elements") + TCom("More than 2 faces with not quadrangle elements: ") <Surface(), pcurves, isForward ); - SHOWYXZ( endl<<"F "<< iF << " id " << fID << " FRW " << sideFace->IsForward(), ); + SHOWYXZ( endl<<"F "<< iF << " id " << fID << " FRW " << sideFace->IsForward(), sideFace->Value(0,0)); // edges 3D geometry vector< int > edgeIdVec; SMESH_Block::GetFaceEdgesIDs( fID, edgeIdVec ); diff --git a/src/StdMeshers/StdMeshers_Prism_3D.hxx b/src/StdMeshers/StdMeshers_Prism_3D.hxx index 564919937..d6fab7b38 100644 --- a/src/StdMeshers/StdMeshers_Prism_3D.hxx +++ b/src/StdMeshers/StdMeshers_Prism_3D.hxx @@ -79,10 +79,12 @@ struct TNode gp_XYZ GetCoords() const { return gp_XYZ( myNode->X(), myNode->Y(), myNode->Z() ); } gp_XYZ GetParams() const { return myParams; } gp_XYZ& ChangeParams() { return myParams; } + bool HasParams() const { return myParams.X() >= 0.0; } SMDS_TypeOfPosition GetPositionType() const { return myNode ? myNode->GetPosition()->GetTypeOfPosition() : SMDS_TOP_UNSPEC; } + bool IsNeighbor( const TNode& other ) const; - TNode(const SMDS_MeshNode* node = 0): myNode(node) {} + TNode(const SMDS_MeshNode* node = 0): myNode(node), myParams(-1,-1,-1) {} bool operator < (const TNode& other) const { return myNode < other.myNode; } }; diff --git a/src/StdMeshers/StdMeshers_ProjectionUtils.cxx b/src/StdMeshers/StdMeshers_ProjectionUtils.cxx index c276b3afa..1452599ed 100644 --- a/src/StdMeshers/StdMeshers_ProjectionUtils.cxx +++ b/src/StdMeshers/StdMeshers_ProjectionUtils.cxx @@ -146,10 +146,11 @@ namespace { * \param edges2 - matching edges of another face * \param theMesh1 - mesh 1 * \param theMesh2 - mesh 2 + * \retval bool - true if association was fixed */ //================================================================================ - void FixAssocByPropagation( const int nbEdges, + bool FixAssocByPropagation( const int nbEdges, list< TopoDS_Edge > & edges1, list< TopoDS_Edge > & edges2, SMESH_Mesh* theMesh1, @@ -159,10 +160,13 @@ namespace { { list< TopoDS_Edge >::iterator eIt2 = ++edges2.begin(); // 2nd edge of the 2nd face TopoDS_Edge edge2 = - StdMeshers_ProjectionUtils::GetPropagationEdge( theMesh1, *eIt2, edges1.front() ); - if ( !edge2.IsNull() ) // propagation found for the second edge + StdMeshers_ProjectionUtils::GetPropagationEdge( theMesh1, *eIt2, edges1.front() ).second; + if ( !edge2.IsNull() ) { // propagation found for the second edge Reverse( edges2, nbEdges ); + return true; + } } + return false; } } @@ -330,15 +334,21 @@ bool StdMeshers_ProjectionUtils::FindSubShapeAssociation(const TopoDS_Shape& the list< TopoDS_Edge > edges1, edges2; int nbE = FindFaceAssociation( face1, VV1, face2, VV2, edges1, edges2 ); if ( !nbE ) RETURN_BAD_RESULT("FindFaceAssociation() failed"); - FixAssocByPropagation( nbE, edges1, edges2, theMesh1, theMesh2 ); - InsertAssociation( face1, face2, theMap, bidirect); // assoc faces + MESSAGE("Assoc FACE " << theMesh1->GetMeshDS()->ShapeToIndex( face1 )<< + " to " << theMesh2->GetMeshDS()->ShapeToIndex( face2 )); + if ( nbE == 2 && (edge1.IsSame( edges1.front())) != (edge2.IsSame( edges2.front()))) + { + Reverse( edges2, nbE ); + } list< TopoDS_Edge >::iterator eIt1 = edges1.begin(); list< TopoDS_Edge >::iterator eIt2 = edges2.begin(); for ( ; eIt1 != edges1.end(); ++eIt1, ++eIt2 ) { if ( !boundEdges.Add( *eIt1 )) continue; // already associated InsertAssociation( *eIt1, *eIt2, theMap, bidirect); // assoc edges + MESSAGE("Assoc edge " << theMesh1->GetMeshDS()->ShapeToIndex( *eIt1 )<< + " to " << theMesh2->GetMeshDS()->ShapeToIndex( *eIt2 )); VV1[0] = TopExp::FirstVertex( *eIt1, true ); VV2[0] = TopExp::FirstVertex( *eIt2, true ); InsertAssociation( VV1[0], VV2[0], theMap, bidirect); // assoc vertices @@ -372,7 +382,7 @@ bool StdMeshers_ProjectionUtils::FindSubShapeAssociation(const TopoDS_Shape& the TopoDS_Edge edge2 = TopoDS::Edge( theShape2 ); if ( IsPropagationPossible( theMesh1, theMesh2 )) { - TopoDS_Edge prpEdge = GetPropagationEdge( theMesh1, edge2, edge1 ); + TopoDS_Edge prpEdge = GetPropagationEdge( theMesh1, edge2, edge1 ).second; if ( !prpEdge.IsNull() ) { TopoDS_Vertex VV1[2], VV2[2]; @@ -405,40 +415,46 @@ bool StdMeshers_ProjectionUtils::FindSubShapeAssociation(const TopoDS_Shape& the { TopoDS_Face face1 = TopoDS::Face(theShape1); TopoDS_Face face2 = TopoDS::Face(theShape2); + TopoDS_Edge edge1, edge2; // get outer edge of theShape1 - TopoDS_Edge edge1 = TopoDS::Edge( OuterShape( face1, TopAbs_EDGE )); + edge1 = TopoDS::Edge( OuterShape( face1, TopAbs_EDGE )); // find out if any edge of face2 is a propagation edge of outer edge1 + map propag_edges; // use map to find the closest propagation edge for ( TopExp_Explorer exp( face2, TopAbs_EDGE ); exp.More(); exp.Next() ) { - TopoDS_Edge edge2 = TopoDS::Edge( exp.Current() ); - edge2 = GetPropagationEdge( theMesh1, edge2, edge1 ); - if ( !edge2.IsNull() ) // propagation found + edge2 = TopoDS::Edge( exp.Current() ); + pair step_edge = GetPropagationEdge( theMesh1, edge2, edge1 ); + if ( !step_edge.second.IsNull() ) { // propagation found + propag_edges.insert( step_edge ); + } + } + if ( !propag_edges.empty() ) // propagation found + { + edge2 = propag_edges.begin()->second; + TopoDS_Vertex VV1[2], VV2[2]; + TopExp::Vertices( edge1, VV1[0], VV1[1], true ); + TopExp::Vertices( edge2, VV2[0], VV2[1], true ); + list< TopoDS_Edge > edges1, edges2; + int nbE = FindFaceAssociation( face1, VV1, face2, VV2, edges1, edges2 ); + if ( !nbE ) RETURN_BAD_RESULT("FindFaceAssociation() failed"); + if ( nbE == 2 ) // only 2 edges { - TopoDS_Vertex VV1[2], VV2[2]; - TopExp::Vertices( edge1, VV1[0], VV1[1], true ); - TopExp::Vertices( edge2, VV2[0], VV2[1], true ); - list< TopoDS_Edge > edges1, edges2; - int nbE = FindFaceAssociation( face1, VV1, face2, VV2, edges1, edges2 ); - if ( !nbE ) RETURN_BAD_RESULT("FindFaceAssociation() failed"); - if ( nbE == 2 ) // only 2 edges - { - // take care of proper association of propagated edges - bool same1 = edge1.IsSame( edges1.front() ); - bool same2 = edge2.IsSame( edges2.front() ); - if ( same1 != same2 ) - Reverse(edges2, nbE); - } - // store association - list< TopoDS_Edge >::iterator eIt1 = edges1.begin(); - list< TopoDS_Edge >::iterator eIt2 = edges2.begin(); - for ( ; eIt1 != edges1.end(); ++eIt1, ++eIt2 ) - { - InsertAssociation( *eIt1, *eIt2, theMap, bidirect); - VV1[0] = TopExp::FirstVertex( *eIt1, true ); - VV2[0] = TopExp::FirstVertex( *eIt2, true ); - InsertAssociation( VV1[0], VV2[0], theMap, bidirect); - } - return true; + // take care of proper association of propagated edges + bool same1 = edge1.IsSame( edges1.front() ); + bool same2 = edge2.IsSame( edges2.front() ); + if ( same1 != same2 ) + Reverse(edges2, nbE); } + // store association + list< TopoDS_Edge >::iterator eIt1 = edges1.begin(); + list< TopoDS_Edge >::iterator eIt2 = edges2.begin(); + for ( ; eIt1 != edges1.end(); ++eIt1, ++eIt2 ) + { + InsertAssociation( *eIt1, *eIt2, theMap, bidirect); + VV1[0] = TopExp::FirstVertex( *eIt1, true ); + VV2[0] = TopExp::FirstVertex( *eIt2, true ); + InsertAssociation( VV1[0], VV2[0], theMap, bidirect); + } + return true; } } break; // try by vertex closeness @@ -568,6 +584,7 @@ int StdMeshers_ProjectionUtils::FindFaceAssociation(const TopoDS_Face& face1, list< TopoDS_Edge >::iterator eBackIt; if ( !VV1[1].IsSame( TopExp::LastVertex( edges1.front(), true ))) { + reverse = true; eBackIt = --edges1.end(); // check if the second vertex belongs to the first or last edge in the wire if ( !VV1[1].IsSame( TopExp::FirstVertex( *eBackIt, true ))) { @@ -580,10 +597,10 @@ int StdMeshers_ProjectionUtils::FindFaceAssociation(const TopoDS_Face& face1, if ( KO ) RETURN_BAD_RESULT("GetOrderedEdges() failed"); } - reverse = true; } eBackIt = --edges2.end(); if ( !VV2[1].IsSame( TopExp::LastVertex( edges2.front(), true ))) { + reverse = !reverse; // check if the second vertex belongs to the first or last edge in the wire if ( !VV2[1].IsSame( TopExp::FirstVertex( *eBackIt, true ))) { bool KO = true; // belongs to none @@ -595,7 +612,6 @@ int StdMeshers_ProjectionUtils::FindFaceAssociation(const TopoDS_Face& face1, if ( KO ) RETURN_BAD_RESULT("GetOrderedEdges() failed"); } - reverse = !reverse; } if ( reverse ) { @@ -762,23 +778,25 @@ TopoDS_Face StdMeshers_ProjectionUtils::GetNextFace( SMESH_Mesh* mesh, * \param aMesh - mesh * \param theEdge - edge to find by propagation * \param fromEdge - start edge for propagation - * \retval TopoDS_Edge - found edge + * \retval pair - propagation step and found edge */ //================================================================================ -TopoDS_Edge StdMeshers_ProjectionUtils::GetPropagationEdge( SMESH_Mesh* aMesh, - const TopoDS_Edge& theEdge, - const TopoDS_Edge& fromEdge) +pair +StdMeshers_ProjectionUtils::GetPropagationEdge( SMESH_Mesh* aMesh, + const TopoDS_Edge& theEdge, + const TopoDS_Edge& fromEdge) { SMESH_IndexedMapOfShape aChain; - //aChain.Add(fromEdge); + int step = 0; // List of edges, added to chain on the previous cycle pass TopTools_ListOfShape listPrevEdges; - listPrevEdges.Append(fromEdge/*.Oriented( TopAbs_FORWARD )*/); + listPrevEdges.Append(fromEdge); // Collect all edges pass by pass while (listPrevEdges.Extent() > 0) { + step++; // List of edges, added to chain on this cycle pass TopTools_ListOfShape listCurEdges; @@ -823,7 +841,7 @@ TopoDS_Edge StdMeshers_ProjectionUtils::GetPropagationEdge( SMESH_Mesh* a ori = TopAbs::Reverse( ori ); anOppE.Orientation( ori ); if ( anOppE.IsSame( theEdge )) - return TopoDS::Edge( anOppE ); + return make_pair( step, TopoDS::Edge( anOppE )); aChain.Add(anOppE); listCurEdges.Append(anOppE); } @@ -835,7 +853,7 @@ TopoDS_Edge StdMeshers_ProjectionUtils::GetPropagationEdge( SMESH_Mesh* a listPrevEdges = listCurEdges; } // while (listPrevEdges.Extent() > 0) - return TopoDS_Edge(); + return make_pair( INT_MAX, TopoDS_Edge()); } //================================================================================ @@ -888,33 +906,50 @@ FindMatchingNodesOnFaces( const TopoDS_Face& face1, // 1. Nodes of corresponding links: - // get 2 matching edges, not seam ones - TopoDS_Edge edge1, edge2; + // get 2 matching edges, try to find not seam ones + TopoDS_Edge edge1, edge2, seam1, seam2; TopExp_Explorer eE( OuterShape( face2, TopAbs_WIRE ), TopAbs_EDGE ); do { - edge2 = TopoDS::Edge( eE.Current() ); + // edge 2 + TopoDS_Edge e2 = TopoDS::Edge( eE.Current() ); eE.Next(); - } while ( BRep_Tool::IsClosed( edge2, face2 ) && eE.More()); - if ( !assocMap.IsBound( edge2 )) - RETURN_BAD_RESULT("Association not found for edge " << meshDS2->ShapeToIndex( edge2 )); - edge1 = TopoDS::Edge( assocMap( edge2 )); - if ( !IsSubShape( edge1, face1 )) - RETURN_BAD_RESULT("Wrong association, edge " << meshDS1->ShapeToIndex( edge1 ) << - " isn't a subshape of face " << meshDS1->ShapeToIndex( face1 )); + // edge 1 + if ( !assocMap.IsBound( e2 )) + RETURN_BAD_RESULT("Association not found for edge " << meshDS2->ShapeToIndex( e2 )); + TopoDS_Edge e1 = TopoDS::Edge( assocMap( e2 )); + if ( !IsSubShape( e1, face1 )) + RETURN_BAD_RESULT("Wrong association, edge " << meshDS1->ShapeToIndex( e1 ) << + " isn't a subshape of face " << meshDS1->ShapeToIndex( face1 )); + // check that there are nodes on edges + SMESHDS_SubMesh * eSM1 = meshDS1->MeshElements( e1 ); + SMESHDS_SubMesh * eSM2 = meshDS2->MeshElements( e2 ); + if ( eSM1 && eSM2 && eSM1->NbNodes() > 0 && eSM2->NbNodes() > 0 ) + { + if ( BRep_Tool::IsClosed( e2, face2 )) { + seam1 = e1; seam2 = e2; + } + else { + edge1 = e1; edge2 = e2; + } + } + } while ( edge2.IsNull() && eE.More() ); + // + if ( edge2.IsNull() ) { + edge1 = seam1; edge2 = seam2; + } + if ( edge2.IsNull() ) RETURN_BAD_RESULT("No matching edges with nodes found"); // get 2 matching vertices - TopoDS_Shape V2 = TopExp::FirstVertex( TopoDS::Edge( edge2 )); + TopoDS_Vertex V2 = TopExp::FirstVertex( TopoDS::Edge( edge2 )); if ( !assocMap.IsBound( V2 )) RETURN_BAD_RESULT("Association not found for vertex " << meshDS2->ShapeToIndex( V2 )); - TopoDS_Shape V1 = assocMap( V2 ); + TopoDS_Vertex V1 = TopoDS::Vertex( assocMap( V2 )); // nodes on vertices - SMESHDS_SubMesh * vSM1 = meshDS1->MeshElements( V1 ); - SMESHDS_SubMesh * vSM2 = meshDS2->MeshElements( V2 ); - if ( !vSM1 || !vSM2 || vSM1->NbNodes() != 1 || vSM2->NbNodes() != 1 ) - RETURN_BAD_RESULT("Bad node submesh"); - const SMDS_MeshNode* vNode1 = vSM1->GetNodes()->next(); - const SMDS_MeshNode* vNode2 = vSM2->GetNodes()->next(); + const SMDS_MeshNode* vNode1 = SMESH_Algo::VertexNode( V1, meshDS1 ); + const SMDS_MeshNode* vNode2 = SMESH_Algo::VertexNode( V2, meshDS2 ); + if ( !vNode1 ) RETURN_BAD_RESULT("No node on vertex #" << meshDS1->ShapeToIndex( V1 )); + if ( !vNode2 ) RETURN_BAD_RESULT("No node on vertex #" << meshDS2->ShapeToIndex( V2 )); // nodes on edges linked with nodes on vertices const SMDS_MeshNode* nullNode = 0; @@ -1020,6 +1055,18 @@ FindMatchingNodesOnFaces( const TopoDS_Face& face1, if ( !onBnd ) elems.insert( f ); } + // add also faces adjacent to faceToKeep + int nbNodes = faceToKeep->NbNodes(); + if ( faceToKeep->IsQuadratic() ) nbNodes /= 2; + notInSet.insert( f1 ); + notInSet.insert( f2 ); + for ( int i = 0; i < nbNodes; ++i ) { + const SMDS_MeshNode* n1 = faceToKeep->GetNode( i ); + const SMDS_MeshNode* n2 = faceToKeep->GetNode( i+1 ); + f1 = SMESH_MeshEditor::FindFaceInSet( n1, n2, inSet, notInSet ); + if ( f1 ) + elems.insert( f1 ); + } } // case on a sphere } // loop on 2 faces @@ -1083,13 +1130,11 @@ FindMatchingNodesOnFaces( const TopoDS_Face& face1, V2 = TopExp::LastVertex( TopoDS::Edge( edge2 )); if ( !assocMap.IsBound( V2 )) RETURN_BAD_RESULT("Association not found for vertex " << meshDS2->ShapeToIndex( V2 )); - V1 = assocMap( V2 ); - vSM1 = meshDS1->MeshElements( V1 ); - vSM2 = meshDS2->MeshElements( V2 ); - if ( !vSM1 || !vSM2 || vSM1->NbNodes() != 1 || vSM2->NbNodes() != 1 ) - RETURN_BAD_RESULT("Bad node submesh"); - vNode1 = vSM1->GetNodes()->next(); - vNode2 = vSM2->GetNodes()->next(); + V1 = TopoDS::Vertex( assocMap( V2 )); + vNode1 = SMESH_Algo::VertexNode( V1, meshDS1 ); + vNode2 = SMESH_Algo::VertexNode( V2, meshDS2 ); + if ( !vNode1 ) RETURN_BAD_RESULT("No node on vertex #" << meshDS1->ShapeToIndex( V1 )); + if ( !vNode2 ) RETURN_BAD_RESULT("No node on vertex #" << meshDS2->ShapeToIndex( V2 )); node1To2Map.insert( make_pair( vNode1, vNode2 )); } diff --git a/src/StdMeshers/StdMeshers_ProjectionUtils.hxx b/src/StdMeshers/StdMeshers_ProjectionUtils.hxx index 53064e7f1..ca57f556a 100644 --- a/src/StdMeshers/StdMeshers_ProjectionUtils.hxx +++ b/src/StdMeshers/StdMeshers_ProjectionUtils.hxx @@ -139,11 +139,11 @@ class STDMESHERS_EXPORT StdMeshers_ProjectionUtils * \brief Return an oriented propagation edge * \param aMesh - mesh * \param fromEdge - start edge for propagation - * \retval TopoDS_Edge - found edge + * \retval pair - propagation step and found edge */ - static TopoDS_Edge GetPropagationEdge( SMESH_Mesh* aMesh, - const TopoDS_Edge& anEdge, - const TopoDS_Edge& fromEdge); + static std::pair GetPropagationEdge( SMESH_Mesh* aMesh, + const TopoDS_Edge& anEdge, + const TopoDS_Edge& fromEdge); /*! * \brief Find corresponding nodes on two faces diff --git a/src/StdMeshers/StdMeshers_Projection_1D.cxx b/src/StdMeshers/StdMeshers_Projection_1D.cxx index 1bfdc41c5..d3d292575 100644 --- a/src/StdMeshers/StdMeshers_Projection_1D.cxx +++ b/src/StdMeshers/StdMeshers_Projection_1D.cxx @@ -191,7 +191,7 @@ bool StdMeshers_Projection_1D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& TAssocTool::InitVertexAssociation( _sourceHypo, shape2ShapeMap ); if ( !TAssocTool::FindSubShapeAssociation( tgtEdge, tgtMesh, srcEdge, srcMesh, shape2ShapeMap) ) - return error(dfltErr(),SMESH_Comment("Vertices association failed" )); + return error(SMESH_Comment("Vertices association failed" )); // ---------------------------------------------- // Assure that mesh on a source edge is computed @@ -275,7 +275,7 @@ bool StdMeshers_Projection_1D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& // from the point at given parameter. GCPnts_AbscissaPoint Discret( curveAdaptor, dl * lengths[ i-1 ], tgtParams[ i-1 ] ); if ( !Discret.IsDone() ) - return error(dfltErr(),"GCPnts_AbscissaPoint failed"); + return error("GCPnts_AbscissaPoint failed"); tgtParams[ i ] = Discret.Parameter(); } // make internal nodes diff --git a/src/StdMeshers/StdMeshers_Projection_2D.cxx b/src/StdMeshers/StdMeshers_Projection_2D.cxx index 4aa83bdd0..687ccc4af 100644 --- a/src/StdMeshers/StdMeshers_Projection_2D.cxx +++ b/src/StdMeshers/StdMeshers_Projection_2D.cxx @@ -439,11 +439,6 @@ bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& { TopoDS_Edge srcE1 = srcEdges.front(), tgtE1 = tgtEdges.front(); reverse = ( ! srcE1.IsSame( shape2ShapeMap( tgtE1 ))); - if ( BRep_Tool::IsClosed( tgtE1, tgtFace )) { - reverse = ( srcE1.Orientation() == tgtE1.Orientation() ); - if ( _sourceHypo->GetSourceFace().Orientation() != theShape.Orientation() ) - reverse = !reverse; - } } else if ( nbEdgesInWires.front() == 1 ) { @@ -463,18 +458,18 @@ bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& mapper.Apply( tgtFace, tgtV1, reverse ); if ( mapper.GetErrorCode() != SMESH_Pattern::ERR_OK ) - return error(dfltErr(),"Can't apply source mesh pattern to the face"); + return error("Can't apply source mesh pattern to the face"); // Create the mesh const bool toCreatePolygons = false, toCreatePolyedrs = false; mapper.MakeMesh( tgtMesh, toCreatePolygons, toCreatePolyedrs ); if ( mapper.GetErrorCode() != SMESH_Pattern::ERR_OK ) - return error(dfltErr(),"Can't make mesh by source mesh pattern"); + return error("Can't make mesh by source mesh pattern"); // it will remove mesh built by pattern mapper on edges and vertices // in failure case - MeshCleaner cleaner( tgtSubMesh ); + // MeshCleaner cleaner( tgtSubMesh ); // ------------------------------------------------------------------------- // mapper doesn't take care of nodes already existing on edges and vertices, @@ -497,7 +492,7 @@ bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& bool isSeam = helper.IsSeamShape( sm->GetId() ); - enum { NEW_NODES, OLD_NODES }; + enum { NEW_NODES = 0, OLD_NODES }; map< double, const SMDS_MeshNode* > u2nodesMaps[2], u2nodesOnSeam; map< double, const SMDS_MeshNode* >::iterator u_oldNode, u_newNode, u_newOnSeam, newEnd; set< const SMDS_MeshNode* > seamNodes; @@ -518,7 +513,7 @@ bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& } // sort nodes on edges by its position - map< double, const SMDS_MeshNode* > & pos2nodes = u2nodesMaps[ isOld ]; + map< double, const SMDS_MeshNode* > & pos2nodes = u2nodesMaps[isOld ? OLD_NODES : NEW_NODES]; switch ( node->GetPosition()->GetTypeOfPosition() ) { case SMDS_TOP_VERTEX: { @@ -536,14 +531,22 @@ bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& node->GetPosition()->GetTypeOfPosition()); } } - if ( u2nodesMaps[ OLD_NODES ].size() != u2nodesMaps[ NEW_NODES ].size() ) - RETURN_BAD_RESULT("Different nb of old and new nodes " << + if ( u2nodesMaps[ NEW_NODES ].size() != u2nodesMaps[ OLD_NODES ].size() ) + { + if ( u2nodesMaps[ NEW_NODES ].size() == 0 && + sm->GetSubShape().ShapeType() == TopAbs_EDGE && + BRep_Tool::Degenerated( TopoDS::Edge( sm->GetSubShape() ))) + // NPAL15894 (tt88bis.py) - project mesh built by NETGEN_1d_2D that + // does not make segments/nodes on degenerated edges + continue; + RETURN_BAD_RESULT("Different nb of old and new nodes on shape #"<< sm->GetId() <<" "<< u2nodesMaps[ OLD_NODES ].size() << " != " << u2nodesMaps[ NEW_NODES ].size()); - if ( isSeam && u2nodesMaps[ OLD_NODES ].size() != u2nodesOnSeam.size() ) + } + if ( isSeam && u2nodesMaps[ OLD_NODES ].size() != u2nodesOnSeam.size() ) { RETURN_BAD_RESULT("Different nb of old and seam nodes " << u2nodesMaps[ OLD_NODES ].size() << " != " << u2nodesOnSeam.size()); - + } // Make groups of nodes to merge u_oldNode = u2nodesMaps[ OLD_NODES ].begin(); u_newNode = u2nodesMaps[ NEW_NODES ].begin(); @@ -606,7 +609,7 @@ bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& } } - cleaner.Release(); // do not remove mesh + //cleaner.Release(); // do not remove mesh return true; } diff --git a/src/StdMeshers/StdMeshers_Projection_3D.cxx b/src/StdMeshers/StdMeshers_Projection_3D.cxx index 68eda5d65..4a3d9a630 100644 --- a/src/StdMeshers/StdMeshers_Projection_3D.cxx +++ b/src/StdMeshers/StdMeshers_Projection_3D.cxx @@ -92,6 +92,7 @@ bool StdMeshers_Projection_3D::CheckHypothesis(SMESH_Mesh& SMESH_Hypothesis::Hypothesis_Status& aStatus) { // check aShape that must be a 6 faces block +/* PAL16229 if ( TAssocTool::Count( aShape, TopAbs_SHELL, 1 ) != 1 || TAssocTool::Count( aShape, TopAbs_FACE , 1 ) != 6 || TAssocTool::Count( aShape, TopAbs_EDGE , 1 ) != 12 || @@ -100,7 +101,7 @@ bool StdMeshers_Projection_3D::CheckHypothesis(SMESH_Mesh& aStatus = HYP_BAD_GEOMETRY; return false; } - +*/ list ::const_iterator itl; const list &hyps = GetUsedHypothesis(aMesh, aShape); @@ -206,14 +207,24 @@ bool StdMeshers_Projection_3D::Compute(SMESH_Mesh& aMesh, const TopoDS_Shape& aS srcShell = TopoDS::Shell( exp.Current() ); if ( nbShell != 1 ) return error(COMPERR_BAD_SHAPE, - SMESH_Comment("Shape must have 1 shell but not") << nbShell); + SMESH_Comment("Source shape must have 1 shell but not ") << nbShell); exp.Init( aShape, TopAbs_SHELL ); for ( nbShell = 0; exp.More(); exp.Next(), ++nbShell ) tgtShell = TopoDS::Shell( exp.Current() ); if ( nbShell != 1 ) return error(COMPERR_BAD_SHAPE, - SMESH_Comment("Shape must have 1 shell but not") << nbShell); + SMESH_Comment("Target shape must have 1 shell but not ") << nbShell); + + // Check that shapes are blocks + if ( TAssocTool::Count( tgtShell, TopAbs_FACE , 1 ) != 6 || + TAssocTool::Count( tgtShell, TopAbs_EDGE , 1 ) != 12 || + TAssocTool::Count( tgtShell, TopAbs_WIRE , 1 ) != 6 ) + return error(COMPERR_BAD_SHAPE, "Target shape is not a block"); + if ( TAssocTool::Count( srcShell, TopAbs_FACE , 1 ) != 6 || + TAssocTool::Count( srcShell, TopAbs_EDGE , 1 ) != 12 || + TAssocTool::Count( srcShell, TopAbs_WIRE , 1 ) != 6 ) + return error(COMPERR_BAD_SHAPE, "Source shape is not a block"); // Assure that mesh on a source shape is computed @@ -251,12 +262,12 @@ bool StdMeshers_Projection_3D::Compute(SMESH_Mesh& aMesh, const TopoDS_Shape& aS TopExp::Vertices( TopoDS::Edge( exp.Current() ), tgtV000, tgtV100 ); if ( !shape2ShapeMap.IsBound( tgtV000 ) || !shape2ShapeMap.IsBound( tgtV100 )) - return error(dfltErr(),"Association of subshapes failed" ); + return error("Association of subshapes failed" ); srcV000 = TopoDS::Vertex( shape2ShapeMap( tgtV000 )); srcV100 = TopoDS::Vertex( shape2ShapeMap( tgtV100 )); if ( !TAssocTool::IsSubShape( srcV000, srcShell ) || !TAssocTool::IsSubShape( srcV100, srcShell )) - return error(dfltErr(),"Incorrect association of subshapes" ); + return error("Incorrect association of subshapes" ); } // Load 2 SMESH_Block's with src and tgt shells @@ -342,12 +353,12 @@ bool StdMeshers_Projection_3D::Compute(SMESH_Mesh& aMesh, const TopoDS_Shape& aS gp_Pnt srcCoord = gpXYZ( srcNode ); gp_XYZ srcParam; if ( !srcBlock.ComputeParameters( srcCoord, srcParam )) - return error(dfltErr(),SMESH_Comment("Can't compute normalized parameters ") + return error(SMESH_Comment("Can't compute normalized parameters ") << "for source node " << srcNode->GetID()); // compute coordinates of target node by srcParam gp_XYZ tgtXYZ; if ( !tgtBlock.ShellPoint( srcParam, tgtXYZ )) - return error(dfltErr(),"Can't compute coordinates by normalized parameters"); + return error("Can't compute coordinates by normalized parameters"); // add node SMDS_MeshNode* newNode = tgtMeshDS->AddNode( tgtXYZ.X(), tgtXYZ.Y(), tgtXYZ.Z() ); tgtMeshDS->SetNodeInVolume( newNode, helper.GetSubShapeID() ); diff --git a/src/StdMeshers/StdMeshers_Propagation.cxx b/src/StdMeshers/StdMeshers_Propagation.cxx index 9bbab440e..306ae1830 100644 --- a/src/StdMeshers/StdMeshers_Propagation.cxx +++ b/src/StdMeshers/StdMeshers_Propagation.cxx @@ -28,10 +28,18 @@ #include "utilities.h" +#include "SMDS_SetIterator.hxx" +#include "SMESH_Algo.hxx" +#include "SMESH_HypoFilter.hxx" #include "SMESH_Mesh.hxx" #include "SMESH_subMesh.hxx" -#include "SMESH_HypoFilter.hxx" -#include "SMDS_SetIterator.hxx" + +#include +#include +#include + +#define DBGMSG(txt) \ +// cout << txt << endl; using namespace std; @@ -54,7 +62,7 @@ namespace { /*! * \brief Return an edge from which hypotheses are propagated from */ - static TopoDS_Edge GetSource(SMESH_subMesh * submesh) { return TopoDS_Edge(); }; + static TopoDS_Edge GetSource(SMESH_subMesh * submesh); /*! * \brief Does it's main job */ @@ -106,7 +114,7 @@ TopoDS_Edge StdMeshers_Propagation::GetPropagationSource(SMESH_Mesh& theMesh, namespace { - enum SubMeshState { WAIT_PROPAG_HYP, // no propagation hyp in chain + enum SubMeshState { WAIT_PROPAG_HYP, // propagation hyp or local 1D hyp is missing HAS_PROPAG_HYP, // propag hyp on this submesh IN_CHAIN, // submesh is in propagation chain LAST_IN_CHAIN, // submesh with local 1D hyp breaking a chain @@ -115,15 +123,24 @@ namespace { struct PropagationMgrData : public EventListenerData { bool myForward; //!< true if a curve of edge in chain is codirected with one of source edge - PropagationMgrData( SubMeshState state ): EventListenerData(true) { - myType = state; + PropagationMgrData( SubMeshState state=WAIT_PROPAG_HYP ): EventListenerData(true) { + myType = state; myForward = true; + } + void Init() { + myType = WAIT_PROPAG_HYP; mySubMeshes.clear(); myForward = true; } SubMeshState State() const { return (SubMeshState) myType; } + void SetState(SubMeshState state) { + myType = state; + } void SetSource(SMESH_subMesh* sm ) { mySubMeshes.clear(); if ( sm ) mySubMeshes.push_back( sm ); } + void AddSource(SMESH_subMesh* sm ) { + if ( sm ) mySubMeshes.push_back( sm ); + } void SetChain(list< SMESH_subMesh* >& chain ) { mySubMeshes.clear(); mySubMeshes.splice( mySubMeshes.end(), chain ); } @@ -131,16 +148,6 @@ namespace { SMESH_subMesh* GetSource() const; }; - //============================================================================= - /*! - * \brief return filter to find Propagation hypothesis - */ - SMESH_HypoFilter & propagHypFilter() - { - static SMESH_HypoFilter propagHypFilter - ( SMESH_HypoFilter::HasName( StdMeshers_Propagation::GetName ())); - return propagHypFilter; - } //============================================================================= /*! * \brief return static PropagationMgr @@ -156,9 +163,9 @@ namespace { } //============================================================================= /*! - * \brief return PropagationMgrData + * \brief return PropagationMgrData found on a submesh */ - PropagationMgrData* getData(SMESH_subMesh* sm) + PropagationMgrData* findData(SMESH_subMesh* sm) { if ( sm ) return static_cast< PropagationMgrData* >( sm->GetEventListenerData( getListener() )); @@ -166,57 +173,61 @@ namespace { } //============================================================================= /*! - * \brief return PropagationMgrData + * \brief return PropagationMgrData found on theEdge submesh */ - PropagationMgrData* getData(SMESH_Mesh& theMesh, const TopoDS_Shape& theEdge) + PropagationMgrData* findData(SMESH_Mesh& theMesh, const TopoDS_Shape& theEdge) { if ( theEdge.ShapeType() == TopAbs_EDGE ) - return getData( theMesh.GetSubMeshContaining( theEdge ) ); + return findData( theMesh.GetSubMeshContaining( theEdge ) ); return 0; } - //================================================================================ + //============================================================================= /*! - * \brief Return an iterator on a chain + * \brief return existing or a new PropagationMgrData */ - SMESH_subMeshIteratorPtr PropagationMgrData::GetChain() const + PropagationMgrData* getData(SMESH_subMesh* sm) { - typedef SMESH_subMesh* TsubMesh; - typedef SMDS_SetIterator< TsubMesh, list< TsubMesh >::const_iterator > TIterator; - switch ( State() ) { - case HAS_PROPAG_HYP: - return SMESH_subMeshIteratorPtr - ( new TIterator( mySubMeshes.begin(), mySubMeshes.end() )); - case IN_CHAIN: - case LAST_IN_CHAIN: - if ( mySubMeshes.empty() ) break; - return getData( mySubMeshes.front() )->GetChain(); - default:; + PropagationMgrData* data = findData( sm ); + if ( !data && sm ) { + data = new PropagationMgrData(); + sm->SetEventListener( getListener(), data, sm ); } - return SMESH_subMeshIteratorPtr - ( new TIterator( mySubMeshes.end(), mySubMeshes.end() )); + return data; } - //================================================================================ + //============================================================================= /*! - * \brief Return a propagation source submesh + * \brief Returns a local 1D hypothesis used for theEdge */ - SMESH_subMesh* PropagationMgrData::GetSource() const + const SMESH_Hypothesis* getLocal1DHyp (SMESH_Mesh& theMesh, + const TopoDS_Shape& theEdge) { - if ( myType == IN_CHAIN || myType == LAST_IN_CHAIN ) - if ( !mySubMeshes.empty() ) - return mySubMeshes.front(); - return 0; + static SMESH_HypoFilter hypo; + hypo.Init( hypo.HasDim( 1 )). + AndNot ( hypo.IsAlgo() ). + AndNot ( hypo.IsAssignedTo( theMesh.GetMeshDS()->ShapeToMesh() )); + return theMesh.GetHypothesis( theEdge, hypo, true ); } //============================================================================= /*! - * \brief Returns a local 1D hypothesis used for theEdge + * \brief Returns a propagation hypothesis assigned to theEdge */ - const SMESH_Hypothesis* isLocal1DHypothesis (SMESH_Mesh& theMesh, - const TopoDS_Shape& theEdge) + const SMESH_Hypothesis* getProagationHyp (SMESH_Mesh& theMesh, + const TopoDS_Shape& theEdge) { - static SMESH_HypoFilter hypo ( SMESH_HypoFilter::HasDim( 1 )); - hypo.AndNot( hypo.IsAlgo() ).AndNot( hypo.IsAssignedTo( theMesh.GetMeshDS()->ShapeToMesh() )); - - return theMesh.GetHypothesis( theEdge, hypo, true ); + static SMESH_HypoFilter propagHypFilter + ( SMESH_HypoFilter::HasName( StdMeshers_Propagation::GetName ())); + return theMesh.GetHypothesis( theEdge, propagHypFilter, true ); + } + //================================================================================ + /*! + * \brief Return an iterator on a list of submeshes + */ + SMESH_subMeshIteratorPtr iterate( list::const_iterator from, + list::const_iterator to) + { + typedef SMESH_subMesh* TsubMesh; + typedef SMDS_SetIterator< TsubMesh, list< TsubMesh >::const_iterator > TIterator; + return SMESH_subMeshIteratorPtr ( new TIterator( from, to )); } //================================================================================ /*! @@ -225,126 +236,212 @@ namespace { */ bool buildPropagationChain ( SMESH_subMesh* theMainSubMesh ) { - // const TopoDS_Shape& theMainEdge = theMainSubMesh->GetSubShape(); -// if (theMainEdge.ShapeType() != TopAbs_EDGE) return true; - -// SMESH_Mesh* mesh = theMainSubMesh->GetFather(); - -// EventListenerData* chainData = new PropagationMgrData(HAS_PROPAG_HYP); -// theMainSubMesh->SetEventListener( getListener(), chainData, theMainSubMesh ); - -// // Edges submeshes, on which the 1D hypothesis will be propagated from -// list & chain = chainData->mySubMeshes; - -// // List of edges, added to chain on the previous cycle pass -// TopTools_ListOfShape listPrevEdges; -// listPrevEdges.Append(theMainEdge.Oriented( TopAbs_FORWARD )); - -// // 4____3____2____3____4____5 -// // | | | | | | Number in the each knot of -// // | | | | | | grid indicates cycle pass, -// // 3____2____1____2____3____4 on which corresponding edge -// // | | | | | | (perpendicular to the plane -// // | | | | | | of view) will be found. -// // 2____1____0____1____2____3 -// // | | | | | | -// // | | | | | | -// // 3____2____1____2____3____4 - -// // Collect all edges pass by pass -// while (listPrevEdges.Extent() > 0) { -// // List of edges, added to chain on this cycle pass -// TopTools_ListOfShape listCurEdges; - -// // Find the next portion of edges -// TopTools_ListIteratorOfListOfShape itE (listPrevEdges); -// for (; itE.More(); itE.Next()) { -// TopoDS_Shape anE = itE.Value(); - -// // Iterate on faces, having edge -// TopTools_ListIteratorOfListOfShape itA (mesh->GetAncestors(anE)); -// for (; itA.More(); itA.Next()) { -// TopoDS_Shape aW = itA.Value(); - -// // There are objects of different type among the ancestors of edge -// if (aW.ShapeType() == TopAbs_WIRE) { -// TopoDS_Shape anOppE; - -// BRepTools_WireExplorer aWE (TopoDS::Wire(aW)); -// Standard_Integer nb = 1, found = 0; -// TopTools_Array1OfShape anEdges (1,4); -// for (; aWE.More(); aWE.Next(), nb++) { -// if (nb > 4) { -// found = 0; -// break; -// } -// anEdges(nb) = aWE.Current(); -// if (!_mapAncestors.Contains(anEdges(nb))) { -// MESSAGE("WIRE EXPLORER HAVE GIVEN AN INVALID EDGE !!!"); -// break; -// } -// if (anEdges(nb).IsSame(anE)) found = nb; -// } - -// if (nb == 5 && found > 0) { -// // Quadrangle face found, get an opposite edge -// Standard_Integer opp = ( found + 2 ) % 4; -// anOppE = anEdges(opp); - -// // add anOppE to aChain if ... -// PropagationMgrData* data = getData( *mesh, anOppE ); -// if ( !data || data->State() == WAIT_PROPAG_HYP ) { // ... anOppE is not in any chain -// if ( !isLocal1DHypothesis( *mesh, anOppE )) { // ... no other 1d hyp on anOppE -// // Add found edge to the chain oriented so that to -// // have it co-directed with a forward MainEdge -// TopAbs_Orientation ori = anE.Orientation(); -// if ( anEdges(opp).Orientation() == anEdges(found).Orientation() ) -// ori = TopAbs::Reverse( ori ); -// anOppE.Orientation( ori ); -// aChain.Add(anOppE); -// listCurEdges.Append(anOppE); -// } -// else { -// // Collision! -// MESSAGE("Error: Collision between propagated hypotheses"); -// CleanMeshOnPropagationChain(theMainEdge); -// aChain.Clear(); -// return ( aMainHyp == isLocal1DHypothesis(aMainEdgeForOppEdge) ); -// } -// } -// } -// } // if (nb == 5 && found > 0) -// } // if (aF.ShapeType() == TopAbs_WIRE) -// } // for (; itF.More(); itF.Next()) -// } // for (; itE.More(); itE.Next()) - -// listPrevEdges = listCurEdges; -// } // while (listPrevEdges.Extent() > 0) - -// CleanMeshOnPropagationChain(theMainEdge); + DBGMSG( "buildPropagationChain from " << theMainSubMesh->GetId() ); + const TopoDS_Shape& theMainEdge = theMainSubMesh->GetSubShape(); + if (theMainEdge.ShapeType() != TopAbs_EDGE) return true; + + SMESH_Mesh* mesh = theMainSubMesh->GetFather(); + + PropagationMgrData* chainData = getData( theMainSubMesh ); + chainData->SetState( HAS_PROPAG_HYP ); + + // Edge submeshes, to which the 1D hypothesis will be propagated from theMainEdge + list & chain = chainData->mySubMeshes; + chain.clear(); + chain.push_back( theMainSubMesh ); + + TopTools_MapOfShape checkedShapes; + checkedShapes.Add( theMainEdge ); + + list::iterator smIt = chain.begin(); + for ( ; smIt != chain.end(); ++smIt ) + { + const TopoDS_Edge& anE = TopoDS::Edge( (*smIt)->GetSubShape() ); + PropagationMgrData* data = findData( *smIt ); + if ( !data ) continue; + + // Iterate on faces, having edge + TopTools_ListIteratorOfListOfShape itA (mesh->GetAncestors(anE)); + for (; itA.More(); itA.Next()) + { + // there are objects of different type among the ancestors of edge + if ( itA.Value().ShapeType() != TopAbs_WIRE || !checkedShapes.Add( itA.Value() )) + continue; + + // Get ordered edges and find index of anE in a sequence + BRepTools_WireExplorer aWE (TopoDS::Wire(itA.Value())); + vector edges; + edges.reserve(4); + int edgeIndex = 0; + for (; aWE.More(); aWE.Next()) { + TopoDS_Edge edge = aWE.Current(); + edge.Orientation( aWE.Orientation() ); + if ( edge.IsSame( anE )) + edgeIndex = edges.size(); + edges.push_back( edge ); + } + + // Find an edge opposite to anE + TopoDS_Edge anOppE; + if ( edges.size() < 4 ) { + continue; // too few edges + } + else if ( edges.size() == 4 ) { + int oppIndex = edgeIndex + 2; + if ( oppIndex > 3 ) oppIndex -= 4; + anOppE = edges[ oppIndex ]; + } + else { + // count nb sides + TopoDS_Edge prevEdge = anE; + int nbSide = 0, eIndex = edgeIndex + 1; + for ( int i = 0; i < edges.size(); ++i, ++eIndex ) + { + if ( eIndex == edges.size() ) + eIndex = 0; + if ( !SMESH_Algo::IsContinuous( prevEdge, edges[ eIndex ])) { + nbSide++; + } + else { + // check that anE is not a part of a composite side + if ( anE.IsSame( prevEdge ) || anE.IsSame( edges[ eIndex ])) { + anOppE.Nullify(); break; + } + } + if ( nbSide == 2 ) { // opposite side + if ( !anOppE.IsNull() ) { + // composite opposite side -> stop propagation + anOppE.Nullify(); break; + } + anOppE = edges[ eIndex ]; + } + if ( nbSide == 5 ) { + anOppE.Nullify(); break; // too many sides + } + prevEdge = edges[ eIndex ]; + } + if ( anOppE.IsNull() ) + continue; + if ( nbSide != 4 ) { + DBGMSG( nbSide << " sides in wire #" << mesh->GetMeshDS()->ShapeToIndex( itA.Value() ) << " - SKIP" ); + continue; + } + } + if ( anOppE.IsNull() || !checkedShapes.Add( anOppE )) + continue; + SMESH_subMesh* oppSM = mesh->GetSubMesh( anOppE ); + PropagationMgrData* oppData = getData( oppSM ); + + // Add anOppE to aChain if ... + if ( oppData->State() == WAIT_PROPAG_HYP ) // ... anOppE is not in any chain + { + oppData->SetSource( theMainSubMesh ); + if ( !getLocal1DHyp( *mesh, anOppE )) // ... no 1d hyp on anOppE + { + oppData->myForward = data->myForward; + if ( edges[ edgeIndex ].Orientation() == anOppE.Orientation() ) + oppData->myForward = !oppData->myForward; + chain.push_back( oppSM ); + oppSM->ComputeStateEngine( SMESH_subMesh::CLEAN ); + oppData->SetState( IN_CHAIN ); + DBGMSG( "set IN_CHAIN on " << oppSM->GetId() ); + } + else { + oppData->SetState( LAST_IN_CHAIN ); + DBGMSG( "set LAST_IN_CHAIN on " << oppSM->GetId() ); + } + } + else if ( oppData->State() == LAST_IN_CHAIN ) // anOppE breaks other chain + { + DBGMSG( "encounters LAST_IN_CHAIN on " << oppSM->GetId() ); + oppData->AddSource( theMainSubMesh ); + } + } // loop on face ancestors + } // loop on the chain + + // theMainSubMesh must not be in a chain + chain.pop_front(); + return true; } //================================================================================ /*! * \brief Clear propagation chain */ - //================================================================================ - bool clearPropagationChain( SMESH_subMesh* subMesh ) { - if ( PropagationMgrData* data = getData( subMesh )) { - if ( data->State() == IN_CHAIN ) + DBGMSG( "clearPropagationChain from " << subMesh->GetId() ); + if ( PropagationMgrData* data = findData( subMesh )) + { + switch ( data->State() ) { + case IN_CHAIN: return clearPropagationChain( data->GetSource() ); + + case HAS_PROPAG_HYP: { + SMESH_subMeshIteratorPtr smIt = data->GetChain(); + while ( smIt->more() ) { + SMESH_subMesh* sm = smIt->next(); + getData( sm )->Init(); + sm->ComputeStateEngine( SMESH_subMesh::CLEAN ); + } + data->Init(); + break; + } + case LAST_IN_CHAIN: { + SMESH_subMeshIteratorPtr smIt = iterate( data->mySubMeshes.begin(), + data->mySubMeshes.end()); + while ( smIt->more() ) + clearPropagationChain( smIt->next() ); + data->Init(); + break; + } + default:; + } return true; } return false; - } + } + + + //================================================================================ + /*! + * \brief Return an iterator on chain submeshes + */ + //================================================================================ + + SMESH_subMeshIteratorPtr PropagationMgrData::GetChain() const + { + switch ( State() ) { + case HAS_PROPAG_HYP: + return iterate( mySubMeshes.begin(), mySubMeshes.end() ); + case IN_CHAIN: + if ( mySubMeshes.empty() ) break; + return getData( mySubMeshes.front() )->GetChain(); + default:; + } + return iterate( mySubMeshes.end(), mySubMeshes.end() ); + } + //================================================================================ + /*! + * \brief Return a propagation source submesh + */ + //================================================================================ + + SMESH_subMesh* PropagationMgrData::GetSource() const + { + if ( myType == IN_CHAIN ) + if ( !mySubMeshes.empty() ) + return mySubMeshes.front(); + return 0; + } //================================================================================ /*! * \brief Constructor */ + //================================================================================ + PropagationMgr::PropagationMgr() : SMESH_subMeshEventListener( false ) // won't be deleted by submesh {} @@ -352,14 +449,16 @@ namespace { /*! * \brief Set PropagationMgr on a submesh */ + //================================================================================ + void PropagationMgr::Set(SMESH_subMesh * submesh) { - EventListenerData* data = EventListenerData::MakeData(submesh,WAIT_PROPAG_HYP); - + DBGMSG( "PropagationMgr::Set() on " << submesh->GetId() ); + EventListenerData* data = new PropagationMgrData(); submesh->SetEventListener( getListener(), data, submesh ); const SMESH_Hypothesis * propagHyp = - submesh->GetFather()->GetHypothesis( submesh->GetSubShape(), propagHypFilter(), true ); + getProagationHyp( *submesh->GetFather(), submesh->GetSubShape() ); if ( propagHyp ) getListener()->ProcessEvent( SMESH_subMesh::ADD_HYP, SMESH_subMesh::ALGO_EVENT, @@ -367,7 +466,28 @@ namespace { data, propagHyp); } + //================================================================================ + /*! + * \brief Return an edge from which hypotheses are propagated + */ + //================================================================================ + TopoDS_Edge PropagationMgr::GetSource(SMESH_subMesh * submesh) + { + if ( PropagationMgrData* data = findData( submesh )) { + if ( data->State() == IN_CHAIN ) { + if ( SMESH_subMesh* sm = data->GetSource() ) + { + TopoDS_Shape edge = sm->GetSubShape(); + edge = edge.Oriented( data->myForward ? TopAbs_FORWARD : TopAbs_REVERSED ); + DBGMSG( " GetSource() = edge " << sm->GetId() << " REV = " << (!data->myForward)); + if ( edge.ShapeType() == TopAbs_EDGE ) + return TopoDS::Edge( edge ); + } + } + } + return TopoDS_Edge(); + } //================================================================================ /*! * \brief React on events on 1D submeshes @@ -377,31 +497,36 @@ namespace { void PropagationMgr::ProcessEvent(const int event, const int eventType, SMESH_subMesh* subMesh, - SMESH_subMeshEventListenerData* data, + SMESH_subMeshEventListenerData* listenerData, const SMESH_Hypothesis* hyp) { - if ( !data ) + if ( !listenerData ) return; if ( !hyp || hyp->GetType() != SMESHDS_Hypothesis::PARAM_ALGO || hyp->GetDim() != 1 ) return; if ( eventType != SMESH_subMesh::ALGO_EVENT ) return; + DBGMSG( "PropagationMgr::ProcessEvent() on " << subMesh->GetId() ); - bool isPropagHyp = ( StdMeshers_Propagation::GetName() != hyp->GetName() ); + bool isPropagHyp = ( StdMeshers_Propagation::GetName() == hyp->GetName() ); - switch ( data->myType ) { + PropagationMgrData* data = static_cast( listenerData ); + switch ( data->State() ) { - case WAIT_PROPAG_HYP: { // no propagation hyp in chain + case WAIT_PROPAG_HYP: { // propagation hyp or local 1D hyp is missing // -------------------------------------------------------- - if ( !isPropagHyp ) + bool hasPropagHyp = ( isPropagHyp || + getProagationHyp( *subMesh->GetFather(), subMesh->GetSubShape()) ); + if ( !hasPropagHyp ) return; - if ( !isLocal1DHypothesis( *subMesh->GetFather(), subMesh->GetSubShape())) + bool hasLocal1DHyp = getLocal1DHyp( *subMesh->GetFather(), subMesh->GetSubShape()); + if ( !hasLocal1DHyp ) return; if ( event == SMESH_subMesh::ADD_HYP || - event == SMESH_subMesh::ADD_FATHER_HYP ) // add propagation hyp + event == SMESH_subMesh::ADD_FATHER_HYP ) // add local or propagation hyp { + DBGMSG( "ADD_HYP propagation to WAIT_PROPAG_HYP " << subMesh->GetId() ); // build propagation chain - clearPropagationChain( subMesh ); buildPropagationChain( subMesh ); } return; @@ -411,32 +536,57 @@ namespace { switch ( event ) { case SMESH_subMesh::REMOVE_HYP: case SMESH_subMesh::REMOVE_FATHER_HYP: // remove propagation hyp - if ( isPropagHyp ) + if ( isPropagHyp && !getProagationHyp( *subMesh->GetFather(), subMesh->GetSubShape()) ) { + DBGMSG( "REMOVE_HYP propagation from HAS_PROPAG_HYP " << subMesh->GetId() ); // clear propagation chain + clearPropagationChain( subMesh ); } return; case SMESH_subMesh::MODIF_HYP: // hyp modif // clear mesh in a chain + DBGMSG( "MODIF_HYP on HAS_PROPAG_HYP " << subMesh->GetId() ); + SMESH_subMeshIteratorPtr smIt = data->GetChain(); + while ( smIt->more() ) { + SMESH_subMesh* smInChain = smIt->next(); + smInChain->AlgoStateEngine( SMESH_subMesh::MODIF_HYP, + (SMESH_Hypothesis*) hyp ); + } return; } return; } case IN_CHAIN: { // submesh is in propagation chain // -------------------------------------------------------- - if ( event == SMESH_subMesh::ADD_HYP ) // add local hypothesis - if ( isPropagHyp ) - ; // collision - else - ; // rebuild propagation chain - return; + if ( event == SMESH_subMesh::ADD_HYP ) { // add local hypothesis + if ( isPropagHyp ) { // propagation hyp added + DBGMSG( "ADD_HYP propagation on IN_CHAIN " << subMesh->GetId() ); + // collision - do nothing + } + else { // 1D hyp added + // rebuild propagation chain + DBGMSG( "ADD_HYP 1D on IN_CHAIN " << subMesh->GetId() ); + SMESH_subMesh* sourceSM = data->GetSource(); + clearPropagationChain( sourceSM ); + buildPropagationChain( sourceSM ); + } + } + return; } case LAST_IN_CHAIN: { // submesh with local 1D hyp, breaking a chain // -------------------------------------------------------- - if ( event == SMESH_subMesh::REMOVE_HYP ) // remove local hyp - ; // rebuild propagation chain + if ( event == SMESH_subMesh::REMOVE_HYP ) { // remove local hyp + // rebuild propagation chain + DBGMSG( "REMOVE_HYP 1D from LAST_IN_CHAIN " << subMesh->GetId() ); + list sourceSM = data->mySubMeshes; + clearPropagationChain( subMesh ); + SMESH_subMeshIteratorPtr smIt = iterate( sourceSM.begin(), sourceSM.end()); + while ( smIt->more() ) + buildPropagationChain( smIt->next() ); + } return; } } // switch by SubMeshState } + } // namespace diff --git a/src/StdMeshers/StdMeshers_Propagation.hxx b/src/StdMeshers/StdMeshers_Propagation.hxx index c0d2f3cdf..62ad2a439 100644 --- a/src/StdMeshers/StdMeshers_Propagation.hxx +++ b/src/StdMeshers/StdMeshers_Propagation.hxx @@ -64,7 +64,7 @@ class STDMESHERS_EXPORT StdMeshers_Propagation:public SMESH_Hypothesis static void SetPropagationMgr(SMESH_subMesh* subMesh); /*! - * \brief Return an edge from which hypotheses are propagated from + * \brief Return an edge from which hypotheses are propagated * \param theMesh - mesh * \param theEdge - edge to which hypotheses are propagated * \retval TopoDS_Edge - source edge, also passing orientation diff --git a/src/StdMeshers/StdMeshers_QuadranglePreference.cxx b/src/StdMeshers/StdMeshers_QuadranglePreference.cxx index b16eeb58e..3e04aa872 100644 --- a/src/StdMeshers/StdMeshers_QuadranglePreference.cxx +++ b/src/StdMeshers/StdMeshers_QuadranglePreference.cxx @@ -42,7 +42,7 @@ StdMeshers_QuadranglePreference::StdMeshers_QuadranglePreference(int hyp :SMESH_Hypothesis(hypId, studyId, gen) { _name = "QuadranglePreference"; - _param_algo_dim = 2; // is used by StdMeshers_Quadrangle_2D + _param_algo_dim = -2; // auxiliary used by StdMeshers_Quadrangle_2D } //============================================================================= diff --git a/src/StdMeshers/StdMeshers_Quadrangle_2D.cxx b/src/StdMeshers/StdMeshers_Quadrangle_2D.cxx index 8a1659402..2c3c74128 100644 --- a/src/StdMeshers/StdMeshers_Quadrangle_2D.cxx +++ b/src/StdMeshers/StdMeshers_Quadrangle_2D.cxx @@ -119,7 +119,7 @@ bool StdMeshers_Quadrangle_2D::CheckHypothesis aStatus = SMESH_Hypothesis::HYP_OK; // there is only one compatible Hypothesis so far - const list &hyps = GetUsedHypothesis(aMesh, aShape); + const list &hyps = GetUsedHypothesis(aMesh, aShape, false); myQuadranglePreference = hyps.size() > 0; return isOk; @@ -132,9 +132,10 @@ bool StdMeshers_Quadrangle_2D::CheckHypothesis //============================================================================= bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh& aMesh, - const TopoDS_Shape& aShape) throw (SALOME_Exception) + const TopoDS_Shape& aShape)// throw (SALOME_Exception) { - Unexpect aCatch(SalomeException); + // PAL14921. Enable catching std::bad_alloc and Standard_OutOfMemory outside + //Unexpect aCatchSalomeException); SMESHDS_Mesh * meshDS = aMesh.GetMeshDS(); aMesh.GetSubMesh(aShape); @@ -238,6 +239,9 @@ bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh& aMesh, const vector& uv_e2 = quad->side[2]->GetUVPtStruct(true,1 ); const vector& uv_e3 = quad->side[3]->GetUVPtStruct(false,0); + if ( uv_e0.empty() || uv_e1.empty() || uv_e2.empty() || uv_e3.empty() ) + return error( COMPERR_BAD_INPUT_MESH ); + double eps = Precision::Confusion(); // Boundary quadrangles @@ -562,10 +566,8 @@ bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh& aMesh, FaceQuadStruct* StdMeshers_Quadrangle_2D::CheckNbEdges(SMESH_Mesh & aMesh, const TopoDS_Shape & aShape) - throw(SALOME_Exception) + //throw(SALOME_Exception) { - Unexpect aCatch(SalomeException); - const TopoDS_Face & F = TopoDS::Face(aShape); const bool ignoreMediumNodes = _quadraticMesh; @@ -596,16 +598,14 @@ FaceQuadStruct* StdMeshers_Quadrangle_2D::CheckNbEdges(SMESH_Mesh & aMes sideEdges.splice( sideEdges.end(), edges, edges.begin()); // edges.front() -> sideEdges.end() bool sameSide = true; while ( !edges.empty() && sameSide ) { - GeomAbs_Shape cont = SMESH_Algo::Continuity( sideEdges.back(), edges.front() ); - sameSide = ( cont >= GeomAbs_G1 ); + sameSide = SMESH_Algo::IsContinuous( sideEdges.back(), edges.front() ); if ( sameSide ) sideEdges.splice( sideEdges.end(), edges, edges.begin()); } if ( nbSides == 0 ) { // go backward from the first edge sameSide = true; while ( !edges.empty() && sameSide ) { - GeomAbs_Shape cont = SMESH_Algo::Continuity( sideEdges.front(), edges.back() ); - sameSide = ( cont >= GeomAbs_G1 ); + sameSide = SMESH_Algo::IsContinuous( sideEdges.front(), edges.back() ); if ( sameSide ) sideEdges.splice( sideEdges.begin(), edges, --edges.end()); } @@ -645,10 +645,8 @@ FaceQuadStruct* StdMeshers_Quadrangle_2D::CheckNbEdges(SMESH_Mesh & aMes FaceQuadStruct *StdMeshers_Quadrangle_2D::CheckAnd2Dcompute (SMESH_Mesh & aMesh, const TopoDS_Shape & aShape, - const bool CreateQuadratic) throw(SALOME_Exception) + const bool CreateQuadratic) //throw(SALOME_Exception) { - Unexpect aCatch(SalomeException); - _quadraticMesh = CreateQuadratic; FaceQuadStruct *quad = CheckNbEdges(aMesh, aShape); @@ -656,7 +654,12 @@ FaceQuadStruct *StdMeshers_Quadrangle_2D::CheckAnd2Dcompute if(!quad) return 0; // set normalized grid on unit square in parametric domain - SetNormalizedGrid(aMesh, aShape, quad); + bool stat = SetNormalizedGrid(aMesh, aShape, quad); + if(!stat) { + if(!quad) + delete quad; + quad = 0; + } return quad; } @@ -695,9 +698,8 @@ namespace { bool StdMeshers_Quadrangle_2D::SetNormalizedGrid (SMESH_Mesh & aMesh, const TopoDS_Shape& aShape, - FaceQuadStruct* & quad) throw (SALOME_Exception) + FaceQuadStruct* & quad) //throw (SALOME_Exception) { - Unexpect aCatch(SalomeException); // Algorithme décrit dans "Génération automatique de maillages" // P.L. GEORGE, MASSON, § 6.4.1 p. 84-85 // traitement dans le domaine paramétrique 2d u,v @@ -738,7 +740,8 @@ bool StdMeshers_Quadrangle_2D::SetNormalizedGrid (SMESH_Mesh & aMesh, const vector& uv_e3 = GetUVPtStructIn( quad, 3, nbvertic - 1 ); if ( uv_e0.empty() || uv_e1.empty() || uv_e2.empty() || uv_e3.empty() ) - return error(dfltErr(), "Can't find nodes on sides"); + //return error( "Can't find nodes on sides"); + return error( COMPERR_BAD_INPUT_MESH ); // nodes Id on "in" edges if (! quad->isEdgeOut[0]) { @@ -888,14 +891,11 @@ static gp_UV CalcUV(double x0, double x1, double y0, double y1, bool StdMeshers_Quadrangle_2D::ComputeQuadPref (SMESH_Mesh & aMesh, const TopoDS_Shape& aShape, FaceQuadStruct* quad) - throw (SALOME_Exception) { - Unexpect aCatch(SalomeException); - SMESHDS_Mesh * meshDS = aMesh.GetMeshDS(); const TopoDS_Face& F = TopoDS::Face(aShape); Handle(Geom_Surface) S = BRep_Tool::Surface(F); - const TopoDS_Wire& W = BRepTools::OuterWire(F); +// const TopoDS_Wire& W = BRepTools::OuterWire(F); bool WisF = true; // if(W.Orientation()==TopAbs_FORWARD) // WisF = true; diff --git a/src/StdMeshers/StdMeshers_Quadrangle_2D.hxx b/src/StdMeshers/StdMeshers_Quadrangle_2D.hxx index 90db88e55..72b317be2 100644 --- a/src/StdMeshers/StdMeshers_Quadrangle_2D.hxx +++ b/src/StdMeshers/StdMeshers_Quadrangle_2D.hxx @@ -47,14 +47,8 @@ enum TSideID { BOTTOM_SIDE=0, RIGHT_SIDE, TOP_SIDE, LEFT_SIDE, NB_SIDES }; typedef uvPtStruct UVPtStruct; typedef struct faceQuadStruct { - //int nbPts[4]; - //TopoDS_Edge edge[4]; vector< StdMeshers_FaceSide*> side; - //double first[4]; - //double last[4]; - //bool isEdgeForward[4]; bool isEdgeOut[4]; // true, if an edge has more nodes, than the opposite - //UVPtStruct* uv_edges[4]; UVPtStruct* uv_grid; ~faceQuadStruct(); } FaceQuadStruct; @@ -70,32 +64,27 @@ public: SMESH_Hypothesis::Hypothesis_Status& aStatus); virtual bool Compute(SMESH_Mesh& aMesh, - const TopoDS_Shape& aShape) - throw (SALOME_Exception); + const TopoDS_Shape& aShape); FaceQuadStruct* CheckAnd2Dcompute(SMESH_Mesh& aMesh, const TopoDS_Shape& aShape, - const bool CreateQuadratic) - throw (SALOME_Exception); + const bool CreateQuadratic); protected: FaceQuadStruct* CheckNbEdges(SMESH_Mesh& aMesh, - const TopoDS_Shape& aShape) - throw (SALOME_Exception); + const TopoDS_Shape& aShape); bool SetNormalizedGrid(SMESH_Mesh& aMesh, const TopoDS_Shape& aShape, - FaceQuadStruct*& quad) - throw (SALOME_Exception); + FaceQuadStruct*& quad); /** * Special function for creation only quandrangle faces */ bool ComputeQuadPref(SMESH_Mesh& aMesh, const TopoDS_Shape& aShape, - FaceQuadStruct* quad) - throw (SALOME_Exception); + FaceQuadStruct* quad); UVPtStruct* LoadEdgePoints2(SMESH_Mesh& aMesh, const TopoDS_Face& F, const TopoDS_Edge& E, diff --git a/src/StdMeshers/StdMeshers_RadialPrism_3D.cxx b/src/StdMeshers/StdMeshers_RadialPrism_3D.cxx index c83bff525..128b32077 100644 --- a/src/StdMeshers/StdMeshers_RadialPrism_3D.cxx +++ b/src/StdMeshers/StdMeshers_RadialPrism_3D.cxx @@ -98,13 +98,14 @@ bool StdMeshers_RadialPrism_3D::CheckHypothesis(SMESH_Mesh& SMESH_Hypothesis::Hypothesis_Status& aStatus) { // check aShape that must have 2 shells +/* PAL16229 if ( TAssocTool::Count( aShape, TopAbs_SOLID, 0 ) != 1 || TAssocTool::Count( aShape, TopAbs_SHELL, 0 ) != 2 ) { aStatus = HYP_BAD_GEOMETRY; return false; } - +*/ myNbLayerHypo = 0; myDistributionHypo = 0; @@ -167,7 +168,7 @@ bool StdMeshers_RadialPrism_3D::Compute(SMESH_Mesh& aMesh, const TopoDS_Shape& a if ( !outerShell.IsSame( It.Value() )) innerShell = It.Value(); if ( nbShells != 2 ) - return error(COMPERR_BAD_SHAPE, SMESH_Comment("Must be 2 shells but not")<ShapeToIndex( outFace )); } else { inFace = TopoDS::Face( shape2ShapeMap( outFace )); @@ -222,12 +223,18 @@ bool StdMeshers_RadialPrism_3D::Compute(SMESH_Mesh& aMesh, const TopoDS_Shape& a vector< const TNodeColumn* > columns( nbNodes ); for ( int i = 0; i < nbNodes; ++i ) { - const SMDS_MeshNode* n = face->GetNode( i ); - TNode2ColumnMap::iterator n_col = node2columnMap.find( n ); - if ( n_col != node2columnMap.end() ) + const SMDS_MeshNode* nIn = face->GetNode( i ); + TNode2ColumnMap::iterator n_col = node2columnMap.find( nIn ); + if ( n_col != node2columnMap.end() ) { columns[ i ] = & n_col->second; - else - columns[ i ] = makeNodeColumn( node2columnMap, n, nodeIn2OutMap[ n ] ); + } + else { + TNodeNodeMap::iterator nInOut = nodeIn2OutMap.find( nIn ); + if ( nInOut == nodeIn2OutMap.end() ) + RETURN_BAD_RESULT("No matching node for "<< nIn->GetID() << + " in face "<< face->GetID()); + columns[ i ] = makeNodeColumn( node2columnMap, nIn, nInOut->second ); + } } StdMeshers_Prism_3D::AddPrisms( columns, myHelper ); @@ -312,24 +319,24 @@ public: const StdMeshers_LayerDistribution* hyp) { double len = pIn.Distance( pOut ); - if ( len <= DBL_MIN ) return error(dfltErr(),"Too close points of inner and outer shells"); + if ( len <= DBL_MIN ) return error("Too close points of inner and outer shells"); if ( !hyp || !hyp->GetLayerDistribution() ) - return error(dfltErr(), "Invalid LayerDistribution hypothesis"); + return error( "Invalid LayerDistribution hypothesis"); myUsedHyps.clear(); myUsedHyps.push_back( hyp->GetLayerDistribution() ); TopoDS_Edge edge = BRepBuilderAPI_MakeEdge( pIn, pOut ); SMESH_Hypothesis::Hypothesis_Status aStatus; if ( !StdMeshers_Regular_1D::CheckHypothesis( aMesh, edge, aStatus )) - return error(dfltErr(), "StdMeshers_Regular_1D::CheckHypothesis() failed" - "with LayerDistribution hypothesis"); + return error( "StdMeshers_Regular_1D::CheckHypothesis() failed " + "with LayerDistribution hypothesis"); BRepAdaptor_Curve C3D(edge); double f = C3D.FirstParameter(), l = C3D.LastParameter(); list< double > params; if ( !StdMeshers_Regular_1D::computeInternalParameters( C3D, len, f, l, params, false )) - return error(dfltErr(),"StdMeshers_Regular_1D failed to compute layers distribution"); + return error("StdMeshers_Regular_1D failed to compute layers distribution"); positions.clear(); positions.reserve( params.size() ); diff --git a/src/StdMeshers/StdMeshers_Regular_1D.cxx b/src/StdMeshers/StdMeshers_Regular_1D.cxx index 9e59aa0c6..ba5f74503 100644 --- a/src/StdMeshers/StdMeshers_Regular_1D.cxx +++ b/src/StdMeshers/StdMeshers_Regular_1D.cxx @@ -37,6 +37,7 @@ #include "StdMeshers_Deflection1D.hxx" #include "StdMeshers_AutomaticLength.hxx" #include "StdMeshers_SegmentLengthAroundVertex.hxx" +#include "StdMeshers_Propagation.hxx" #include "SMESH_Gen.hxx" #include "SMESH_Mesh.hxx" @@ -85,6 +86,7 @@ StdMeshers_Regular_1D::StdMeshers_Regular_1D(int hypId, int studyId, _compatibleHypothesis.push_back("AutomaticLength"); _compatibleHypothesis.push_back("QuadraticMesh"); // auxiliary !!! + _compatibleHypothesis.push_back("Propagation"); // auxiliary !!! } //============================================================================= @@ -410,6 +412,7 @@ void StdMeshers_Regular_1D::SetEventListener(SMESH_subMesh* subMesh) // while (smIt->more()) { // subMesh->SetEventListener( &listener, 0, smIt->next() ); // } + StdMeshers_Propagation::SetPropagationMgr( subMesh ); } //============================================================================= @@ -627,7 +630,7 @@ bool StdMeshers_Regular_1D::computeInternalParameters(Adaptor3d_Curve& theC3d, } GCPnts_UniformAbscissa Discret(theC3d, eltSize, f, l); if ( !Discret.IsDone() ) - return error( dfltErr(), "GCPnts_UniformAbscissa failed"); + return error( "GCPnts_UniformAbscissa failed"); int NbPoints = Discret.NbPoints(); for ( int i = 2; i < NbPoints; i++ ) @@ -759,7 +762,7 @@ bool StdMeshers_Regular_1D::Compute(SMESH_Mesh & aMesh, const TopoDS_Shape & aSh list< double > params; bool reversed = false; if ( !_mainEdge.IsNull() ) - reversed = aMesh.IsReversedInChain( EE, _mainEdge ); + reversed = ( _mainEdge.Orientation() == TopAbs_REVERSED ); BRepAdaptor_Curve C3d( E ); double length = EdgeLength( E ); @@ -774,6 +777,11 @@ bool StdMeshers_Regular_1D::Compute(SMESH_Mesh & aMesh, const TopoDS_Shape & aSh const SMDS_MeshNode * idPrev = idFirst; double parPrev = f; double parLast = l; + if(reversed) { + idPrev = idLast; + parPrev = l; + parLast = f; + } for (list::iterator itU = params.begin(); itU != params.end(); itU++) { double param = *itU; @@ -809,16 +817,24 @@ bool StdMeshers_Regular_1D::Compute(SMESH_Mesh & aMesh, const TopoDS_Shape & aSh meshDS->SetMeshElementOnShape(edge, shapeID); } else { - SMDS_MeshEdge* edge = meshDS->AddEdge(idPrev, idLast); - meshDS->SetMeshElementOnShape(edge, shapeID); + if(!reversed) { + SMDS_MeshEdge* edge = meshDS->AddEdge(idPrev, idLast); + meshDS->SetMeshElementOnShape(edge, shapeID); + } + else { + SMDS_MeshEdge* edge = meshDS->AddEdge(idPrev, idFirst); + meshDS->SetMeshElementOnShape(edge, shapeID); + } } } - else { + else + { + //MESSAGE("************* Degenerated edge! *****************"); + // Edge is a degenerated Edge : We put n = 5 points on the edge. const int NbPoints = 5; BRep_Tool::Range( E, f, l ); // PAL15185 double du = (l - f) / (NbPoints - 1); - //MESSAGE("************* Degenerated edge! *****************"); gp_Pnt P = BRep_Tool::Pnt(VFirst); @@ -879,11 +895,11 @@ StdMeshers_Regular_1D::GetUsedHypothesis(SMESH_Mesh & aMesh, // get non-auxiliary assigned to aShape int nbHyp = aMesh.GetHypotheses( aShape, compatibleFilter, _usedHypList, false ); - if (nbHyp == 0) + if (nbHyp == 0 && aShape.ShapeType() == TopAbs_EDGE) { // Check, if propagated from some other edge - if (aShape.ShapeType() == TopAbs_EDGE && - aMesh.IsPropagatedHypothesis(aShape, _mainEdge)) + _mainEdge = StdMeshers_Propagation::GetPropagationSource( aMesh, aShape ); + if ( !_mainEdge.IsNull() ) { // Propagation of 1D hypothesis from on this edge; // get non-auxiliary assigned to _mainEdge diff --git a/src/StdMeshersGUI/StdMeshersGUI_LayerDistributionParamWdg.cxx b/src/StdMeshersGUI/StdMeshersGUI_LayerDistributionParamWdg.cxx index 7537e621b..ed77aaf61 100644 --- a/src/StdMeshersGUI/StdMeshersGUI_LayerDistributionParamWdg.cxx +++ b/src/StdMeshersGUI/StdMeshersGUI_LayerDistributionParamWdg.cxx @@ -48,9 +48,11 @@ */ //================================================================================ -StdMeshersGUI_LayerDistributionParamWdg::StdMeshersGUI_LayerDistributionParamWdg -( SMESH::SMESH_Hypothesis_ptr hyp, - QDialog* dlg ): QHGroupBox(), myDlg( dlg ) +StdMeshersGUI_LayerDistributionParamWdg +::StdMeshersGUI_LayerDistributionParamWdg(SMESH::SMESH_Hypothesis_ptr hyp, + const QString& theName, + QDialog* dlg): + QHGroupBox(), myName(theName), myDlg( dlg ) { init(); set( hyp ); @@ -204,7 +206,7 @@ void StdMeshersGUI_LayerDistributionParamWdg::onEdit() try { QWidget* parent = this; if ( myDlg ) parent = myDlg->parentWidget(); - editor->edit( myHyp, parent ); + editor->edit( myHyp, myName, parent ); } catch(...) { } diff --git a/src/StdMeshersGUI/StdMeshersGUI_LayerDistributionParamWdg.h b/src/StdMeshersGUI/StdMeshersGUI_LayerDistributionParamWdg.h index cc8d7d801..6c6d5f680 100644 --- a/src/StdMeshersGUI/StdMeshersGUI_LayerDistributionParamWdg.h +++ b/src/StdMeshersGUI/StdMeshersGUI_LayerDistributionParamWdg.h @@ -50,7 +50,8 @@ class STDMESHERSGUI_EXPORT StdMeshersGUI_LayerDistributionParamWdg : public QHGr public: StdMeshersGUI_LayerDistributionParamWdg(SMESH::SMESH_Hypothesis_ptr hyp, - QDialog* dlg); + const QString& theName, + QDialog* dlg); ~StdMeshersGUI_LayerDistributionParamWdg(); SMESH::SMESH_Hypothesis_var GetHypothesis() { return myHyp; } @@ -76,6 +77,7 @@ private: QPushButton* myEditButton; QPopupMenu* myHypTypePopup; QDialog* myDlg; + QString myName; QString myParamValue; QStringList myHypTypes; diff --git a/src/StdMeshersGUI/StdMeshersGUI_NbSegmentsCreator.cxx b/src/StdMeshersGUI/StdMeshersGUI_NbSegmentsCreator.cxx index 02bb83a35..f5468b118 100644 --- a/src/StdMeshersGUI/StdMeshersGUI_NbSegmentsCreator.cxx +++ b/src/StdMeshersGUI/StdMeshersGUI_NbSegmentsCreator.cxx @@ -251,8 +251,7 @@ bool StdMeshersGUI_NbSegmentsCreator::readParamsFromHypo( NbSegmentsHypothesisDa StdMeshers::StdMeshers_NumberOfSegments_var h = StdMeshers::StdMeshers_NumberOfSegments::_narrow( initParamsHypothesis() ); - HypothesisData* data = SMESH::GetHypothesisData( hypType() ); - h_data.myName = isCreation() && data ? data->Label : ""; + h_data.myName = hypName(); h_data.myNbSeg = (int) h->GetNumberOfSegments(); int distr = (int) h->GetDistrType(); diff --git a/src/StdMeshersGUI/StdMeshersGUI_StdHypothesisCreator.cxx b/src/StdMeshersGUI/StdMeshersGUI_StdHypothesisCreator.cxx index 1be50e5d1..cfa700236 100644 --- a/src/StdMeshersGUI/StdMeshersGUI_StdHypothesisCreator.cxx +++ b/src/StdMeshersGUI/StdMeshersGUI_StdHypothesisCreator.cxx @@ -512,7 +512,7 @@ bool StdMeshersGUI_StdHypothesisCreator::stdParams( ListOfStdParams& p ) const { HypothesisData* data = SMESH::GetHypothesisData( hypType() ); item.myName = tr( "SMESH_NAME" ); - item.myValue = data ? data->Label : QString(); + item.myValue = data ? hypName() : QString(); p.append( item ); customWidgets()->append(0); } @@ -615,7 +615,7 @@ bool StdMeshersGUI_StdHypothesisCreator::stdParams( ListOfStdParams& p ) const item.myName = tr( "SMESH_LAYERS_DISTRIBUTION" ); p.append( item ); customWidgets()->append - ( new StdMeshersGUI_LayerDistributionParamWdg( h->GetLayerDistribution(), dlg())); + ( new StdMeshersGUI_LayerDistributionParamWdg( h->GetLayerDistribution(), hypName(), dlg())); } else if( hypType()=="ProjectionSource1D" ) { -- 2.30.2