From 2de294b09ac8b9ace071a01db9cb4e235f1eadbb Mon Sep 17 00:00:00 2001 From: inv Date: Fri, 24 Dec 2010 08:18:34 +0000 Subject: [PATCH] Merge from V6_2_BR 23/12/2010 --- Makefile.am | 2 +- configure.ac | 4 + doc/docutils/Makefile.am | 7 +- doc/docutils/{conf.py => conf.py.in} | 4 +- .../SMESH/images/bare_border_faces_smpl.png | Bin 0 -> 9095 bytes .../SMESH/images/bare_border_volumes_smpl.png | Bin 0 -> 7555 bytes .../gui/SMESH/images/controls_popup.png | Bin 0 -> 1900 bytes doc/salome/gui/SMESH/images/copy_mesh_dlg.png | Bin 0 -> 24617 bytes .../gui/SMESH/images/copy_mesh_icon.png | Bin 0 -> 1117 bytes .../SMESH/images/over_constrained_faces.png | Bin 0 -> 6599 bytes .../SMESH/images/over_constrained_volumes.png | Bin 0 -> 8184 bytes .../gui/SMESH/images/scalar_bar_dlg.png | Bin 0 -> 22098 bytes doc/salome/gui/SMESH/input/about_meshes.doc | 3 + .../SMESH/input/about_quality_controls.doc | 23 +- .../gui/SMESH/input/bare_border_face.doc | 15 + .../gui/SMESH/input/bare_border_volumes.doc | 15 + doc/salome/gui/SMESH/input/copy_mesh.doc | 56 ++ .../SMESH/input/over_constrained_faces.doc | 14 + .../SMESH/input/over_constrained_volumes.doc | 14 + .../gui/SMESH/input/projection_algos.doc | 35 +- doc/salome/gui/SMESH/input/scalar_bar.doc | 40 + .../SMESH/input/selection_filter_library.doc | 16 +- .../gui/SMESH/input/tui_creating_meshes.doc | 44 + doc/salome/gui/SMESH/input/tui_filters.doc | 104 ++- .../gui/SMESH/input/tui_quality_controls.doc | 84 ++ idl/SMESH_Filter.idl | 35 +- idl/SMESH_Gen.idl | 68 +- resources/Makefile.am | 5 + resources/bare_border_face.png | Bin 0 -> 3168 bytes resources/bare_border_volume.png | Bin 0 -> 3369 bytes resources/copy_mesh.png | Bin 0 -> 1117 bytes resources/over_constrained_face.png | Bin 0 -> 3329 bytes resources/over_constrained_volume.png | Bin 0 -> 3444 bytes src/Controls/SMESH_Controls.cxx | 149 +++- src/Controls/SMESH_ControlsDef.hxx | 75 +- src/OBJECT/SMESH_Actor.cxx | 92 ++- src/OBJECT/SMESH_Actor.h | 4 +- src/OBJECT/SMESH_ActorDef.h | 2 + src/OBJECT/SMESH_DeviceActor.cxx | 33 +- src/OBJECT/SMESH_PreviewActorsCollection.cxx | 2 +- src/SMDS/SMDS_MeshElement.cxx | 15 +- src/SMDS/SMDS_MeshElement.hxx | 1 + src/SMDS/SMDS_MeshNode.cxx | 14 +- src/SMDS/SMDS_MeshNode.hxx | 1 + src/SMDS/SMDS_VtkEdge.cxx | 2 +- src/SMDS/SMDS_VtkFace.cxx | 8 +- src/SMDS/SMDS_VtkFace.hxx | 2 +- src/SMDS/SMDS_VtkVolume.cxx | 3 +- src/SMESH/Makefile.am | 1 + src/SMESH/SMESH_Mesh.cxx | 31 +- src/SMESH/SMESH_Mesh.hxx | 2 +- src/SMESH/SMESH_MeshEditor.cxx | 141 ++-- src/SMESH/SMESH_subMesh.cxx | 2 +- src/SMESH/SMESH_subMesh.hxx | 2 +- src/SMESHFiltersSelection/SMESH_Type.h | 4 +- .../SMESH_TypeFilter.cxx | 6 + src/SMESHGUI/Makefile.am | 3 + src/SMESHGUI/SMESHGUI.cxx | 178 +++- src/SMESHGUI/SMESHGUI_ClippingDlg.cxx | 30 +- src/SMESHGUI/SMESHGUI_CopyMeshDlg.cxx | 667 +++++++++++++++ src/SMESHGUI/SMESHGUI_CopyMeshDlg.h | 125 +++ src/SMESHGUI/SMESHGUI_FilterDlg.cxx | 68 +- src/SMESHGUI/SMESHGUI_Hypotheses.cxx | 4 +- src/SMESHGUI/SMESHGUI_MeshInfo.cxx | 777 ++++++++++-------- src/SMESHGUI/SMESHGUI_MeshInfo.h | 43 +- .../SMESHGUI_Preferences_ScalarBarDlg.cxx | 49 +- src/SMESHGUI/SMESHGUI_Utils.cxx | 2 +- src/SMESHGUI/SMESH_images.ts | 24 + src/SMESHGUI/SMESH_msg_en.ts | 120 ++- src/SMESHGUI/SMESH_msg_fr.ts | 625 +++++++++++++- src/SMESH_I/SMESH_2smeshpy.cxx | 29 +- src/SMESH_I/SMESH_DumpPython.cxx | 81 +- src/SMESH_I/SMESH_Filter_i.cxx | 182 +++- src/SMESH_I/SMESH_Filter_i.hxx | 59 +- src/SMESH_I/SMESH_Gen_i.cxx | 233 +++++- src/SMESH_I/SMESH_Gen_i.hxx | 6 + src/SMESH_I/SMESH_MeshEditor_i.cxx | 37 +- src/SMESH_SWIG/ex19_sphereINcube.py | 35 +- src/SMESH_SWIG/smeshDC.py | 370 +++++---- src/StdMeshers/StdMeshers_Import_1D.cxx | 432 ++++++---- src/StdMeshers/StdMeshers_Import_1D2D.cxx | 19 +- src/StdMeshers/StdMeshers_ProjectionUtils.cxx | 28 +- .../StdMeshers_QuadToTriaAdaptor.cxx | 50 +- 83 files changed, 4370 insertions(+), 1086 deletions(-) rename doc/docutils/{conf.py => conf.py.in} (99%) create mode 100644 doc/salome/gui/SMESH/images/bare_border_faces_smpl.png create mode 100644 doc/salome/gui/SMESH/images/bare_border_volumes_smpl.png create mode 100755 doc/salome/gui/SMESH/images/controls_popup.png create mode 100644 doc/salome/gui/SMESH/images/copy_mesh_dlg.png create mode 100644 doc/salome/gui/SMESH/images/copy_mesh_icon.png create mode 100644 doc/salome/gui/SMESH/images/over_constrained_faces.png create mode 100644 doc/salome/gui/SMESH/images/over_constrained_volumes.png create mode 100755 doc/salome/gui/SMESH/images/scalar_bar_dlg.png create mode 100644 doc/salome/gui/SMESH/input/bare_border_face.doc create mode 100644 doc/salome/gui/SMESH/input/bare_border_volumes.doc create mode 100644 doc/salome/gui/SMESH/input/copy_mesh.doc create mode 100644 doc/salome/gui/SMESH/input/over_constrained_faces.doc create mode 100644 doc/salome/gui/SMESH/input/over_constrained_volumes.doc create mode 100755 doc/salome/gui/SMESH/input/scalar_bar.doc create mode 100644 resources/bare_border_face.png create mode 100644 resources/bare_border_volume.png create mode 100644 resources/copy_mesh.png create mode 100644 resources/over_constrained_face.png create mode 100644 resources/over_constrained_volume.png create mode 100644 src/SMESHGUI/SMESHGUI_CopyMeshDlg.cxx create mode 100644 src/SMESHGUI/SMESHGUI_CopyMeshDlg.h diff --git a/Makefile.am b/Makefile.am index 8b479765a..b37435467 100644 --- a/Makefile.am +++ b/Makefile.am @@ -41,7 +41,7 @@ SUBDIRS = idl adm_local resources src doc bin DIST_SUBDIRS = idl adm_local resources src doc bin -DISTCLEANFILES = a.out aclocal.m4 configure local-install.sh +DISTCLEANFILES = a.out aclocal.m4 configure local-install.sh hack_libtool salomeinclude_DATA = SMESH_version.h diff --git a/configure.ac b/configure.ac index bd1705160..9fd33f5ca 100644 --- a/configure.ac +++ b/configure.ac @@ -444,6 +444,9 @@ sed -i "s%^CC=\"\(.*\)\"%hack_libtool (){ \n\ $(pwd)/hack_libtool \1 \"\$[@]\" \n\ }\n\ CC=\"hack_libtool\"%g" libtool +sed -i "s%\(\s*\)for searchdir in \$newlib_search_path \$lib_search_path \$sys_lib_search_path \$shlib_search_path; do%\1searchdirs=\"\$newlib_search_path \$lib_search_path \$sys_lib_search_path \$shlib_search_path\"\n\1for searchdir in \$searchdirs; do%g" libtool +sed -i "s%\(\s*\)searchdirs=\"\$newlib_search_path \$lib_search_path \(.*\)\"%\1searchdirs=\"\$newlib_search_path \$lib_search_path\"\n\1sss_beg=\"\"\n\1sss_end=\"\2\"%g" libtool +sed -i "s%\(\s*\)\(for searchdir in \$searchdirs; do\)%\1for sss in \$searchdirs; do\n\1 if ! test -d \$sss; then continue; fi\n\1 ssss=\$(cd \$sss; pwd)\n\1 if test \"\$ssss\" != \"\" \&\& test -d \$ssss; then\n\1 case \$ssss in\n\1 /usr/lib | /usr/lib64 ) ;;\n\1 * ) sss_beg=\"\$sss_beg \$ssss\" ;;\n\1 esac\n\1 fi\n\1done\n\1searchdirs=\"\$sss_beg \$sss_end\"\n\1\2%g" libtool ],[]) # This list is initiated using autoscan and must be updated manually @@ -460,6 +463,7 @@ AC_OUTPUT([ \ SMESH_version.h \ doc/Makefile \ doc/docutils/Makefile \ + doc/docutils/conf.py \ doc/salome/Makefile \ doc/salome/gui/Makefile \ doc/salome/gui/SMESH/Makefile \ diff --git a/doc/docutils/Makefile.am b/doc/docutils/Makefile.am index 867fd0a30..573f4a4f0 100644 --- a/doc/docutils/Makefile.am +++ b/doc/docutils/Makefile.am @@ -47,7 +47,7 @@ htm: mkdir -p html doctrees PYTHONPATH=$(SPHINX_PYTHONPATH):${PYTHONPATH} \ LD_LIBRARY_PATH=$(SPHINX_LD_LIBRARY_PATH):${LD_LIBRARY_PATH} \ - $(SPHINXBUILD) -W -b html $(ALLSPHINXOPTS) html + $(SPHINXBUILD) -c $(top_builddir)/doc/docutils -W -b html $(ALLSPHINXOPTS) html @echo @echo "Build finished. The HTML pages are in html." @@ -55,7 +55,7 @@ latex: mkdir -p latex doctrees PYTHONPATH=$(SPHINX_PYTHONPATH):${PYTHONPATH} \ LD_LIBRARY_PATH=$(SPHINX_LD_LIBRARY_PATH):${LD_LIBRARY_PATH} \ - $(SPHINXBUILD) -W -b latex $(ALLSPHINXOPTS) latex + $(SPHINXBUILD) -c $(top_builddir)/doc/docutils -W -b latex $(ALLSPHINXOPTS) latex @echo @echo "Build finished; the LaTeX files are in latex." @echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \ @@ -71,9 +71,6 @@ RSTFILES= \ EXTRA_DIST+= $(RSTFILES) -EXTRA_DIST+= \ - conf.py - install-data-local: html/index.html test -z $(pydocdir) || mkdir -p $(DESTDIR)$(pydocdir) if test -d "html"; then b=; else b="$(srcdir)/"; fi; \ diff --git a/doc/docutils/conf.py b/doc/docutils/conf.py.in similarity index 99% rename from doc/docutils/conf.py rename to doc/docutils/conf.py.in index aebd4b163..b2bb21f71 100644 --- a/doc/docutils/conf.py +++ b/doc/docutils/conf.py.in @@ -54,9 +54,9 @@ copyright = '2010 EDF R&D' # built documents. # # The short X.Y version. -version = '6.2.0' +version = '@VERSION@' # The full version, including alpha/beta/rc tags. -release = '6.2.0' +release = '@VERSION@' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/doc/salome/gui/SMESH/images/bare_border_faces_smpl.png b/doc/salome/gui/SMESH/images/bare_border_faces_smpl.png new file mode 100644 index 0000000000000000000000000000000000000000..6b7ead85ef02ab273a2decc40729602d0bf24254 GIT binary patch literal 9095 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 literal 0 HcmV?d00001 diff --git a/doc/salome/gui/SMESH/images/controls_popup.png b/doc/salome/gui/SMESH/images/controls_popup.png new file mode 100755 index 0000000000000000000000000000000000000000..b0bd01fb9aa0a7abf50480a84e69439a29d91b18 GIT binary patch literal 1900 zcmZ`)X*3&X7Y;pCRWX)PdoeY{l9sf-Dx*|uX%v+rRAZT_p_T@*HK;8gB^ZJ%YO7eP zsV0_`;B<^Nw%F5(jM}29t(bNwKGT`bv}fk~ao_vnzUQ9%-1|KDraD};Iwqk$z=cwzXyn+NVlh&3z}01*HAcN4(rh${jBhgEDW&7qN`k9y`zLWQ^MJ*^+^*w;6< zqt%qMODHTtifV4ysMOf`)wd6;bsy&0zR!?4AtNi9Ci;0%4$uo)z!Q5$wyS2-&6|m& zx%J3N1RNTnh?jwnK52u8@dm}q1^>eE$M=s}xxJ!`-Jam6zeuO% zGD9@3XKqQw#NL5!cDWiYs}qKEi9SBwSU8AEx+tf~j6N3@1D?><2czlrD!npK#jDaW z=YlNysqZzd^NxY&qgbyIg!1`B({JDHc#L>^INC3$Hjtn+V|lxgN0^pPGcz+Qr7BoD z{#Lf_NC3MI!mnx6P5QYJYT$7wn&Yt5U$0VSfpxDVpHdLNsQe%q8gkCsS=z%ddn>Ou zUPniFQs;$y31<6*kHLB<(8m1ZY(B&Fd3VC3!}SmK-e?J2Zwhx>R9rJO!+EwD(>wU% z0YlSH!^*o}s2EOk^(n9pD}3QBhdm%=O2i1${AP5T2l^a3X*q`>6L_Jn$g>N9)G|JV zJ4GL?3M-5f^D;TQT9xoz*UfqYCZBP$Q9u7^5j2!o%<8QH9X(yOoE*q-j5fqr$yqycLcvqQekW$ugs)|Ms|V5M!l z{mHHS*JGnMrY=yldz{x$*?i(AhyX%B`N1X|S{p$m6`meGSV$H@!0bpLkwK?s(nW2BkkuQIleuCINK<2CyJ_Wb5hrSKkUoA5<{ z{#M?5u2#!_2q37S+zsam{{P^a$r6h3u~$ZZ^z%qODwN$doIpPC+-+s@L+6hoBaCn{}RAKhOxw(BK+2U@LFyhZ)s#!&b* z1l+B9ztr7{mDG0;oyD7XH975j22C&1#8WypbryTNEA||YAA4p_Y03QBD(720HRNL} zh3|4)lNgLCWt@#mcn+2`R(lte+jS@C?37noewMBO6~v@=@P+ByswvYK6?Ozo=(#%-oZBt0^%@ZdvEC}KjQ<4uuXXWLjge%*masT&8c+iLXZYia z11=yL&YQbUqyGgNMZ3ai^~H-`DUcXrSIbB06?7RZJ~ig_GMUTcebt%g!W(O3RxRA% z(&V~0tfR6XxaPTzo);~{ka7K`$^Mc1;$=MNex!3gLxlKVf^!3Ghhfb_ZB+EKi;SoS9dj1aB>3)lJ4PK1M)cQ+(PchdK5{^8 zZ|=+J=h^?VGe4@qI>0f8jY8tfiyVPzZiAFNlSxyhwe`i1v=gsbk>fbVg}!PTWVrn= zyh&Sj(@)7zX%^w;T%{2tSau^XG~$VA_;Ot=rzth#@hf=Z8FZvj1-?u2iMt#fy)SX^ zm6NCYVH6>1GmaCzOn#SaC^sIKzS9&Q5$`V?;IB}}y87!ab+@*l-CE=dJ3m5+`-5}h z_%kr9v${rfTN#5SjK#yH|2#gQ=9v|j34YmNS~R%0!G3BqC-t9e0#SyYAGTLrR)ey1 bep5}Ipqq<4t?NHHp8%UnS1loNIjF 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 literal 0 HcmV?d00001 diff --git a/doc/salome/gui/SMESH/images/copy_mesh_icon.png b/doc/salome/gui/SMESH/images/copy_mesh_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..263479f3bf79e868ee99d860c0c3b13ffb9b3d55 GIT binary patch literal 1117 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 literal 0 HcmV?d00001 diff --git a/doc/salome/gui/SMESH/images/over_constrained_volumes.png b/doc/salome/gui/SMESH/images/over_constrained_volumes.png new file mode 100644 index 0000000000000000000000000000000000000000..761144382c7140950b71a664885556b86018fd12 GIT binary patch literal 8184 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%0AgYRI zxHJpwJrEw{2NNSIV=u4XIR*RHtYAS7JNP-|Kpwo`GuLg9w=nzFLGeGKm~37OpIpdW zx2#oWpq-^oZOlD`6?^ThDn_B(Er6PA_Gu^s6Zr^vbwn!)Eb<>k)dmQi8uMB zN^@6UzfVqZ9Z!o?9l)Hz!%01v@fk{RSG%phzAS;t;=B$m(=L;U_JQo4x~8*F_QO1J z%6?P9tJ+IuXh}mnnjBqR*2}bDXzDcP+x+Y9m}E`svzsWxr_O^ZR^YdN`e=rSVSzhi z*xw+?J~CUOKV)igwVRX)7|f(v$f0?Y|AyUW&C#H$lXBz0y7>4cV^OkM1&`5Hp6blm zBeRwRlLfs^G(ZjZ*A!Ey1rw4}z!8sfB|_hsanv2Wtk;{P&95UZX3w`e+KMi66XKX@ zbuN5PUtgZi*$ap-IjKgs8V!3QT5qN5QRgR1!|q)mqJ|-P&ze0NT-Q#6JopB>^mcb< z-%fh;YeG^&)R*MY!`@}h&=pN=cY=sW;hS!Uwhi-8V1{JikW`i#3?;l8bb!^z;e zwR8!Eyn_Jr$J_%%Ntw?xOLWR3Q>_B~we)Ye&0V(`gyH7XYpArdqmH6ebQq z;obi`94=e3v@o7ni>3yt=j&q|2JqFORUvQDY`61d#sO(11;5v#oP~NFnYQOfQ}BMdMPkf!Mz_~c8S zdYi!h4uO3UEL?Ch;%lfe7L<8EKV)lb%fc`QJSq|P2`_vq2Ul)#aOLs_yx7X_XmyN` z3u7dLt5aNa?G-_Y%>B7WB8ZC%3#?|ILB?mxcE7L#nFOBBK?HLJS^h>LM%7>HKNsX? zgRzgmRU+WBv>T|&pyQ?s)JXo;8n*9|*3!fcU?yVS{pVy@MrqpV{FJAae%55meag<| zf<*AFe_n|V`6CdId*5Haarn6JWDhw<=i~&v{y46hMFmK*TqE9{id8>~1<2*Kg5gBz z#}$&D-qu~HtSI-v>AE8ckmxuqdgAJc2SEDb6EdHCS=F(AS8@t~&HYb|zHoW!0;{E6 zZ_Xb8ToJ>`yXsU0BHicsgZ{*x=E)u-SvCjxlL)l@G|so;4iXtmw=E3uw*5O{NhJfh z@ssyzP!7YIs^OC}jF_i~BA&B0N!lONJs%?_%Y=w(LNFj&b-X;E!1SL_k-#ZfNCg}K zUfq9Zat8adfLHUMS)9ciDE&;O+*_;TVVt6}5J0csll@cx?7sW;A8A=@t&W4;uR18W zD7UduyiG?Akh$(0E^B1WR^3ZWO)Y>{uU#1zH>;60=_TeJzmxfQhJGZQunw; zs4JCHyRL`o5HO8;TP7}+nZ8&t0R-BJ;RXLKdc|9xcbDdBSdj4~bwThw1+C}wP4a`- z?gfeLz;Eu^6Q*X|VgW1O@Sa=TaANnkS)lund}8;J@{CD>)b9>FrwZ%pFKvxD+V5`% zY>n;8m~k17akwTU2H<)Xt0lOO1Jf#lc-|NM5PBdJxwhm0B>slNw7%1~Ic3XF;R!Df zR(x^-R}OuHDiz)+-6%3BY0lgIf|bvfG#W$R(#w0DSFWr2OEemJ0hG&s+=t?zeN})| zzLL$^XY@$KgsfkkZl~K?EH~;2R9J9G3{j3u*!a#%G%2ANX^oj$-9c>icd0>+v@r(8 z!SBzo@R=PKM%}%|Vbp%nB;Q3#d$q~er25ytF?4fnYQAvJH3^W%QqxVF8S+Uzw4ZDE; zFp$@qV(FYCasD>*eooE$J~`DkO^_S9!N5KAYOkM!QIH964e9IIQ|e3`8z*ZdbIvs)}s$0 z0@58Ixeon_d4zmLuKgsDtlw|2S;uvh0vP2Rt&2Gq4riVIPEy|86Os4+a05Yh0hngO zbaVhPJa}HNKt-I%bP1=(Vql%K^8b~4Z2XY1ap~SuOZ|V$TJTBk(P!X&{u7In4c@+RFpkhx+ju;QA{a4{U_HkTfm!fi%_pIM<)750!y@-e_<|0S2X|Jc}V9T^W;6_LW{xC^2Cp^{1+ze*eIrzCX;|Dr`@q zx!)W@gQLQHBzN`oHSO>3FNlaBud1wkV`^%OSzboh-~aLO4h&|No}NzZ@{20KwNsp& zoL&XIVIUJfZaT}EO}(y}Aj7-P#l`hAt2IchNC0AgCckd9`+}jVuEc^FCZY;RM=CJC z{Vjm4T21l^je#?EyT6D`3Qlh)l?LDFb`#CcxQ@ERESj+QIw`y#AF0gyJ_xj)`!1IF zunux!5+W8?fYhd*Q{4Et=KIRugquK675hvvT?x?a2f|Fb(ugIUWj7c;?chM|;6URI zuVPnA^{!`=Q;d^A0I<^R7kdQiGmvt>Bp`zrR2ihnSENsbLUM$a)_uAx3u1+#0 zNx}?Mqj`!$$55R-(#6@3SpJ>?AW>#+6=;TVkCLAtr4HCW$qH6$KQ?v(k zf6iPA+0$K6Sb{k)+8RAKEV-~rnc!!k*zKU}FRvK6WOnpzZZP+qswmQ%I+EI-VZ;Yx zt7NctfTqH>+a|MPh$+*uI+@X-1|VfRHa?}y{{1f&-4b6}3|)A;lQOb3koh{bg*^^o<3?D0`?fpsHtwCB9hzFz-uJ@|-o9hZ*lYSbCOcWyF8 z*Ba4iAn~O+WUsAWqM8r#l^q7v+@jV5hCq|3QYONv;qKv~w>w$7ifHzZKfnLIjdW+W zn`H+`l1mFJN_TA+B0}y=J^8{jsiLC4+o!TUc|jyp0Fv#wF}KZlG6f3rfO#-JQl9I) zN%*xfW9FZ2nsxnXEqv!TRU&;=)5A;Q8lou;o1>>XO(xAk7i*hd(e%fx`V{OORI9v9 zP8Ko1b(?mrVWIG&&KG8-~n+))bqd?ZQC=1X-uhcQ-2ZREGlSGDr#9$8aZV&E~^*kU6BF9En zbUx}53CXF(sn(lX%4lL2aDdnlQ+dNJEz@GfMfK%+dD42ykwT~mQamDHO6qzarD4y$ zsX zo>L0UZg>auS@FmxQ;JvztyXorPe=)@M~XsBem&D`wo_(@3p*8|&fU#gUiH zIK(6pKlO-5%I+^4K!4O#Ggf#6m|F&y&)E)`BFqIKrNE@1cM&N|P`M)&m(u%se)Ho# zuCzt9tW2WiT%iC2Av>jk3J!U`%qzwsn++ZRaZoCpL+2BNc_we-AR+`^ zeg!+Z^RhRF{hCs~9GF7pvl_pJPs7s4+p_?A>L<)8;IkvRjsO%YeWYtbK(c6EiSv`N zekXB2V76MxD?tt24666pX*>8%F3$d3@wmfaK>!jE{&d8s`BG1^U~SK`mi2XDJBbFj zJvflpKM&dWmyXy`M=;Ph>-l~CbXC+8vUAQN!#9Mm$n}F%t6l7+=70bMYp%b6AVc#E zml&Ren8Su&R&l8UCzqOr4De|Z#e_gsUn4Z@S0+(1G}pA|eKxPLy~$AN6P+O*`s()y z2Q@LY$8@Fhq+)^)ps^U=zHj+VECNpEItvm)K2Pidf|H_0sy8e`W$D_>pkVLVolna> z9=-MF1Rw(J`SlQp)KyVC33qbR)e{0}5ptbY#A8saOtL!D^bY`(2k*SqVjpI#4rBSv-RTJZtAgfP^3r zL9x*a-MC5-4H}VwrFIOtfj!YY7LRI#d*Kv-grsO@-%N9hkf(MtBugAV5>S|^=OV&? z1H$PB$$`Dge1ZgAX%9C5SK5qVo9gzYO7fN`zCNeEaJG2-rUs4Xz}!a+sgAwFzYJ;L zheOj#=e>?V~N zXOleE(CnGb7cm*R_A~0)uSjyhnaHgxZuO7Po-OgM zcxX3o+2PVnD}CJ&RWlV1fJT1VUvXem==#e z0-Vq>ltFy1;+p+HxB`>SV-B0Uvft!vQMZus3>%Wnp#=J~Q7rnC?cHLuYQS*Jkwg4f zil^F~cY&NISxOEC#~6Ks9*5|O;Vdi!Fq|2s0!h-w=x`(UkjH)C4Ul6D<}zWn^ZAcg zt7Mx0Ybv+*mN-pO|FV(&pC@EQ1KR(;B#@&BoC#z~Q^oRJjm}iG4snF}rCfN{Ej0#c z0zVVZ}#?s8HE5uY~Y|}}AYGpv*Etq)e0Wk(Of2TCMzdHi`82H{<<5D;6MmaDUg<}v!- zmWwU5$7n89jN}8caKk)Z?WS4I>a7@XYUB8+M)7qSnGKICdG|eIq74pLR7&>BOqiN4 zxxdA=zfq@73_1UP@~dp-l^duP3zS>6ld@BfY6zM%!s!W|;>D#IA1fx&1iy67QL#_Q zX#J1wOwoFM?#*`1klf~!!S50?_6^#NXA{BQUjk*kT*VNh&QVqiCB)Nw%4-P zwA}o)h9c9ZfbNb9)m1Cn1#N&6D9^5pWODy#Qnvg652yz2;SyCjvuyTVoKdP%a4MxW zNY(QF+N*7U(r=O;NbX^`Lpj)*A*5g z70yAWKLEnlRFB(_EtKe+g1fhR;y#Io~8#LpnN29bJHth5O76UN% zw<9NswHi56U~sWk4oM9}JWmQGmVE41A&XbMnPD3JX)%z-)TxKK4>s8++K4+*8_7#e z<;+b8__kLw+n+jUVwSXfE1-hW7jHPug=68r5w<7`zVGo1mv91uL~}L(gUSF54r8aB z(pPrt#=iF?7?$XVo)&wkk*)sF?E?(dfwe&52W6P4-SOo|Gb@ z3gW2NTk1A zY_fm>c+$25@UL8rk_~@okhH}-TR6*WXx$!7Vq_SWBl&aW5t5%=TPYE5DcG0PZQha! z^5W;XOihs(kv+r#n2RcJZEy!KOG3~_{%HA>_2rCFC}I}+8z!5BzPLa z9-{5=w+!<0c=l%W{m;S=c}~1V6nqdprCS!~PJCmJ0XI;GwEd>CA+VPJT|^)|X*=N0 zDc>n6@&{j>qO&cgqlkxs*!I7jM8f|cv`lSPK^#;91s|tL6`fxSVafOI^V*}NN~w%* zA`iZQqg?*>P4SAnTHgGbdFvW}A1w8jfr zOg-|$1rgteM_&8BVk-g=PNMMP%dbyMOY7?5qE%c}l#j)lz<<0auWD{Ck&~0d%+CwE zoR>Q-f*>3QT4PmCd(%?A>ZQ{1&+afv5uIAiu?z=d!BWwQt{(g6l zmZ_ebn_EKC(C%*a*y!l(hK2@LPfvr@_4Nb_J5sNqNJd_zgs7q9=53*!s#1g=;)oZ4 z;5Te;^bTGDk>h7JafTzBs7o}7?yKF^S?qZ_$x;OpW+l20ll6g=p=onsnzS+H!r^YQ zE0@<0VBTqpcgUFZpLy23tQ9i1?;N`3j2&;;*mZacs2U?9#FY7Sm+b z3I4TDmx!uFqBumg6F;w9nf^Q+ksgrD`29?Os{S)tM46|LoC4Cj|5BlQM^%y;h4GqN z_bwnE%p#)z?IDElXgEQH#f#`znMJI?e)oFs6z7){;lYFqZQOZXBLD5mcwa*>Nz2`V z2d?ypa!>EaV8`HFuL=@e{qMIM%e%^FD-`UPg^g5a1xykYPJ!66GWZ~? z;HBc&p=ySO* z&M^5??|#Yi`r?+=zVTl1n!R&OJ^>gj9>vh3oneugl^*G?x3^K~cb+r}ZdV-fH@80L zK7LMq;1K#8G-oN3RQ_tS7}c%?_*-f_?q4`>A4qr~;LN<%hfQeQn@gI}BS%+qhhw@q zR~RGxDsq8Q+(NqIemu6?;fH*9&^~g(u(`S?S>v+9j$kR^Kq*0k=cdb_1lsWKUO$w# z4Smk2_29=&&$iQsF$g#dZ4A@l{`Ox|5vwOLX`fkfr9!6zr7upUftK%u0YLEth+>^fOe8HfZl6J zc0Hpzo|yl+r4OOO6XR6;d5yDi^zB+cvCi1yik#U&kGu@IypljdN{}wD{3+OxIlrD1 zT=&|O)|rl2B^DMA(4VeWnSbnPOihX|{8u{Vw=kW0RW|7HssG9Z^^m<)d8zfDf{&uJ zo}0mJO&BIj^65 zz%p7EY=4ZB0^(fFNt_e?haV#$I}8Senw*icg5YpCS9|;G9{29WpMyP zaT&Y~;5I_-VLkAA@-skJvBOGrs&Gldy1!QG8T_YQRBzI*|IIq@BA0wB?m@)* zKg^I?q-98jr4NyenOYiJA(E;MqVId$ zhM3d#o>aNlvX?YdJD#Pt%70>+aK8Oi(B6A0S)yk#vs?8{53VqL=HB?%vL^~lKl(q+I1EhNho;ZXu1f)m zo?((wv`(?X3Pu?J>xSxEqazgKE~O+Sko=YM4;HTEpDAtaR^5v;&Gsd3`x&Mb4*~)L zHX)Ay47!?!lP@tK(`wgh_1~E8m_;nUaHuFQ(@a)8cB$@ag;poZTvbr`81GG!*k2K6 zWU0{~T%u&PZ)9q$I8t-;e#g3oacz9gdS#pv|C&j3_42OUt#))q#n#(CK}YZ$A;Ene zKrWuB+5p`Af`R{4padlkFdgVm;t8V**8(E9XPmEl6h2)7+=&%$#6fd+G9xrZwM7h(Z3KH6*B&-x%9oFu>3^CEXfvWd=Rb47-@2XnDHU3q0a6E3` zlu2~__UgpLPd%a$>!-IbSh?&{nFHp3LDO%_9oYe+7|&?$*aG0Qb!I?0;i7Fx)@+k>>A686h}@SPkEO(7@bHlsR0{rz z0+0AKx^@L`6Uquoy7U?+z^Fe~@?rZnes*K&b!qXY5cMozkQxRIEy>~#kFxYj-RK~X zk@fHa-%<-2eE9x3W9Y&X`rPkE4NnV#BMd~fzQ@hI*g^mbxz4AT(ybx952}OuPnLPe znQYu`%j#ca@HcX9XGD^+UwnLVa5}%5Ol(KSXT&pMz!xVKfdDekuF2b{hNb=;mQN*I zMCeJMoJvz&*I6l3So+&&mlOqM8r3E;H&F=lqgyjTpl})3SaIzw#^GkGjr7xv%&vy^ zU408r)j(aMHl8?z`u4ddLY9K4gSGy|QCj%@y%%>H{ZUS{Y5@Y2g~r#cU#<~{OF~))*a1dpY%YO*SO5MV%6wMz zZQhC?4i26_J%Ded{J3KuN5!{)Y}Fx^#L~fYT&vQAhET7~n#L@^#Iy|a88pt1J8|>7 z&^-``4c%PAW{B8lD`1+X2OCjtlBZ)QpL zIAVC6NerZ;g^Z|fwP&DEViRpD7C{cz6xYWPZSgu{1BCUJ2FkgH)C< z%5Fuxm|CXVgKtvKYJ7J~53GjaRlTaFxrmZHHiW?jAB2od;}nIqGtf(Xkp3N_Ll6I+ zxTgWwvyvHvIm|xWGOcsV?o4}ht8t*sE5t={I#w~rf$HrTg^79ujtx1qm!thlII?-% zCNzO;`q2!_p{MGs zK#5N9ypr8%)=nMixongenNz|k>Pw#V<@7;w@8y>HN)b3yK0wgwZEVB=>UZ6n{v10| z1l#<0P%paUtkkMejpC4qn%qCePqgwyJKLwys9-Kk<7%fMKKEIf^C$LQE$$N7 z#pIcjb0if^DSh6Nvb~N)9EH^!fX{Y&@pBniY$luPr9rK`OoCG1WfPF&RJ)toyZoAT zaI3$sy|aJkfDA?Z8Qy=^zogM1hmh`}p|FWsuj?mO$$;JUS3yF`hEK+DMbtU?D7@0b zk89QAjx+VlXeFabkHPpa(=xrxM*DJSF$7cg;lIjUKGP<0=s)Ua&%^Jn7Xlk}ry zXBGGbzD3^N=bWrn{9)m#UhlBiW^+&Cr7Y-fXwi(D=Q<|SKX*iAHnhM#b==dal&dFs zXz$!`G?p(U06(z$+ixi(H}1iOF$z{frAmkxWn`&^W?g_tfsIae|2R*D$?QhUUmjg_ zRk3GC-wGDDS1cX90j&dtnBakeNsrq#R_WCja`mQ@|2DUN$tM>FEWw-IBFm9#hqlIV zw%rFG^{cXbD@;ARRxl_MY!cfrHs=;sDD9ziyQCgEQ-J4}uw}~2m?`KIzPzhynN~m5Fr zPN&45m}|c*0=`S{p*G!nBOP?M*E|{S_2pPql(OL|c%xHHchI=7f?C0(>GlQU*x{z6eO-Ac2(r8zrpbye$VI(rFxC8Pa0nmR0a+cu(H!ru@OA)bq&) zGgY}l$)iRpW7tfplI=UicOGZYb|rf0%%Qf+Dr@dSeak(vrq76h<|=IaB5?;EF{dMH zwYax1!F6UP)5*YZ2wXm?ml7)r_yiJqmaMPs?Lmr_0WZa>?e5BC?U-J$UwBB^>58Dj z^ek(iR1g`9s4}{eJ6m-A6#Y5xDqoK|k#OD&)$en!K{O0)wI`MQ{Weq*Xyg zMPq1c03!^eRrZnu1cO8n5D3tKQMQyp2B8p^hBbl&j5u^9Ji}IEqfd+Bhx|k-8A( z{@^WeiDyZ5%2gZ@G~?{VEA0kwF>H-AK>++fCw$?0(&Vay^9rj<%pxy9Tm;KnqaM?+ z*qd0||CKg{zE);J@{(>07gLCoRe#3mnG27s@PGZsAdOw$KAl~9PelsTnz14D)KczO zQMHbyuL47KppUX6IiSZQoxRR%5A?9Y=@K+fGnj>mQj=b+v8k=yG~*V^ENfj%2!NzxE0`<=%zW?F?l)AH zo%4Bs6;nWk++VBQT3(ju!a0<%?Q5u()n5NtTJsN0@tVN!5V14O&`aE~X^rnpY>@Y> zKu?f?0lhRIWndm|l&K2f4jNhAY&crlBhf4N5_qFK6A+O;6IKP>wuv$gC9eyGzI~MN z?NH12Vz?#IT?{AN*2OlmqlnwPM7WBjKt zpOX&(=wHZzZ<&?70Qrd7#kuI^QPEoZFKMXKKHDdr!n^5O7|w{Z!*SAE<2<|LYm22=NJlM|j`P3{{Ig?6yg-(P;;(H)+j z!78$oH+EXd(5cVtwPf_gpXlZuhKOqQVy7~Lu9?Xe#qa#KR;+VblyC4(CF4g(IFQs$ z$6Vi{e4yB7{*hpM)wo{T^*H4pHs(o<3-6y|eJf}*S|=y)HDjDKQosu9vaS_sFvn*X z4)!*%Nq!RibTh%L5LEK_um#enioT|;_mj6(pA$qf+^I=v@-xTjJdP~PvAK^VZ*mQ~ zR~LmH$e{|h5-gJ(g`Qcq$T3haXF)cib~wGblTP-H4N&X3vm~3cRCpkrI|>I18s}7N zv9`6vH1AFRe0V0zJhDxQo4t*bw(B)=$ejt#Nbw^;ifZO-MsDIkf_AIIl<1SXgXipA zcH;aKj-IAYuTfAbtDJZjP#bt)!c4O-JUk;ySVPi6Rt-8_b8xG({y( zPVr3kzq>j+Xc^3}YD2;!A$x3BqB+r~wLjcC>`*Jr_A`-?ytVVC7s7nM23kGON>7yd z-!xA27`iY>Ue@ox(=X*tYBkU#e!r31kT%&PJ2?oN+=Bxm{^;G2geN1dgy7daNE4ef zLpaeDb>9g5z{{n6?MsS3GAv4dX=t$Ap;uiwTU8*~C!8nu9P6zZ8*Ns}&>#}AaAznH zy8y|@u^r5=W{wsW{;Bd}~+x&`%X4S?9$&0)LLN!+BzTx(xiUnD8 z`B5Zy52-(VswZ;riv~abA&+@QeJrFMxluPx;)LJh<#!z)ZF1i-%VDW7qq~w1a>U*9 zXsKxQhEhcGcL)_RU$LOw7rO92ew3-H?sa^3{>%fkA`re`|>;pBT3!|hEZe6$v(n(NY)-*T$E`Scvn zjeIjXYCtv)16QNO(AXW)@?%51SaU_i2d#jvZEVk8^`QfL*1?4gsvy)Twdg)%L?v&+ zAs|2-F%jJ~g0nGmCn-mH&U9jp>O27KgT*|f+2Un(*|qRzcowtQIDScWlH6>zWM;zp znz|-A(PQ8gF?d}^_rtjC*UNSW+(68|@yM`du7^&nUqd{k?VieT31X>Y(Dq^^vR83d zfW7KmHqglNo;W+|qjCU`hOX_-zmN>QKYh~K#EnoI!NTEMH7t5bmF1->;{uFUpP_9e zOX@In|9>v)p-|_OW0p+rb595Ml|dTtx9tXgv}({|hZiiVjdU}lx=JNHZ{jBQQ$7no zD4%j!j@G9wB%1u^7;@tLOo*7byBixmdPD!YLr=ov;OMvPAjvnIF=)x{MdOq$5Yqi1 z$H1U{Q|Rea6>JR^<>e*NV?YuJb=T_}sX8gXgCb2j`^2i2gZ@iP{pN_)N{4`t0|p3K zP*=qz`0)X$QbTiUtq@PJdQZ?V_U|rVBbFlX&~}Xll0a9*s+(3>x*g+I;$P!-+o-(- zb#v|tt6N%j+lBC4!0$%g;*r~&Xb^8%1>kSNy)O|`mGv}|jVCP8`8)s6VZ&eS3 z;nQ;|E(M2Bn!+0UAX@_+P}o!s!)KuR@$L?Ajj`5P0QEy;Rk)#+znh#(AWT9vc6MCt zw=G(LyX5@Ci<;*;wF~O-2SH+duj{YLD{=F;l%%3#M4e4X;@9)CX*+u_ra)Y!IlEm6 z;6}a7B6qpXj(H4_&-L#wYR5}y46VqXN literal 0 HcmV?d00001 diff --git a/doc/salome/gui/SMESH/input/about_meshes.doc b/doc/salome/gui/SMESH/input/about_meshes.doc index 8a81c7ea0..c79f26644 100644 --- a/doc/salome/gui/SMESH/input/about_meshes.doc +++ b/doc/salome/gui/SMESH/input/about_meshes.doc @@ -16,6 +16,9 @@ for example, a face. Several created meshes can be \subpage building_compounds_page "combined into mesh compounds". +The whole mesh or it's part can be \subpage copy_mesh_page "copied" +into another mesh. + All created meshes and submeshes can be \subpage editing_meshes_page "edited". Meshes can be also edited using the MESH functions destined for diff --git a/doc/salome/gui/SMESH/input/about_quality_controls.doc b/doc/salome/gui/SMESH/input/about_quality_controls.doc index 8f78c38c5..ee57c8c81 100644 --- a/doc/salome/gui/SMESH/input/about_quality_controls.doc +++ b/doc/salome/gui/SMESH/input/about_quality_controls.doc @@ -32,6 +32,8 @@ Edge quality controls: Face quality controls:
  • \subpage free_faces_page "Free faces"
  • +
  • \subpage bare_border_faces_page "Bare border faces"
  • +
  • \subpage over_constrained_faces_page "Over-constrained faces"
  • \subpage length_2d_page "Length 2D"
  • \subpage borders_at_multi_connection_2d_page "Borders at multi-connection 2D"
  • \subpage area_page "Area"
  • @@ -40,14 +42,31 @@ Face quality controls:
  • \subpage minimum_angle_page "Minimum angle"
  • \subpage warping_page "Warping"
  • \subpage skew_page "Skew"
  • -
  • \subpage max_element_length_2d_page "Max element length 2D"
  • +
  • \subpage max_element_length_2d_page "Element Diameter 2D"
Volume quality controls:
  • \subpage aspect_ratio_3d_page "Aspect ratio 3D"
  • \subpage volume_page "Volume"
  • -
  • \subpage max_element_length_3d_page "Max element length 3D"
  • +
  • \subpage max_element_length_3d_page "Element Diameter 3D"
  • +
  • \subpage bare_border_volumes_page "Bare border volumes"
  • +
  • \subpage over_constrained_volumes_page "Over-constrained volumes"
+To manage the quality controls call pop-up in the VTK viewer and select "Controls" sub-menu +\image html controls_popup.png + +
    +
  • Reset switches off quality controls;
  • +
  • Node Controls provides access to the node quality controls;
  • +
  • Edge Controls provides access to the edge quality controls;
  • +
  • Face Controls provides access to the face quality controls;
  • +
  • Volume Controls provides access to the volume quality controls;
  • +
  • Scalar Bar Properties allows setting \subpage scalar_bar_dlg;
  • +
  • Export Distribution... allows saving the distribution of quality control values in the text file;
  • +
  • Show Distribution Shows/Hides the distribution histogram of the quality control values in the VTK Viewer.
  • +
+ + */ diff --git a/doc/salome/gui/SMESH/input/bare_border_face.doc b/doc/salome/gui/SMESH/input/bare_border_face.doc new file mode 100644 index 000000000..2115d3249 --- /dev/null +++ b/doc/salome/gui/SMESH/input/bare_border_face.doc @@ -0,0 +1,15 @@ +/*! + +\page bare_border_faces_page Bare border faces + +This mesh quality control highlights the faces having the border not +shared with other faces (free border) and missing an edge based on +nodes of the free border. The faces with bare border are shown with a +color different from the color of shared faces. + +\image html bare_border_faces_smpl.png + +\sa A sample TUI Script making a group of faces highlighted in the +picture is \ref tui_bare_border_faces "Bare border faces Control". + +*/ diff --git a/doc/salome/gui/SMESH/input/bare_border_volumes.doc b/doc/salome/gui/SMESH/input/bare_border_volumes.doc new file mode 100644 index 000000000..d0dd894ba --- /dev/null +++ b/doc/salome/gui/SMESH/input/bare_border_volumes.doc @@ -0,0 +1,15 @@ +/*! + +\page bare_border_volumes_page Bare border volumes + +This mesh quality control highlights the volumes having the border not +shared with other volumes (free border) and missing a face based on +nodes of the free border. The volumes with bare border are shown with a +color different from the color of shared volumes. + +\image html bare_border_volumes_smpl.png + +\sa A sample TUI Script making a group of volumes highlighted in the +picture is \ref tui_bare_border_volumes "Bare border volumes Control". + +*/ diff --git a/doc/salome/gui/SMESH/input/copy_mesh.doc b/doc/salome/gui/SMESH/input/copy_mesh.doc new file mode 100644 index 000000000..2c65ab8d0 --- /dev/null +++ b/doc/salome/gui/SMESH/input/copy_mesh.doc @@ -0,0 +1,56 @@ +/*! + +\page copy_mesh_page Copy Mesh + +\n A mesh can be created by copying a part of or the whole other mesh. + +To make a copy of a mesh: + +\par +From the \b Mesh menu select Copy Mesh or click "Copy Mesh" +button in the toolbar. + +\image html copy_mesh_icon.png +
"Copy Mesh" button
+ +\par +The following dialog box will appear: + +\image html copy_mesh_dlg.png + +\par +In the dialog: +
    +
  • specify the part of mesh to copy: + +
      +
    • Select the whole mesh, submesh or group by mouse activating +this checkbox; or
    • +
    • choose mesh elements with the mouse in the 3D Viewer. It is +possible to select a whole area with a mouse frame; or
    • +
    • input the Source Element IDs directly in this field. The +selected elements will be highlighted in the viewer; or
    • +
    • apply Filters. Set filter button allows to apply a filter +to the selection of elements. See more about filters in the \ref +selection_filter_library_page "Selection filter library" page.
    • +
    +
  • + +
  • specify the New Mesh Name;
  • + +
  • specify the conditions of copying: +
      +
    • activate Generate groups checkbox to copy the groups of +elements of the source mesh to the newly created mesh.
    • +
    • activate Preserve IDs of elements checkbox to keep +the IDs of new nodes and elements the same as the IDs of source nodes +and elements.
    • +
    +
  • + +
  • Click \b Apply or Apply and Close button to confirm the operation.
  • +
+ +See Also a sample +\ref tui_copy_mesh "TUI Example of mesh copying." +*/ diff --git a/doc/salome/gui/SMESH/input/over_constrained_faces.doc b/doc/salome/gui/SMESH/input/over_constrained_faces.doc new file mode 100644 index 000000000..26ad944f7 --- /dev/null +++ b/doc/salome/gui/SMESH/input/over_constrained_faces.doc @@ -0,0 +1,14 @@ +/*! + +\page over_constrained_faces_page Over-constrained faces + +\n This mesh quality control highlights faces sharing only one of its borders with other faces. + +\image html over_constrained_faces.png + +In this picture the over-constrained face is displayed in red. + +
See Also a sample TUI Script of a +\ref tui_over_constrained_faces "Over-constrained faces" filter. + +*/ diff --git a/doc/salome/gui/SMESH/input/over_constrained_volumes.doc b/doc/salome/gui/SMESH/input/over_constrained_volumes.doc new file mode 100644 index 000000000..1519e0ae6 --- /dev/null +++ b/doc/salome/gui/SMESH/input/over_constrained_volumes.doc @@ -0,0 +1,14 @@ +/*! + +\page over_constrained_volumes_page Over-constrained volumes + +\n This mesh quality control highlights volumes sharing only one of its borders with other volumes. + +\image html over_constrained_volumes.png + +In this picture the over-constrained volume is displayed in red. + +
See Also a sample TUI Script of a +\ref tui_over_constrained_volumes "Over-constrained volumes" filter. + +*/ \ No newline at end of file diff --git a/doc/salome/gui/SMESH/input/projection_algos.doc b/doc/salome/gui/SMESH/input/projection_algos.doc index ddd3bf708..07e7c343e 100644 --- a/doc/salome/gui/SMESH/input/projection_algos.doc +++ b/doc/salome/gui/SMESH/input/projection_algos.doc @@ -17,12 +17,13 @@ The following dialog box will appear: \image html projection_1d.png In this menu you can define the \b Name of the algorithm, the already -meshed source \b Edge and the \b Mesh (optional, use it if there are several -different meshes on the same edge). It could also be necessary to -define the orientation of edges, which is done by indicating the -Source Vertex being the first point of the Source Edge and the -Target Vertex being the first point of the created \b Edge. For -a group of edges, Source and Target vertices should be +meshed source \b Edge and the \b Mesh (It can be omitted only when +projecting a submesh on another one from the same global Mesh). +It could also be necessary to define the orientation of edges, +which is done by indicating the Source Vertex being the first point +of the Source Edge and the Target Vertex being the first point of +the created \b Edge. +For a group of edges, Source and Target vertices should be shared by only one edge of the group. If Source and Target vertices are specified, the elements of the group must be ajacent. @@ -42,17 +43,17 @@ following dialog box will appear: \image html projection_2d.png In this menu you can define the \b Name of the algorithm, the already -meshed source \b Face and the \b Mesh (optional, use it if there are several -different meshes on the same face). It could also be necessary to -define the orientation of mesh on the face, which is done by -indicating two Source Vertices, which belong to the same edge of the -source face, and two Target Vertices, which belong to the same edge of -the created \b Face. +meshed source \b Face and the \b Mesh (It can be omitted only when +projecting a submesh on another one from the same global Mesh). +It could also be necessary to define the orientation of mesh on the face +, which is done by indicating two Source Vertices, which belong +to the same edge of the source face, and two Target Vertices, which +belong to the same edge of the created \b Face. \n Projection 3D algorithm allows to define the mesh of a shape by the projection of another already meshed shape. This algorithm works -only if all faces and edges of the target face have been meshed as 1D -Projections of the faces and edges of the source face. Another +only if all faces and edges of the target shape have been meshed as 1D-2D +Projections of the faces and edges of the source shape. Another limitation is that this algorithm currently works only on boxes. To apply this algorithm select the solid to be meshed (indicated in @@ -63,9 +64,9 @@ following dialog box will appear: \image html projection_3d.png In this menu you can define the \b Name of the algorithm, the already -meshed source 3D shape and the \b Mesh (optional, use it if there are -several different meshes on the same shape). It could also be -necessary to define the orientation of mesh on the shape, which is +meshed source 3D shape and the \b Mesh (It can be omitted only when +projecting a submesh on another one from the same global Mesh). +It could also be necessary to define the orientation of mesh on the shape, which is done by indicating two Source Vertices, which belong to the same edge of the source 3D Shape, and two Target Vertices, which belong to the same edge of the source 3D Shape. diff --git a/doc/salome/gui/SMESH/input/scalar_bar.doc b/doc/salome/gui/SMESH/input/scalar_bar.doc new file mode 100755 index 000000000..146a7fa78 --- /dev/null +++ b/doc/salome/gui/SMESH/input/scalar_bar.doc @@ -0,0 +1,40 @@ +/*! + +\page scalar_bar_dlg Scalar Bar properties + +In this dialog you can specify the properties of the scalar bar + +\image html scalar_bar_dlg.png + +
    +
  • Scalar Range in this menu you can specify +Min value and Max value of the Scalar Bar
  • + +
  • Font - in this menu you can set type, face and color for +the font of Title and Labels of the Scalar +Bar
  • + +
  • Colors & Labels - in this menu you can set the number of +colors and the number of labels of the Scalar +Bar
  • + +
  • Orientation - allows choosing between vertical and +horizontal orientation of the Scalar Bar
  • . + +
  • Origin & Size Vertical & Horizontal - allows defining the +location (X and Y) and size (Width and +Height) of Scalar Bar
  • +
      +
    • X: abscissa of the origin (from the left +side)
    • +
    • Y: ordinate of the origin (from the bottom)
    • +
    +
  • Distribution in this menu you can Show/Hide distribution histogram of the values of the Scalar Bar and specify histogram properties
  • +
      +
    • Multicolor the histogram is colored as Scalar Bar
    • +
    • Monocolor the histogram is colored as selected with Distribution color selector
    • +
    +
+ + +*/ diff --git a/doc/salome/gui/SMESH/input/selection_filter_library.doc b/doc/salome/gui/SMESH/input/selection_filter_library.doc index 1f612994f..9657f4c0d 100644 --- a/doc/salome/gui/SMESH/input/selection_filter_library.doc +++ b/doc/salome/gui/SMESH/input/selection_filter_library.doc @@ -144,7 +144,14 @@ Additional criteria to select mesh Faces are the following: one element of mesh only. See also a \ref free_edges_page "Free Edges quality control".
  • -Free faces selects 3D mesh elements wich belong to less than two volumes. +Free faces selects 2D mesh elements wich belong to less than two volumes. +
  • +Faces with bare border selects 2D mesh elements having a free border without an edge on it. +See also \ref bare_border_faces_page "Bare border faces quality control". +
  • +Over-constrained faces selects 2D mesh elements having only one border shared +with other 2D elements. +See also \ref over_constrained_faces_page "Over-constrained faces quality control".
  • Borders at Multi-Connections 2D selects cells consisting of edges belonging to several elements of mesh. The number of mesh elements should be more, less or equal @@ -187,6 +194,13 @@ diagonals with a value of length, which is more, less or equal
  • Bad oriented volume selects mesh volumes, which are incorrectly oriented from the point of view of MED convention. +
  • +Over-constrained volumes selects mesh volumes having only one border shared +with other volumes. +See also \ref over_constrained_volumes_page "Over-constrained volumes quality control". +
  • +Volumes with bare border selects 3D mesh elements having a free border without a face on it. +See also \ref bare_border_volumes_page "Bare border volumes quality control".
  • diff --git a/doc/salome/gui/SMESH/input/tui_creating_meshes.doc b/doc/salome/gui/SMESH/input/tui_creating_meshes.doc index 359ffd7d5..bad32ebf4 100644 --- a/doc/salome/gui/SMESH/input/tui_creating_meshes.doc +++ b/doc/salome/gui/SMESH/input/tui_creating_meshes.doc @@ -249,4 +249,48 @@ demonstrating the resulting mesh. \skipline import geompy \until #end +
    +\anchor tui_copy_mesh +

    Mesh Copying

    +\code +from smesh import * +SetCurrentStudy(salome.myStudy) + +# make geometry of a box +box = geompy.MakeBoxDXDYDZ(100,100,100) +face = geompy.SubShapeAllSorted(box, geompy.ShapeType["FACE"])[0] + +# generate 3D mesh +mesh = Mesh(box) +localAlgo = mesh.Triangle(face) +mesh.AutomaticHexahedralization() + +# objects to copy +fGroup = mesh.GroupOnGeom( face, "2D on face") +nGroup = mesh.GroupOnGeom( face, "nodes on face", NODE) +subMesh = localAlgo.GetSubMesh() + +# make a new mesh by copying different part of the mesh + +# 1. copy the whole mesh +newMesh = CopyMesh( mesh, "whole mesh copy") + +# 2. copy a group of 2D elements along with groups +newMesh = CopyMesh( fGroup, "face group copy with groups",toCopyGroups=True) + +# 3. copy a group of nodes with preseving their ids +newMesh = CopyMesh( nGroup, "node group copy", toKeepIDs=True) + +# 4. copy some faces +faceIds = fGroup.GetIDs()[-10:] +newMesh = CopyMesh( mesh.GetIDSource( faceIds, FACE ), "some faces copy") + +# 5. copy some nodes +nodeIds = nGroup.GetIDs()[-10:] +newMesh = CopyMesh( mesh.GetIDSource( nodeIds, NODE), "some nodes copy") + +# 6. copy a sub-mesh +newMesh = CopyMesh( subMesh, "submesh copy" ) +\endcode + */ diff --git a/doc/salome/gui/SMESH/input/tui_filters.doc b/doc/salome/gui/SMESH/input/tui_filters.doc index 6677b2ab5..aa3e1eb1c 100755 --- a/doc/salome/gui/SMESH/input/tui_filters.doc +++ b/doc/salome/gui/SMESH/input/tui_filters.doc @@ -90,7 +90,7 @@ Filter 2D mesh elements (faces) according to the minimum angle value: # create mesh from SMESH_mechanic import * # get faces with minimum angle > 75 -filter = smesh.GetFilter(smesh.FACE, smesh.FT_MinimumAngle, smesh.FT_MoreThan, 75) +filter = smesh.GetFilter(smesh.FACE, smesh.FT_MinimumAngle,">", 75) ids = mesh.GetIdsFromFilter(filter) print "Number of faces with minimum angle > 75:", len(ids) \endcode @@ -237,7 +237,7 @@ from SMESH_mechanic import * # add node mesh.AddNode(0,0,0) # get all free nodes -filter = smesh.GetFilter(smesh.EDGE, smesh.FT_FreeNodes) +filter = smesh.GetFilter(smesh.NODE, smesh.FT_FreeNodes) ids = mesh.GetIdsFromFilter(filter) print "Number of free nodes:", len(ids) \endcode @@ -255,13 +255,69 @@ Filter free faces: # create mesh from SMESH_mechanic import * # get all free faces -filter = smesh.GetFilter(smesh.EDGE, smesh.FT_FreeFaces) +filter = smesh.GetFilter(smesh.FACE, smesh.FT_FreeFaces) ids = mesh.GetIdsFromFilter(filter) print "Number of free faces:", len(ids) \endcode \sa \ref tui_free_faces +\section filter_bare_border_faces Bare border faces + +Filter faces with bare borders: +- element type is \a smesh.FACE +- functor type is \a smesh.FT_BareBorderFace +- threshold value is not required + +\code +# create mesh +from SMESH_mechanic import * +# remove some faces to have faces with bare borders +mesh.RemoveElements( mesh.GetElementsByType(FACE)[0:5] ) +# get all faces bare borders +filter = smesh.GetFilter(smesh.FACE, smesh.FT_BareBorderFace) +ids = mesh.GetIdsFromFilter(filter) +print "Faces with bare borders:", ids +\endcode + +\sa \ref tui_bare_border_faces + +\section filter_coplanar_faces Coplanar faces + +Filter faces with bare borders: +- element type is \a smesh.FACE +- functor type is \a smesh.FT_CoplanarFaces +- threshold value is the face ID +- tolerance is in degrees + +\code +# create mesh +from SMESH_mechanic import * +faceID = mesh.GetElementsByType(FACE)[0] +# get all faces co-planar to the first face with tolerance 5 degrees +filter = smesh.GetFilter(smesh.FACE, smesh.FT_CoplanarFaces,faceID,Tolerance=5.0) +ids = mesh.GetIdsFromFilter(filter) +print "Number of faces coplanar with the first one:", len(ids) +\endcode + +\section filter_over_constrained_faces Over-constrained faces + +Filter over-constrained faces: +- element type is \a smesh.FACE +- functor type is \a smesh.FT_OverConstrainedFace +- threshold value is not required + +\code +# create mesh +from SMESH_mechanic import * +# get all over-constrained faces +filter = smesh.GetFilter(smesh.FACE, smesh.FT_OverConstrainedFace) +ids = mesh.GetIdsFromFilter(filter) +print "Over-constrained faces:", ids +\endcode + +\sa \ref tui_over_constrained_faces + \section filter_borders_multiconnection Borders at multi-connection Filter border 1D mesh elements (edges) according to the specified number of @@ -377,6 +433,48 @@ print "Number of volumes with maximum element length > 10:", len(ids) \sa \ref tui_max_element_length_3d +\section filter_bare_border_volumes Bare border volumes + +Filter 3D mesh elements with bare borders: +- element type is \a smesh.VOLUME +- functor type is \a smesh.FT_BareBorderVolume +- threshold value is not required + +\code +# create mesh +from SMESH_mechanic import * +mesh.Tetrahedron() +mesh.Compute() +# remove some volumes to have volumes with bare borders +mesh.RemoveElements( mesh.GetElementsByType(VOLUME)[0:5] ) +# get all volumes with bare borders +filter = smesh.GetFilter(smesh.VOLUME, smesh.FT_BareBorderVolume) +ids = mesh.GetIdsFromFilter(filter) +print "Volumes with bare borders:", ids +\endcode + +\sa \ref tui_bare_border_volumes + +\section filter_over_constrained_volumes Over-constrained volumes + +Filter over-constrained volumes: +- element type is \a smesh.VOLUME +- functor type is \a smesh.FT_OverConstrainedVolume +- threshold value is not required + +\code +# create mesh +from SMESH_mechanic import * +mesh.Tetrahedron() +mesh.Compute() +# get all over-constrained volumes +filter = smesh.GetFilter(smesh.VOLUME, smesh.FT_OverConstrainedVolume) +ids = mesh.GetIdsFromFilter(filter) +print "Over-constrained volumes:", ids +\endcode + +\sa \ref tui_over_constrained_faces + \section filter_belong_to_geom Belong to Geom Filter mesh entities (nodes or elements) which all nodes lie on the diff --git a/doc/salome/gui/SMESH/input/tui_quality_controls.doc b/doc/salome/gui/SMESH/input/tui_quality_controls.doc index fc496dcde..420e507e1 100644 --- a/doc/salome/gui/SMESH/input/tui_quality_controls.doc +++ b/doc/salome/gui/SMESH/input/tui_quality_controls.doc @@ -309,6 +309,90 @@ aGroup.Add(aFaceIds) salome.sg.updateObjBrowser(1) \endcode +\section tui_bare_border_faces Bare border faces + +\code +from smesh import * +SetCurrentStudy(salome.myStudy) + +box = geompy.MakeBoxDXDYDZ(100, 100, 100) +geompy.addToStudy( box, "box" ) + +mesh = smesh.Mesh(box) +mesh.Segment().NumberOfSegments(3) +mesh.Quadrangle() +mesh.Compute() + +# remove 2 faces +allFaces = mesh.GetElementsByType(FACE) +mesh.RemoveElements( allFaces[0:2]) + +bareGroup = mesh.MakeGroup("bare faces", FACE, FT_BareBorderFace) +assert(bareGroup.Size() == 3) +\endcode + +\section tui_bare_border_volumes Bare border volumes + +\code +from smesh import * +SetCurrentStudy(salome.myStudy) + +box = geompy.MakeBoxDXDYDZ(100, 30, 10) +# the smallest face of the box +face = geompy.SubShapeAllSorted( box, geompy.ShapeType["FACE"])[0] + +geompy.addToStudy( box, "box" ) +geompy.addToStudyInFather( box, face, "face" ) + +mesh = Mesh(box) +mesh.AutomaticHexahedralization(); + +# remove half of mesh faces from the smallest face +faceFaces = mesh.GetSubMeshElementsId(face) +faceToRemove = faceFaces[: len(faceFaces)/2] +mesh.RemoveElements( faceToRemove ) + +# make a group of volumes missing the removed faces +bareGroup = mesh.MakeGroup("bare volumes", VOLUME, FT_BareBorderVolume) +assert(bareGroup.Size() == len( faceToRemove)) +\endcode + +\section tui_over_constrained_faces Over-constrained faces +\code +from smesh import * +SetCurrentStudy(salome.myStudy) + +mesh = Mesh() +faceFilter = GetFilter(FACE,FT_OverConstrainedFace) + +#make an edge +n1 = mesh.AddNode(0,0,0) +n2 = mesh.AddNode(10,0,0) +edge = mesh.AddEdge([n1,n2]) +assert( not mesh.GetIdsFromFilter( faceFilter )) + +# make faces +mesh.ExtrusionSweep([edge], MakeDirStruct(0,7,0), 5) +assert( 2 == len( mesh.GetIdsFromFilter( faceFilter ))) +\endcode + +\section tui_over_constrained_volumes Over-constrained volumes +\code +from smesh import * +SetCurrentStudy(salome.myStudy) + +mesh = Mesh() +volumeFilter = GetFilter(VOLUME,FT_OverConstrainedVolume) + +# make volumes by extrusion of one face +n1 = mesh.AddNode(0,0,0) +n2 = mesh.AddNode(10,0,0) +edge = mesh.AddEdge([n1,n2]) +mesh.ExtrusionSweep([edge], MakeDirStruct(0,7,0), 1) +mesh.ExtrusionSweep( mesh.GetElementsByType(FACE), MakeDirStruct(0,0,5), 7) +assert( 2 == len( mesh.GetIdsFromFilter( volumeFilter ))) +\endcode + \section tui_length_2d Length 2D \code diff --git a/idl/SMESH_Filter.idl b/idl/SMESH_Filter.idl index e12607bcd..087a0b48b 100644 --- a/idl/SMESH_Filter.idl +++ b/idl/SMESH_Filter.idl @@ -64,6 +64,10 @@ module SMESH FT_LyingOnGeom, FT_RangeOfIds, FT_BadOrientedVolume, + FT_BareBorderVolume, + FT_BareBorderFace, + FT_OverConstrainedVolume, + FT_OverConstrainedFace, FT_LinearOrQuadratic, FT_GroupColor, FT_ElemGeomType, @@ -88,6 +92,7 @@ module SMESH }; typedef sequence Histogram; + /*! * Base interface for all functors ( i.e. numerical functors and predicates ) */ @@ -98,8 +103,6 @@ module SMESH ElementType GetElementType(); }; - - /*! * Numerical functors are intended for calculating value by Id of mesh entity */ @@ -150,6 +153,7 @@ module SMESH Values GetValues(); }; + /*! * Predicates are intended for verification of criteria, * must return bool value by mesh id @@ -166,6 +170,29 @@ module SMESH */ interface BadOrientedVolume: Predicate {}; + /*! + * Logical functor (predicate) "Volumes with bare border". + * Verify whether a mesh volume has a free facet without a mesh face on it + */ + interface BareBorderVolume: Predicate {}; + /*! + * Logical functor (predicate) "Faces with bare border". + * Verify whether a mesh face has a side not shared with another face + * and without a mesh edge on it + */ + interface BareBorderFace: Predicate {}; + + /*! + * Logical functor (predicate) "Over-constrained Volume" + * Verify whether a mesh volume has only one facet shared with other volumes + */ + interface OverConstrainedVolume: Predicate {}; + /*! + * Logical functor (predicate) "Over-constrained Face". + * Verify whether a mesh face has only one border shared with other faces + */ + interface OverConstrainedFace: Predicate {}; + /*! * Logical functor (predicate) "Belong To Geometry". * Verify whether mesh element or node belong to pointed Geom Object @@ -503,6 +530,10 @@ module SMESH RangeOfIds CreateRangeOfIds(); BadOrientedVolume CreateBadOrientedVolume(); + BareBorderVolume CreateBareBorderVolume(); + BareBorderFace CreateBareBorderFace(); + OverConstrainedVolume CreateOverConstrainedVolume(); + OverConstrainedFace CreateOverConstrainedFace(); LinearOrQuadratic CreateLinearOrQuadratic(); GroupColor CreateGroupColor(); diff --git a/idl/SMESH_Gen.idl b/idl/SMESH_Gen.idl index 3c375e625..d958719e3 100644 --- a/idl/SMESH_Gen.idl +++ b/idl/SMESH_Gen.idl @@ -221,10 +221,45 @@ module SMESH raises ( SALOME::SALOME_Exception ); /*! - * Create a Mesh object, without a geometry shape reference + * Create a mesh by copying a part of another mesh + * \param meshPart - a part of mesh to copy + * \param meshName - a name of the new mesh + * \param toCopyGroups - to create in the new mesh groups + * the copied elements belongs to + * \param toKeepIDs - to preserve IDs of the copied elements or not */ -// SMESH_Mesh NewEmpty() -// raises ( SALOME::SALOME_Exception ); + SMESH_Mesh CopyMesh(in SMESH_IDSource meshPart, + in string meshName, + in boolean toCopyGroups, + in boolean toKeepIDs) + raises ( SALOME::SALOME_Exception ); + + /*! + * Concatenate the given meshes into one mesh. + * Union groups with the same name and type if + * theUniteIdenticalGroups flag is true. + * Merge coincident nodes and elements if + * theMergeNodesAndElements flag is true. + */ + SMESH_Mesh Concatenate(in mesh_array theMeshesArray, + in boolean theUniteIdenticalGroups, + in boolean theMergeNodesAndElements, + in double theMergeTolerance) + raises ( SALOME::SALOME_Exception ); + + /*! + * Concatenate the given meshes into one mesh. + * Union groups with the same name and type if + * theUniteIdenticalGroups flag is true. + * Merge coincident nodes and elements if + * theMergeNodesAndElements flag is true. + * Create the groups of all elements from initial meshes. + */ + SMESH_Mesh ConcatenateWithGroups(in mesh_array theMeshesArray, + in boolean theUniteIdenticalGroups, + in boolean theMergeNodesAndElements, + in double theMergeTolerance) + raises ( SALOME::SALOME_Exception ); /*! * Mesh a subShape. @@ -309,33 +344,6 @@ module SMESH in long theElementID) raises ( SALOME::SALOME_Exception ); - /*! - * Concatenate the given meshes into one mesh. - * Union groups with the same name and type if - * theUniteIdenticalGroups flag is true. - * Merge coincident nodes and elements if - * theMergeNodesAndElements flag is true. - */ - SMESH_Mesh Concatenate(in mesh_array theMeshesArray, - in boolean theUniteIdenticalGroups, - in boolean theMergeNodesAndElements, - in double theMergeTolerance) - raises ( SALOME::SALOME_Exception ); - - /*! - * Concatenate the given meshes into one mesh. - * Union groups with the same name and type if - * theUniteIdenticalGroups flag is true. - * Merge coincident nodes and elements if - * theMergeNodesAndElements flag is true. - * Create the groups of all elements from initial meshes. - */ - SMESH_Mesh ConcatenateWithGroups(in mesh_array theMeshesArray, - in boolean theUniteIdenticalGroups, - in boolean theMergeNodesAndElements, - in double theMergeTolerance) - raises ( SALOME::SALOME_Exception ); - /*! * \brief Return id of object, registered in current study context * diff --git a/resources/Makefile.am b/resources/Makefile.am index cc7d5a885..623d04ff1 100644 --- a/resources/Makefile.am +++ b/resources/Makefile.am @@ -107,6 +107,10 @@ dist_salomeres_DATA = \ mesh_vertex_n.png \ mesh_vertex.png \ mesh_volume_3d.png \ + bare_border_volume.png \ + bare_border_face.png \ + over_constrained_volume.png \ + over_constrained_face.png \ mesh_wireframe.png \ mesh_points.png \ mesh_wrap.png \ @@ -173,6 +177,7 @@ dist_salomeres_DATA = \ mesh_tree_hypo_projection_3d.png \ mesh_tree_hypo_projection_2d.png \ mesh_build_compound.png \ + copy_mesh.png \ mesh_node_to_point.png \ mesh_tree_mesh_partial.png \ mesh_extractGroup.png \ diff --git a/resources/bare_border_face.png b/resources/bare_border_face.png new file mode 100644 index 0000000000000000000000000000000000000000..1993f2087f86b35ee09a9f1fdb7530e0785a0ae1 GIT binary patch literal 3168 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 literal 0 HcmV?d00001 diff --git a/resources/copy_mesh.png b/resources/copy_mesh.png new file mode 100644 index 0000000000000000000000000000000000000000..263479f3bf79e868ee99d860c0c3b13ffb9b3d55 GIT binary patch literal 1117 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 LNkvXXu0mjfR4HPG literal 0 HcmV?d00001 diff --git a/resources/over_constrained_volume.png b/resources/over_constrained_volume.png new file mode 100644 index 0000000000000000000000000000000000000000..0e2da263fc8d6a08e7d1634fd589703529a3a5b8 GIT binary patch literal 3444 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 nbEvents, - std::vector& funValues) + std::vector& funValues, + const vector& elements, + const double* minmax) { if ( nbIntervals < 1 || !myMesh || @@ -326,13 +330,30 @@ void NumericalFunctor::GetHistogram(int nbIntervals, // get all values sorted std::multiset< double > values; - SMDS_ElemIteratorPtr elemIt = myMesh->elementsIterator(GetType()); - while ( elemIt->more() ) - values.insert( GetValue( elemIt->next()->GetID() )); + if ( elements.empty() ) + { + SMDS_ElemIteratorPtr elemIt = myMesh->elementsIterator(GetType()); + while ( elemIt->more() ) + values.insert( GetValue( elemIt->next()->GetID() )); + } + else + { + vector::const_iterator id = elements.begin(); + for ( ; id != elements.end(); ++id ) + values.insert( GetValue( *id )); + } + if ( minmax ) + { + funValues[0] = minmax[0]; + funValues[nbIntervals] = minmax[1]; + } + else + { + funValues[0] = *values.begin(); + funValues[nbIntervals] = *values.rbegin(); + } // case nbIntervals == 1 - funValues[0] = *values.begin(); - funValues[nbIntervals] = *values.rbegin(); if ( nbIntervals == 1 ) { nbEvents[0] = values.size(); @@ -350,15 +371,21 @@ void NumericalFunctor::GetHistogram(int nbIntervals, std::multiset< double >::iterator min = values.begin(), max; for ( int i = 0; i < nbIntervals; ++i ) { + // find end value of i-th interval double r = (i+1) / double( nbIntervals ); funValues[i+1] = funValues.front() * (1-r) + funValues.back() * r; + + // count values in the i-th interval if there are any if ( min != values.end() && *min <= funValues[i+1] ) { - max = values.upper_bound( funValues[i+1] ); // greater than funValues[i+1], or end() + // find the first value out of the interval + max = values.upper_bound( funValues[i+1] ); // max is greater than funValues[i+1], or end() nbEvents[i] = std::distance( min, max ); min = max; } } + // add values larger than minmax[1] + nbEvents.back() += std::distance( min, values.end() ); } //======================================================================= @@ -1902,7 +1929,115 @@ SMDSAbs_ElementType BadOrientedVolume::GetType() const return SMDSAbs_Volume; } +/* + Class : BareBorderVolume +*/ + +bool BareBorderVolume::IsSatisfy(long theElementId ) +{ + SMDS_VolumeTool myTool; + if ( myTool.Set( myMesh->FindElement(theElementId))) + { + for ( int iF = 0; iF < myTool.NbFaces(); ++iF ) + if ( myTool.IsFreeFace( iF )) + { + const SMDS_MeshNode** n = myTool.GetFaceNodes(iF); + vector< const SMDS_MeshNode*> nodes( n, n+myTool.NbFaceNodes(iF)); + if ( !myMesh->FindElement( nodes, SMDSAbs_Face, /*Nomedium=*/false)) + return true; + } + } + return false; +} + +/* + Class : BareBorderFace +*/ + +bool BareBorderFace::IsSatisfy(long theElementId ) +{ + if ( const SMDS_MeshElement* face = myMesh->FindElement(theElementId)) + if ( face->GetType() == SMDSAbs_Face ) + { + int nbN = face->NbCornerNodes(); + for ( int i = 0; i < nbN; ++i ) + { + // check if a link is shared by another face + const SMDS_MeshNode* n1 = face->GetNode( i ); + const SMDS_MeshNode* n2 = face->GetNode( (i+1)%nbN ); + SMDS_ElemIteratorPtr fIt = n1->GetInverseElementIterator( SMDSAbs_Face ); + bool isShared = false; + while ( !isShared && fIt->more() ) + { + const SMDS_MeshElement* f = fIt->next(); + isShared = ( f != face && f->GetNodeIndex(n2) != -1 ); + } + if ( !isShared ) + { + myLinkNodes.resize( 2 + face->IsQuadratic()); + myLinkNodes[0] = n1; + myLinkNodes[1] = n2; + if ( face->IsQuadratic() ) + myLinkNodes[2] = face->GetNode( i+nbN ); + return !myMesh->FindElement( myLinkNodes, SMDSAbs_Edge, /*noMedium=*/false); + } + } + } + return false; +} + +/* + Class : OverConstrainedVolume +*/ +bool OverConstrainedVolume::IsSatisfy(long theElementId ) +{ + // An element is over-constrained if it has N-1 free borders where + // N is the number of edges/faces for a 2D/3D element. + SMDS_VolumeTool myTool; + if ( myTool.Set( myMesh->FindElement(theElementId))) + { + int nbSharedFaces = 0; + for ( int iF = 0; iF < myTool.NbFaces(); ++iF ) + if ( !myTool.IsFreeFace( iF ) && ++nbSharedFaces > 1 ) + break; + return ( nbSharedFaces == 1 ); + } + return false; +} + +/* + Class : OverConstrainedFace +*/ + +bool OverConstrainedFace::IsSatisfy(long theElementId ) +{ + // An element is over-constrained if it has N-1 free borders where + // N is the number of edges/faces for a 2D/3D element. + if ( const SMDS_MeshElement* face = myMesh->FindElement(theElementId)) + if ( face->GetType() == SMDSAbs_Face ) + { + int nbSharedBorders = 0; + int nbN = face->NbCornerNodes(); + for ( int i = 0; i < nbN; ++i ) + { + // check if a link is shared by another face + const SMDS_MeshNode* n1 = face->GetNode( i ); + const SMDS_MeshNode* n2 = face->GetNode( (i+1)%nbN ); + SMDS_ElemIteratorPtr fIt = n1->GetInverseElementIterator( SMDSAbs_Face ); + bool isShared = false; + while ( !isShared && fIt->more() ) + { + const SMDS_MeshElement* f = fIt->next(); + isShared = ( f != face && f->GetNodeIndex(n2) != -1 ); + } + if ( isShared && ++nbSharedBorders > 1 ) + break; + } + return ( nbSharedBorders == 1 ); + } + return false; +} /* Class : FreeBorders diff --git a/src/Controls/SMESH_ControlsDef.hxx b/src/Controls/SMESH_ControlsDef.hxx index 915bd9f4b..0a71438d7 100644 --- a/src/Controls/SMESH_ControlsDef.hxx +++ b/src/Controls/SMESH_ControlsDef.hxx @@ -127,9 +127,11 @@ namespace SMESH{ virtual void SetMesh( const SMDS_Mesh* theMesh ); virtual double GetValue( long theElementId ); virtual double GetValue(const TSequenceOfXYZ& thePoints) { return -1.0;}; - void GetHistogram(int nbIntervals, - std::vector& nbEvents, - std::vector& funValues); + void GetHistogram(int nbIntervals, + std::vector& nbEvents, + std::vector& funValues, + const std::vector& elements, + const double* minmax=0); virtual SMDSAbs_ElementType GetType() const = 0; virtual double GetBadRate( double Value, int nbNodes ) const = 0; long GetPrecision() const; @@ -373,11 +375,72 @@ namespace SMESH{ virtual void SetMesh( const SMDS_Mesh* theMesh ); virtual bool IsSatisfy( long theElementId ); virtual SMDSAbs_ElementType GetType() const; - + protected: const SMDS_Mesh* myMesh; }; - + + /* + BareBorderVolume + */ + class SMESHCONTROLS_EXPORT BareBorderVolume: public Predicate + { + public: + BareBorderVolume():myMesh(0) {} + virtual void SetMesh( const SMDS_Mesh* theMesh ) { myMesh = theMesh; } + virtual SMDSAbs_ElementType GetType() const { return SMDSAbs_Volume; } + virtual bool IsSatisfy( long theElementId ); + protected: + const SMDS_Mesh* myMesh; + }; + typedef boost::shared_ptr BareBorderVolumePtr; + + /* + BareBorderFace + */ + class SMESHCONTROLS_EXPORT BareBorderFace: public Predicate + { + public: + BareBorderFace():myMesh(0) {} + virtual void SetMesh( const SMDS_Mesh* theMesh ) { myMesh = theMesh; } + virtual SMDSAbs_ElementType GetType() const { return SMDSAbs_Face; } + virtual bool IsSatisfy( long theElementId ); + protected: + const SMDS_Mesh* myMesh; + std::vector< const SMDS_MeshNode* > myLinkNodes; + }; + typedef boost::shared_ptr BareBorderFacePtr; + + /* + OverConstrainedVolume + */ + class SMESHCONTROLS_EXPORT OverConstrainedVolume: public Predicate + { + public: + OverConstrainedVolume():myMesh(0) {} + virtual void SetMesh( const SMDS_Mesh* theMesh ) { myMesh = theMesh; } + virtual SMDSAbs_ElementType GetType() const { return SMDSAbs_Volume; } + virtual bool IsSatisfy( long theElementId ); + protected: + const SMDS_Mesh* myMesh; + }; + typedef boost::shared_ptr OverConstrainedVolumePtr; + + /* + OverConstrainedFace + */ + class SMESHCONTROLS_EXPORT OverConstrainedFace: public Predicate + { + public: + OverConstrainedFace():myMesh(0) {} + virtual void SetMesh( const SMDS_Mesh* theMesh ) { myMesh = theMesh; } + virtual SMDSAbs_ElementType GetType() const { return SMDSAbs_Face; } + virtual bool IsSatisfy( long theElementId ); + protected: + const SMDS_Mesh* myMesh; + std::vector< const SMDS_MeshNode* > myLinkNodes; + }; + typedef boost::shared_ptr OverConstrainedFacePtr; /* Class : FreeEdges @@ -399,7 +462,7 @@ namespace SMESH{ }; typedef std::set TBorders; void GetBoreders(TBorders& theBorders); - + protected: const SMDS_Mesh* myMesh; }; diff --git a/src/OBJECT/SMESH_Actor.cxx b/src/OBJECT/SMESH_Actor.cxx index 4b4f432ff..cafd4b000 100644 --- a/src/OBJECT/SMESH_Actor.cxx +++ b/src/OBJECT/SMESH_Actor.cxx @@ -204,6 +204,25 @@ SMESH_ActorDef::SMESH_ActorDef() aFilter->RegisterCellsWithType(VTK_POLYHEDRON); //#endif + my3DExtActor = SMESH_DeviceActor::New(); + my3DExtActor->SetUserMatrix(aMatrix); + my3DExtActor->PickableOff(); + my3DExtActor->SetProperty(my2DExtProp); + my3DExtActor->SetBackfaceProperty(my2DExtProp); + my3DExtActor->SetRepresentation(SMESH_DeviceActor::eSurface); + aFilter = my3DExtActor->GetExtractUnstructuredGrid(); + aFilter->SetModeOfChanging(VTKViewer_ExtractUnstructuredGrid::eAdding); + aFilter->RegisterCellsWithType(VTK_TETRA); + aFilter->RegisterCellsWithType(VTK_VOXEL); + aFilter->RegisterCellsWithType(VTK_HEXAHEDRON); + aFilter->RegisterCellsWithType(VTK_WEDGE); + aFilter->RegisterCellsWithType(VTK_PYRAMID); + aFilter->RegisterCellsWithType(VTK_QUADRATIC_TETRA); + aFilter->RegisterCellsWithType(VTK_QUADRATIC_HEXAHEDRON); + aFilter->RegisterCellsWithType(VTK_QUADRATIC_WEDGE); + aFilter->RegisterCellsWithType(VTK_QUADRATIC_PYRAMID); + aFilter->RegisterCellsWithType(VTK_CONVEX_POINT_SET); + //Definition 1D device of the actor //--------------------------------- myEdgeProp = vtkProperty::New(); @@ -537,6 +556,7 @@ SMESH_ActorDef::~SMESH_ActorDef() my2DExtProp->Delete(); my2DExtActor->Delete(); my3DActor->Delete(); + my3DExtActor->Delete(); myNodeActor->Delete(); myBaseActor->Delete(); @@ -728,8 +748,8 @@ SetControlMode(eControl theMode, bool anIsScalarVisible = theMode > eNone; - if(anIsScalarVisible){ - switch(theMode){ + if(anIsScalarVisible) { + switch(theMode) { case eLength: { SMESH::Controls::Length* aControl = new SMESH::Controls::Length(); @@ -760,6 +780,14 @@ SetControlMode(eControl theMode, myFunctor.reset(new SMESH::Controls::FreeFaces()); myControlActor = my2DActor; break; + case eBareBorderFace: + myFunctor.reset(new SMESH::Controls::BareBorderFace()); + myControlActor = my2DActor; + break; + case eOverConstrainedFace: + myFunctor.reset(new SMESH::Controls::OverConstrainedFace()); + myControlActor = my2DActor; + break; case eMultiConnection: myFunctor.reset(new SMESH::Controls::MultiConnection()); myControlActor = my1DActor; @@ -824,6 +852,18 @@ SetControlMode(eControl theMode, myControlActor = my3DActor; break; } + case eBareBorderVolume: + { + myFunctor.reset(new SMESH::Controls::BareBorderVolume()); + myControlActor = my3DActor; + break; + } + case eOverConstrainedVolume: + { + myFunctor.reset(new SMESH::Controls::OverConstrainedVolume()); + myControlActor = my3DActor; + break; + } case eMinimumAngle: { SMESH::Controls::MinimumAngle* aControl = new SMESH::Controls::MinimumAngle(); @@ -865,14 +905,22 @@ SetControlMode(eControl theMode, my1DExtActor->SetExtControlMode(myFunctor); break; case eFreeFaces: + case eBareBorderFace: + case eOverConstrainedFace: my2DExtActor->SetExtControlMode(myFunctor); break; + case eBareBorderVolume: + case eOverConstrainedVolume: + my3DExtActor->SetExtControlMode(myFunctor); + break; case eLength2D: case eMultiConnection2D: my1DExtActor->SetExtControlMode(myFunctor,myScalarBarActor,myLookupTable); + UpdateDistribution(); break; default: myControlActor->SetControlMode(myFunctor,myScalarBarActor,myLookupTable); + UpdateDistribution(); } } @@ -916,6 +964,7 @@ void SMESH_ActorDef::AddToRender(vtkRenderer* theRenderer){ theRenderer->AddActor(myNodeExtActor); my3DActor->AddToRender(theRenderer); + my3DExtActor->AddToRender(theRenderer); my2DActor->AddToRender(theRenderer); my2DExtActor->AddToRender(theRenderer); @@ -959,6 +1008,7 @@ void SMESH_ActorDef::RemoveFromRender(vtkRenderer* theRenderer){ my2DActor->RemoveFromRender(theRenderer); my2DExtActor->RemoveFromRender(theRenderer); my3DActor->RemoveFromRender(theRenderer); + my3DExtActor->RemoveFromRender(theRenderer); theRenderer->RemoveActor(myScalarBarActor); theRenderer->RemoveActor(myPointLabels); @@ -994,6 +1044,7 @@ bool SMESH_ActorDef::Init(TVisualObjPtr theVisualObj, my2DActor->Init(myVisualObj,myImplicitBoolean); my2DExtActor->Init(myVisualObj,myImplicitBoolean); my3DActor->Init(myVisualObj,myImplicitBoolean); + my3DExtActor->Init(myVisualObj,myImplicitBoolean); my0DActor->GetMapper()->SetLookupTable(myLookupTable); //my0DExtActor->GetMapper()->SetLookupTable(myLookupTable); @@ -1004,6 +1055,7 @@ bool SMESH_ActorDef::Init(TVisualObjPtr theVisualObj, my2DActor->GetMapper()->SetLookupTable(myLookupTable); my2DExtActor->GetMapper()->SetLookupTable(myLookupTable); my3DActor->GetMapper()->SetLookupTable(myLookupTable); + my3DExtActor->GetMapper()->SetLookupTable(myLookupTable); vtkFloatingPointType aFactor, aUnits; my2DActor->GetPolygonOffsetParameters(aFactor,aUnits); @@ -1076,6 +1128,7 @@ void SMESH_ActorDef::SetTransform(VTKViewer_Transform* theTransform){ my2DActor->SetTransform(theTransform); my2DExtActor->SetTransform(theTransform); my3DActor->SetTransform(theTransform); + my3DExtActor->SetTransform(theTransform); Modified(); } @@ -1131,6 +1184,7 @@ void SMESH_ActorDef::SetShrinkFactor(vtkFloatingPointType theValue){ my2DActor->SetShrinkFactor(theValue); my2DExtActor->SetShrinkFactor(theValue); my3DActor->SetShrinkFactor(theValue); + my3DExtActor->SetShrinkFactor(theValue); Modified(); } @@ -1146,6 +1200,7 @@ void SMESH_ActorDef::SetShrink(){ my2DActor->SetShrink(); my2DExtActor->SetShrink(); my3DActor->SetShrink(); + my3DExtActor->SetShrink(); myIsShrunk = true; Modified(); @@ -1162,6 +1217,7 @@ void SMESH_ActorDef::UnShrink(){ my2DActor->UnShrink(); my2DExtActor->UnShrink(); my3DActor->UnShrink(); + my3DExtActor->UnShrink(); myIsShrunk = false; Modified(); @@ -1208,6 +1264,7 @@ void SMESH_ActorDef::SetVisibility(int theMode, bool theIsUpdateRepersentation){ my2DActor->VisibilityOff(); my2DExtActor->VisibilityOff(); my3DActor->VisibilityOff(); + my3DExtActor->VisibilityOff(); myScalarBarActor->VisibilityOff(); myPointLabels->VisibilityOff(); @@ -1227,8 +1284,14 @@ void SMESH_ActorDef::SetVisibility(int theMode, bool theIsUpdateRepersentation){ my1DExtActor->VisibilityOn(); break; case eFreeFaces: + case eBareBorderFace: + case eOverConstrainedFace: my2DExtActor->VisibilityOn(); break; + case eBareBorderVolume: + case eOverConstrainedVolume: + my3DExtActor->VisibilityOn(); + break; case eLength2D: case eMultiConnection2D: my1DExtActor->VisibilityOn(); @@ -1467,6 +1530,7 @@ void SMESH_ActorDef::SetRepresentation (int theMode) //my0DExtActor->SetVisibility(false); my1DExtActor->SetVisibility(false); my2DExtActor->SetVisibility(false); + my3DExtActor->SetVisibility(false); // ??? //my0DActor->SetProperty(aProp); @@ -1797,6 +1861,7 @@ SMESH_ActorDef::SetImplicitFunctionUsed(bool theIsImplicitFunctionUsed) my2DActor->SetImplicitFunctionUsed(theIsImplicitFunctionUsed); my2DExtActor->SetImplicitFunctionUsed(theIsImplicitFunctionUsed); my3DActor->SetImplicitFunctionUsed(theIsImplicitFunctionUsed); + my3DExtActor->SetImplicitFunctionUsed(theIsImplicitFunctionUsed); } vtkIdType @@ -1958,7 +2023,7 @@ void SMESH_ActorDef::UpdateScalarBar() myScalarBarActor->SetDistributionColoringType(coloringType); QColor distributionColor = mgr->colorValue("SMESH", "distribution_color", - QColor(255, 255, 255)); + QColor(255, 255, 255)); double rgb[3]; rgb[0]= distributionColor.red()/255.; rgb[1]= distributionColor.green()/255.; @@ -1968,6 +2033,27 @@ void SMESH_ActorDef::UpdateScalarBar() } +void SMESH_ActorDef::UpdateDistribution() +{ + if(SMESH::Controls::NumericalFunctor* fun = + dynamic_cast(myFunctor.get())) + { + int nbIntervals = myScalarBarActor->GetMaximumNumberOfColors(); + std::vector nbEvents; + std::vector funValues; + SMESH_VisualObjDef::TEntityList elems; + if ( ! dynamic_cast(myVisualObj.get())) + dynamic_cast(myVisualObj.get())->GetEntities( fun->GetType(), elems ); + std::vector elemIds; + for ( SMESH_VisualObjDef::TEntityList::iterator e = elems.begin(); e != elems.end(); ++e) + elemIds.push_back( (*e)->GetID()); + vtkLookupTable* lookupTable = static_cast(myScalarBarActor->GetLookupTable()); + double * range = lookupTable->GetRange(); + fun->GetHistogram(nbIntervals, nbEvents, funValues, elemIds, range); + myScalarBarActor->SetDistribution(nbEvents); + } +} + void SMESH_ActorDef::SetQuadratic2DRepresentation(EQuadratic2DRepresentation theMode) { switch(theMode) { diff --git a/src/OBJECT/SMESH_Actor.h b/src/OBJECT/SMESH_Actor.h index 24a57a00a..744571e41 100644 --- a/src/OBJECT/SMESH_Actor.h +++ b/src/OBJECT/SMESH_Actor.h @@ -123,7 +123,8 @@ class SMESHOBJECT_EXPORT SMESH_Actor: public SALOME_Actor enum eControl{eNone, eLength, eLength2D, eFreeBorders, eFreeEdges, eFreeNodes, eFreeFaces, eMultiConnection, eArea, eTaper, eAspectRatio, eMinimumAngle, eWarping, eSkew, eAspectRatio3D, eMultiConnection2D, eVolume3D, - eMaxElementLength2D, eMaxElementLength3D}; + eMaxElementLength2D, eMaxElementLength3D, eBareBorderFace, eBareBorderVolume, + eOverConstrainedFace, eOverConstrainedVolume}; virtual void SetControlMode(eControl theMode) = 0; virtual eControl GetControlMode() = 0; virtual SMESH::Controls::FunctorPtr GetFunctor() = 0; @@ -141,6 +142,7 @@ class SMESHOBJECT_EXPORT SMESH_Actor: public SALOME_Actor virtual long GetControlsPrecision() const = 0; virtual void UpdateScalarBar() = 0; + virtual void UpdateDistribution() = 0; }; diff --git a/src/OBJECT/SMESH_ActorDef.h b/src/OBJECT/SMESH_ActorDef.h index 09b2232f0..53001f4ef 100644 --- a/src/OBJECT/SMESH_ActorDef.h +++ b/src/OBJECT/SMESH_ActorDef.h @@ -196,6 +196,7 @@ class SMESH_ActorDef : public SMESH_Actor virtual long GetControlsPrecision() const { return myControlsPrecision; } virtual void UpdateScalarBar(); + virtual void UpdateDistribution(); virtual void SetQuadratic2DRepresentation(EQuadratic2DRepresentation); @@ -234,6 +235,7 @@ class SMESH_ActorDef : public SMESH_Actor SMESH_DeviceActor* my2DActor; SMESH_DeviceActor* my2DExtActor; SMESH_DeviceActor* my3DActor; + SMESH_DeviceActor* my3DExtActor; SMESH_DeviceActor* myControlActor; vtkProperty* myNodeExtProp; diff --git a/src/OBJECT/SMESH_DeviceActor.cxx b/src/OBJECT/SMESH_DeviceActor.cxx index 600a4987c..d4a04203b 100644 --- a/src/OBJECT/SMESH_DeviceActor.cxx +++ b/src/OBJECT/SMESH_DeviceActor.cxx @@ -310,12 +310,6 @@ SMESH_DeviceActor double aValue = aNumericalFunctor->GetValue(anObjId); aScalars->SetValue(i,aValue); } - int nbIntervals = theScalarBarActor->GetMaximumNumberOfColors(); - std::vector nbEvents; - std::vector funValues; - aNumericalFunctor->GetHistogram(nbIntervals, nbEvents, funValues); - theScalarBarActor->SetDistribution(nbEvents); - }else if(Predicate* aPredicate = dynamic_cast(theFunctor.get())){ for(vtkIdType i = 0; i < aNbCells; i++){ vtkIdType anId = myExtractUnstructuredGrid->GetInputId(i); @@ -475,16 +469,6 @@ SMESH_DeviceActor myMergeFilter->SetScalars(aDataSet); aDataSet->Delete(); } - - //Set Distribution - if(NumericalFunctor* aNumericalFunctor = dynamic_cast(theFunctor.get())){ - int nbIntervals = theScalarBarActor->GetMaximumNumberOfColors(); - std::vector nbEvents; - std::vector funValues; - aNumericalFunctor->GetHistogram(nbIntervals, nbEvents, funValues); - theScalarBarActor->SetDistribution(nbEvents); - } - } GetMapper()->SetScalarVisibility(anIsInitialized); theScalarBarActor->SetVisibility(anIsInitialized); @@ -500,8 +484,13 @@ SMESH_DeviceActor myVisualObj->UpdateFunctor(theFunctor); using namespace SMESH::Controls; - if ( dynamic_cast(theFunctor.get()) || - dynamic_cast(theFunctor.get()) ) { + if ( dynamic_cast(theFunctor.get()) || + dynamic_cast(theFunctor.get()) || + dynamic_cast(theFunctor.get()) || + dynamic_cast(theFunctor.get()) || + dynamic_cast(theFunctor.get()) || + dynamic_cast(theFunctor.get())) + { Predicate* aFreePredicate = dynamic_cast(theFunctor.get()); myExtractUnstructuredGrid->SetModeOfChanging(VTKViewer_ExtractUnstructuredGrid::eAdding); vtkUnstructuredGrid* aGrid = myVisualObj->GetUnstructuredGrid(); @@ -514,7 +503,9 @@ SMESH_DeviceActor if(!myExtractUnstructuredGrid->IsCellsRegistered()) myExtractUnstructuredGrid->RegisterCell(-1); SetUnstructuredGrid(myVisualObj->GetUnstructuredGrid()); - }else if(FreeEdges* aFreeEdges = dynamic_cast(theFunctor.get())){ + } + else if(FreeEdges* aFreeEdges = dynamic_cast(theFunctor.get())) + { SMESH::Controls::FreeEdges::TBorders aBorders; aFreeEdges->GetBoreders(aBorders); vtkUnstructuredGrid* aDataSet = vtkUnstructuredGrid::New(); @@ -561,7 +552,9 @@ SMESH_DeviceActor SetUnstructuredGrid(aDataSet); aDataSet->Delete(); - }else if(FreeNodes* aFreeNodes = dynamic_cast(theFunctor.get())){ + } + else if(FreeNodes* aFreeNodes = dynamic_cast(theFunctor.get())) + { myExtractUnstructuredGrid->SetModeOfChanging(VTKViewer_ExtractUnstructuredGrid::eAdding); vtkIdType aNbNodes = myVisualObj->GetNbEntities(SMDSAbs_Node); for( vtkIdType i = 0; i < aNbNodes; i++ ){ diff --git a/src/OBJECT/SMESH_PreviewActorsCollection.cxx b/src/OBJECT/SMESH_PreviewActorsCollection.cxx index 059edd927..91e38e354 100644 --- a/src/OBJECT/SMESH_PreviewActorsCollection.cxx +++ b/src/OBJECT/SMESH_PreviewActorsCollection.cxx @@ -101,7 +101,7 @@ bool SMESH_PreviewActorsCollection::Init( const TopoDS_Shape& theShape, TopAbs_S int index = myMapOfShapes.FindIndex( exp.Current() ); if ( index && !myMapOfActors.contains( index ) ) { // create actor if the index is present - if ( GEOM_Actor* anActor = createActor( exp.Current() )) { + if ( GEOM_Actor* anActor = createActor( exp.Current().Oriented(TopAbs_FORWARD))) { // Create new entry for actor QString aString = theEntry; aString += QString("_%1").arg( index ); // add index to actor entry diff --git a/src/SMDS/SMDS_MeshElement.cxx b/src/SMDS/SMDS_MeshElement.cxx index 3b4cd2520..17a1935ae 100644 --- a/src/SMDS/SMDS_MeshElement.cxx +++ b/src/SMDS/SMDS_MeshElement.cxx @@ -35,13 +35,22 @@ using namespace std; -SMDS_MeshElement::SMDS_MeshElement(int ID):myID(ID), myMeshId(-1), myShapeId(0), myIdInShape(-1) +SMDS_MeshElement::SMDS_MeshElement(int ID) { + init(ID); } -SMDS_MeshElement::SMDS_MeshElement(int id, ShortType meshId, ShortType shapeId): - myID(id), myMeshId(meshId), myShapeId(shapeId), myIdInShape(-1) +SMDS_MeshElement::SMDS_MeshElement(int id, ShortType meshId, ShortType shapeId) { + init(id, meshId, shapeId); +} + +void SMDS_MeshElement::init(int id, ShortType meshId, ShortType shapeId ) +{ + myID = id; + myMeshId = meshId; + myShapeId = shapeId; + myIdInShape = -1; } void SMDS_MeshElement::Print(ostream & OS) const diff --git a/src/SMDS/SMDS_MeshElement.hxx b/src/SMDS/SMDS_MeshElement.hxx index d4f32a51b..374d67379 100644 --- a/src/SMDS/SMDS_MeshElement.hxx +++ b/src/SMDS/SMDS_MeshElement.hxx @@ -151,6 +151,7 @@ protected: inline void setVtkId(int vtkId) { myVtkID = vtkId; }; SMDS_MeshElement(int ID=-1); SMDS_MeshElement(int id, ShortType meshId, ShortType shapeId = 0); + virtual void init(int id = -1, ShortType meshId = -1, ShortType shapeId = 0); virtual void Print(std::ostream & OS) const; //! Element index in vector SMDS_Mesh::myNodes or SMDS_Mesh::myCells diff --git a/src/SMDS/SMDS_MeshNode.cxx b/src/SMDS/SMDS_MeshNode.cxx index de0f10e3e..fd6116368 100644 --- a/src/SMDS/SMDS_MeshNode.cxx +++ b/src/SMDS/SMDS_MeshNode.cxx @@ -61,12 +61,9 @@ SMDS_MeshNode::SMDS_MeshNode(int id, int meshId, int shapeId, double x, double y void SMDS_MeshNode::init(int id, int meshId, int shapeId, double x, double y, double z) { + SMDS_MeshElement::init(id, meshId, shapeId); myVtkID = id -1; assert(myVtkID >= 0); - myID = id; - myMeshId = meshId; - myShapeId = shapeId; - myIdInShape = -1; //MESSAGE("Node " << myID << " " << myVtkID << " (" << x << ", " << y << ", " << z << ")"); SMDS_Mesh* mesh = SMDS_Mesh::_meshList[myMeshId]; SMDS_UnstructuredGrid * grid = mesh->getGrid(); @@ -312,9 +309,12 @@ vtkIdType SMDS_MeshNode::GetVtkType() const //======================================================================= void SMDS_MeshNode::AddInverseElement(const SMDS_MeshElement* ME) { - const SMDS_MeshCell *cell = dynamic_cast(ME); - assert(cell); - SMDS_Mesh::_meshList[myMeshId]->getGrid()->AddReferenceToCell(myVtkID, cell->getVtkId()); + const SMDS_MeshCell *cell = dynamic_cast (ME); + assert(cell); + SMDS_UnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid(); + vtkCellLinks *Links = grid->GetCellLinks(); + Links->ResizeCellList(myVtkID, 1); + Links->AddCellReference(cell->getVtkId(), myVtkID); } //======================================================================= diff --git a/src/SMDS/SMDS_MeshNode.hxx b/src/SMDS/SMDS_MeshNode.hxx index 02fc1ef61..773f39fcf 100644 --- a/src/SMDS/SMDS_MeshNode.hxx +++ b/src/SMDS/SMDS_MeshNode.hxx @@ -40,6 +40,7 @@ public: friend class SMESHDS_Mesh; friend class SMDS_Mesh; friend class ObjectPool; + friend class SMDS_VtkFace; void Print(std::ostream & OS) const; double X() const; diff --git a/src/SMDS/SMDS_VtkEdge.cxx b/src/SMDS/SMDS_VtkEdge.cxx index 6cd006d51..a314565c7 100644 --- a/src/SMDS/SMDS_VtkEdge.cxx +++ b/src/SMDS/SMDS_VtkEdge.cxx @@ -25,8 +25,8 @@ SMDS_VtkEdge::~SMDS_VtkEdge() void SMDS_VtkEdge::init(std::vector nodeIds, SMDS_Mesh* mesh) { + SMDS_MeshEdge::init(); vtkUnstructuredGrid* grid = mesh->getGrid(); - myIdInShape = -1; myMeshId = mesh->getMeshId(); vtkIdType aType = VTK_LINE; if (nodeIds.size() == 3) diff --git a/src/SMDS/SMDS_VtkFace.cxx b/src/SMDS/SMDS_VtkFace.cxx index 79a087709..0a7d5163f 100644 --- a/src/SMDS/SMDS_VtkFace.cxx +++ b/src/SMDS/SMDS_VtkFace.cxx @@ -24,8 +24,8 @@ SMDS_VtkFace::~SMDS_VtkFace() void SMDS_VtkFace::init(std::vector nodeIds, SMDS_Mesh* mesh) { + SMDS_MeshFace::init(); vtkUnstructuredGrid* grid = mesh->getGrid(); - myIdInShape = -1; myMeshId = mesh->getMeshId(); vtkIdType aType = VTK_TRIANGLE; switch (nodeIds.size()) @@ -53,8 +53,8 @@ void SMDS_VtkFace::init(std::vector nodeIds, SMDS_Mesh* mesh) void SMDS_VtkFace::initPoly(std::vector nodeIds, SMDS_Mesh* mesh) { + SMDS_MeshFace::init(); vtkUnstructuredGrid* grid = mesh->getGrid(); - myIdInShape = -1; myMeshId = mesh->getMeshId(); myVtkID = grid->InsertNextLinkedCell(VTK_POLYGON, nodeIds.size(), &nodeIds[0]); mesh->setMyModified(); @@ -249,7 +249,7 @@ SMDS_ElemIteratorPtr SMDS_VtkFace::interlacedNodesElemIterator() const } //! change only the first node, used for temporary triangles in quadrangle to triangle adaptor -void SMDS_VtkFace::ChangeApex(const SMDS_MeshNode* node) +void SMDS_VtkFace::ChangeApex(SMDS_MeshNode* node) { vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid(); vtkIdType npts = 0; @@ -257,6 +257,6 @@ void SMDS_VtkFace::ChangeApex(const SMDS_MeshNode* node) grid->GetCellPoints(myVtkID, npts, pts); grid->RemoveReferenceToCell(pts[0], myVtkID); pts[0] = node->getVtkId(); - grid->AddReferenceToCell(pts[0], myVtkID); + node->AddInverseElement(this), SMDS_Mesh::_meshList[myMeshId]->setMyModified(); } diff --git a/src/SMDS/SMDS_VtkFace.hxx b/src/SMDS/SMDS_VtkFace.hxx index 7a346fd55..ea1bf0ba8 100644 --- a/src/SMDS/SMDS_VtkFace.hxx +++ b/src/SMDS/SMDS_VtkFace.hxx @@ -16,7 +16,7 @@ public: void init(std::vector nodeIds, SMDS_Mesh* mesh); void initPoly(std::vector nodeIds, SMDS_Mesh* mesh); bool ChangeNodes(const SMDS_MeshNode* nodes[], const int nbNodes); - void ChangeApex(const SMDS_MeshNode* node); // to use only for tmp triangles + void ChangeApex(SMDS_MeshNode* node); // to use only for tmp triangles void Print(std::ostream & OS) const; int NbEdges() const; int NbFaces() const; diff --git a/src/SMDS/SMDS_VtkVolume.cxx b/src/SMDS/SMDS_VtkVolume.cxx index 3f5026f37..15664b610 100644 --- a/src/SMDS/SMDS_VtkVolume.cxx +++ b/src/SMDS/SMDS_VtkVolume.cxx @@ -21,8 +21,8 @@ SMDS_VtkVolume::SMDS_VtkVolume(std::vector nodeIds, SMDS_Mesh* mesh) */ void SMDS_VtkVolume::init(std::vector nodeIds, SMDS_Mesh* mesh) { + SMDS_MeshVolume::init(); vtkUnstructuredGrid* grid = mesh->getGrid(); - myIdInShape = -1; myMeshId = mesh->getMeshId(); vtkIdType aType = VTK_TETRA; switch (nodeIds.size()) @@ -63,6 +63,7 @@ void SMDS_VtkVolume::init(std::vector nodeIds, SMDS_Mesh* mesh) //#ifdef VTK_HAVE_POLYHEDRON void SMDS_VtkVolume::initPoly(std::vector nodeIds, std::vector nbNodesPerFace, SMDS_Mesh* mesh) { + SMDS_MeshVolume::init(); //MESSAGE("SMDS_VtkVolume::initPoly"); SMDS_UnstructuredGrid* grid = mesh->getGrid(); double center[3]; diff --git a/src/SMESH/Makefile.am b/src/SMESH/Makefile.am index 9db3b1450..475436428 100644 --- a/src/SMESH/Makefile.am +++ b/src/SMESH/Makefile.am @@ -60,6 +60,7 @@ salomeinclude_HEADERS = \ lib_LTLIBRARIES = libSMESHimpl.la dist_libSMESHimpl_la_SOURCES = \ + memoire.h \ SMESH_Gen.cxx \ SMESH_Mesh.cxx \ SMESH_subMesh.cxx \ diff --git a/src/SMESH/SMESH_Mesh.cxx b/src/SMESH/SMESH_Mesh.cxx index 39c2ca976..7a0b5130e 100644 --- a/src/SMESH/SMESH_Mesh.cxx +++ b/src/SMESH/SMESH_Mesh.cxx @@ -105,6 +105,23 @@ SMESH_Mesh::SMESH_Mesh(int theLocalId, _myMeshDS->ShapeToMesh( PseudoShape() ); } +//================================================================================ +/*! + * \brief Constructor of SMESH_Mesh being a base of some descendant class + */ +//================================================================================ + +SMESH_Mesh::SMESH_Mesh(): + _groupId( 0 ), _nbSubShapes( 0 ) +{ + _myMeshDS = 0; + _isShapeToMesh = false; + _isAutoColor = false; + _isModified = false; + _shapeDiagonal = 0.0; + _rmGroupCallUp = 0; +} + //============================================================================= /*! * @@ -265,14 +282,12 @@ void SMESH_Mesh::Clear() _myMeshDS->ClearMesh(); // update compute state of submeshes - if ( SMESH_subMesh *sm = GetSubMeshContaining( GetShapeToMesh() ) ) { - SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator(/*includeSelf=*/true, - /*complexShapeFirst=*/false); - while ( smIt->more() ) { - sm = smIt->next(); - sm->ComputeStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE ); - sm->ComputeStateEngine( SMESH_subMesh::CLEAN ); // for event listeners (issue 0020918) - } + if ( SMESH_subMesh *sm = GetSubMeshContaining( GetShapeToMesh() ) ) + { + sm->ComputeStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE ); + sm->ComputeSubMeshStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE ); + sm->ComputeStateEngine( SMESH_subMesh::CLEAN ); // for event listeners (issue 0020918) + sm->ComputeSubMeshStateEngine( SMESH_subMesh::CLEAN ); } _isModified = false; } diff --git a/src/SMESH/SMESH_Mesh.hxx b/src/SMESH/SMESH_Mesh.hxx index c88bbd02d..df5b281fb 100644 --- a/src/SMESH/SMESH_Mesh.hxx +++ b/src/SMESH/SMESH_Mesh.hxx @@ -332,7 +332,7 @@ protected: TRmGroupCallUp* _rmGroupCallUp; protected: - SMESH_Mesh() {}; + SMESH_Mesh(); SMESH_Mesh(const SMESH_Mesh&) {}; }; diff --git a/src/SMESH/SMESH_MeshEditor.cxx b/src/SMESH/SMESH_MeshEditor.cxx index 4a970ffa2..198cf0f2d 100644 --- a/src/SMESH/SMESH_MeshEditor.cxx +++ b/src/SMESH/SMESH_MeshEditor.cxx @@ -132,114 +132,125 @@ SMESH_MeshEditor::AddElement(const vector & node, int nbnode = node.size(); SMESHDS_Mesh* mesh = GetMeshDS(); switch ( type ) { - case SMDSAbs_0DElement: - if ( nbnode == 1 ) { - if ( ID >= 0 ) e = mesh->Add0DElementWithID(node[0], ID); - else e = mesh->Add0DElement (node[0] ); - } - break; - case SMDSAbs_Edge: - if ( nbnode == 2 ) { - if ( ID >= 0 ) e = mesh->AddEdgeWithID(node[0], node[1], ID); - else e = mesh->AddEdge (node[0], node[1] ); - } - else if ( nbnode == 3 ) { - if ( ID >= 0 ) e = mesh->AddEdgeWithID(node[0], node[1], node[2], ID); - else e = mesh->AddEdge (node[0], node[1], node[2] ); - } - break; case SMDSAbs_Face: if ( !isPoly ) { if (nbnode == 3) { if ( ID >= 0 ) e = mesh->AddFaceWithID(node[0], node[1], node[2], ID); - else e = mesh->AddFace (node[0], node[1], node[2] ); + else e = mesh->AddFace (node[0], node[1], node[2] ); } else if (nbnode == 4) { if ( ID >= 0 ) e = mesh->AddFaceWithID(node[0], node[1], node[2], node[3], ID); - else e = mesh->AddFace (node[0], node[1], node[2], node[3] ); + else e = mesh->AddFace (node[0], node[1], node[2], node[3] ); } else if (nbnode == 6) { if ( ID >= 0 ) e = mesh->AddFaceWithID(node[0], node[1], node[2], node[3], - node[4], node[5], ID); - else e = mesh->AddFace (node[0], node[1], node[2], node[3], - node[4], node[5] ); + node[4], node[5], ID); + else e = mesh->AddFace (node[0], node[1], node[2], node[3], + node[4], node[5] ); } else if (nbnode == 8) { if ( ID >= 0 ) e = mesh->AddFaceWithID(node[0], node[1], node[2], node[3], - node[4], node[5], node[6], node[7], ID); - else e = mesh->AddFace (node[0], node[1], node[2], node[3], - node[4], node[5], node[6], node[7] ); + node[4], node[5], node[6], node[7], ID); + else e = mesh->AddFace (node[0], node[1], node[2], node[3], + node[4], node[5], node[6], node[7] ); } } else { if ( ID >= 0 ) e = mesh->AddPolygonalFaceWithID(node, ID); - else e = mesh->AddPolygonalFace (node ); + else e = mesh->AddPolygonalFace (node ); } break; + case SMDSAbs_Volume: if ( !isPoly ) { if (nbnode == 4) { if ( ID >= 0 ) e = mesh->AddVolumeWithID(node[0], node[1], node[2], node[3], ID); - else e = mesh->AddVolume (node[0], node[1], node[2], node[3] ); + else e = mesh->AddVolume (node[0], node[1], node[2], node[3] ); } else if (nbnode == 5) { if ( ID >= 0 ) e = mesh->AddVolumeWithID(node[0], node[1], node[2], node[3], - node[4], ID); - else e = mesh->AddVolume (node[0], node[1], node[2], node[3], - node[4] ); + node[4], ID); + else e = mesh->AddVolume (node[0], node[1], node[2], node[3], + node[4] ); } else if (nbnode == 6) { if ( ID >= 0 ) e = mesh->AddVolumeWithID(node[0], node[1], node[2], node[3], - node[4], node[5], ID); - else e = mesh->AddVolume (node[0], node[1], node[2], node[3], - node[4], node[5] ); + node[4], node[5], ID); + else e = mesh->AddVolume (node[0], node[1], node[2], node[3], + node[4], node[5] ); } else if (nbnode == 8) { if ( ID >= 0 ) e = mesh->AddVolumeWithID(node[0], node[1], node[2], node[3], - node[4], node[5], node[6], node[7], ID); - else e = mesh->AddVolume (node[0], node[1], node[2], node[3], - node[4], node[5], node[6], node[7] ); + node[4], node[5], node[6], node[7], ID); + else e = mesh->AddVolume (node[0], node[1], node[2], node[3], + node[4], node[5], node[6], node[7] ); } else if (nbnode == 10) { if ( ID >= 0 ) e = mesh->AddVolumeWithID(node[0], node[1], node[2], node[3], - node[4], node[5], node[6], node[7], - node[8], node[9], ID); - else e = mesh->AddVolume (node[0], node[1], node[2], node[3], - node[4], node[5], node[6], node[7], - node[8], node[9] ); + node[4], node[5], node[6], node[7], + node[8], node[9], ID); + else e = mesh->AddVolume (node[0], node[1], node[2], node[3], + node[4], node[5], node[6], node[7], + node[8], node[9] ); } else if (nbnode == 13) { if ( ID >= 0 ) e = mesh->AddVolumeWithID(node[0], node[1], node[2], node[3], - node[4], node[5], node[6], node[7], - node[8], node[9], node[10],node[11], - node[12],ID); - else e = mesh->AddVolume (node[0], node[1], node[2], node[3], - node[4], node[5], node[6], node[7], - node[8], node[9], node[10],node[11], - node[12] ); + node[4], node[5], node[6], node[7], + node[8], node[9], node[10],node[11], + node[12],ID); + else e = mesh->AddVolume (node[0], node[1], node[2], node[3], + node[4], node[5], node[6], node[7], + node[8], node[9], node[10],node[11], + node[12] ); } else if (nbnode == 15) { if ( ID >= 0 ) e = mesh->AddVolumeWithID(node[0], node[1], node[2], node[3], - node[4], node[5], node[6], node[7], - node[8], node[9], node[10],node[11], - node[12],node[13],node[14],ID); - else e = mesh->AddVolume (node[0], node[1], node[2], node[3], - node[4], node[5], node[6], node[7], - node[8], node[9], node[10],node[11], - node[12],node[13],node[14] ); + node[4], node[5], node[6], node[7], + node[8], node[9], node[10],node[11], + node[12],node[13],node[14],ID); + else e = mesh->AddVolume (node[0], node[1], node[2], node[3], + node[4], node[5], node[6], node[7], + node[8], node[9], node[10],node[11], + node[12],node[13],node[14] ); } else if (nbnode == 20) { if ( ID >= 0 ) e = mesh->AddVolumeWithID(node[0], node[1], node[2], node[3], - node[4], node[5], node[6], node[7], - node[8], node[9], node[10],node[11], - node[12],node[13],node[14],node[15], - node[16],node[17],node[18],node[19],ID); - else e = mesh->AddVolume (node[0], node[1], node[2], node[3], - node[4], node[5], node[6], node[7], - node[8], node[9], node[10],node[11], - node[12],node[13],node[14],node[15], - node[16],node[17],node[18],node[19] ); + node[4], node[5], node[6], node[7], + node[8], node[9], node[10],node[11], + node[12],node[13],node[14],node[15], + node[16],node[17],node[18],node[19],ID); + else e = mesh->AddVolume (node[0], node[1], node[2], node[3], + node[4], node[5], node[6], node[7], + node[8], node[9], node[10],node[11], + node[12],node[13],node[14],node[15], + node[16],node[17],node[18],node[19] ); } } + break; + + case SMDSAbs_Edge: + if ( nbnode == 2 ) { + if ( ID >= 0 ) e = mesh->AddEdgeWithID(node[0], node[1], ID); + else e = mesh->AddEdge (node[0], node[1] ); + } + else if ( nbnode == 3 ) { + if ( ID >= 0 ) e = mesh->AddEdgeWithID(node[0], node[1], node[2], ID); + else e = mesh->AddEdge (node[0], node[1], node[2] ); + } + break; + + case SMDSAbs_0DElement: + if ( nbnode == 1 ) { + if ( ID >= 0 ) e = mesh->Add0DElementWithID(node[0], ID); + else e = mesh->Add0DElement (node[0] ); + } + break; + + case SMDSAbs_Node: + if ( ID >= 0 ) e = mesh->AddNodeWithID(node[0]->X(), node[0]->Y(), node[0]->Z(), ID); + else e = mesh->AddNode (node[0]->X(), node[0]->Y(), node[0]->Z()); + break; + + default:; } if ( e ) myLastCreatedElems.Append( e ); return e; @@ -3874,6 +3885,8 @@ void SMESH_MeshEditor::makeWalls (TNodeOfNodeListMap & mapNewNodes, const SMDS_MeshElement* elem = itElem->first; vector& vecNewNodes = itElemNodes->second; + if(itElem->second.size()==0) continue; + if ( elem->GetType() == SMDSAbs_Edge ) { // create a ceiling edge if (!elem->IsQuadratic()) { @@ -3898,8 +3911,6 @@ void SMESH_MeshEditor::makeWalls (TNodeOfNodeListMap & mapNewNodes, if ( elem->GetType() != SMDSAbs_Face ) continue; - if(itElem->second.size()==0) continue; - bool hasFreeLinks = false; TIDSortedElemSet avoidSet; diff --git a/src/SMESH/SMESH_subMesh.cxx b/src/SMESH/SMESH_subMesh.cxx index a02800b05..f90f792da 100644 --- a/src/SMESH/SMESH_subMesh.cxx +++ b/src/SMESH/SMESH_subMesh.cxx @@ -1700,7 +1700,7 @@ bool SMESH_subMesh::CheckComputeError(SMESH_Algo* theAlgo, const TopoDS_Shape& t // Check my state if ( !_computeError || _computeError->IsOK() ) { - _computeState = COMPUTE_OK; + _computeState = IsMeshComputed() ? COMPUTE_OK : FAILED_TO_COMPUTE; } else { diff --git a/src/SMESH/SMESH_subMesh.hxx b/src/SMESH/SMESH_subMesh.hxx index 58318b1e1..54ffcdac0 100644 --- a/src/SMESH/SMESH_subMesh.hxx +++ b/src/SMESH/SMESH_subMesh.hxx @@ -193,6 +193,7 @@ public: void DumpAlgoState(bool isMain); bool ComputeStateEngine(int event); + void ComputeSubMeshStateEngine(int event); bool Evaluate(MapShapeNbElems& aResMap); @@ -250,7 +251,6 @@ protected: void RemoveSubMeshElementsAndNodes(); void UpdateDependantsState(const compute_event theEvent); void UpdateSubMeshState(const compute_state theState); - void ComputeSubMeshStateEngine(int event); void CleanDependants(); void CleanDependsOn(); void SetAlgoState(int state); diff --git a/src/SMESHFiltersSelection/SMESH_Type.h b/src/SMESHFiltersSelection/SMESH_Type.h index 89857d89c..ee962f22e 100644 --- a/src/SMESHFiltersSelection/SMESH_Type.h +++ b/src/SMESHFiltersSelection/SMESH_Type.h @@ -25,7 +25,6 @@ // Author : Nicolas REJNERI // Project : SALOME // Module : SMESH -// $Header$ // #ifndef SMESH_TYPE_HEADER #define SMESH_TYPE_HEADER @@ -57,7 +56,8 @@ enum MeshObjectType { GROUP_FACE, GROUP_VOLUME, GROUP_0D, - COMPONENT + COMPONENT, + IDSOURCE }; #endif diff --git a/src/SMESHFiltersSelection/SMESH_TypeFilter.cxx b/src/SMESHFiltersSelection/SMESH_TypeFilter.cxx index 1fbb37516..a684d7023 100644 --- a/src/SMESHFiltersSelection/SMESH_TypeFilter.cxx +++ b/src/SMESHFiltersSelection/SMESH_TypeFilter.cxx @@ -203,6 +203,12 @@ bool SMESH_TypeFilter::isOk (const SUIT_DataOwner* theDataOwner) const Ok = true; break; } + case IDSOURCE: + { + Ok = ( SMESH_TypeFilter(MESHorSUBMESH).isOk( theDataOwner ) || + SMESH_TypeFilter(GROUP) .isOk( theDataOwner )); + break; + } } } return Ok; diff --git a/src/SMESHGUI/Makefile.am b/src/SMESHGUI/Makefile.am index 7e7448f59..6da5d4076 100644 --- a/src/SMESHGUI/Makefile.am +++ b/src/SMESHGUI/Makefile.am @@ -94,6 +94,7 @@ salomeinclude_HEADERS = \ SMESHGUI_MeshOrderDlg.h \ SMESHGUI_MeshOrderOp.h \ SMESHGUI_FileValidator.h \ + SMESHGUI_CopyMeshDlg.h \ SMESH_SMESHGUI.hxx # Libraries targets @@ -167,6 +168,7 @@ dist_libSMESH_la_SOURCES = \ SMESHGUI_FindElemByPointDlg.cxx \ SMESHGUI_MeshOrderDlg.cxx \ SMESHGUI_MeshOrderOp.cxx \ + SMESHGUI_CopyMeshDlg.cxx \ SMESHGUI_FileValidator.cxx MOC_FILES = \ @@ -224,6 +226,7 @@ MOC_FILES = \ SMESHGUI_Make2DFrom3DOp_moc.cxx \ SMESHGUI_FindElemByPointDlg_moc.cxx \ SMESHGUI_MeshOrderDlg_moc.cxx \ + SMESHGUI_CopyMeshDlg_moc.cxx \ SMESHGUI_MeshOrderOp_moc.cxx nodist_libSMESH_la_SOURCES= \ diff --git a/src/SMESHGUI/SMESHGUI.cxx b/src/SMESHGUI/SMESHGUI.cxx index efc9c9ea1..c78fd71d1 100644 --- a/src/SMESHGUI/SMESHGUI.cxx +++ b/src/SMESHGUI/SMESHGUI.cxx @@ -76,6 +76,7 @@ #include "SMESHGUI_TransparencyDlg.h" //#include "SMESHGUI_WhatIsDlg.h" #include "SMESHGUI_DuplicateNodesDlg.h" +#include "SMESHGUI_CopyMeshDlg.h" #include "SMESHGUI_Utils.h" #include "SMESHGUI_MeshUtils.h" @@ -141,6 +142,7 @@ #include #include #include +#include // SALOME KERNEL includes #include @@ -759,6 +761,14 @@ type = QObject::tr( "FREE_BORDERS" ); else if ( dynamic_cast< SMESH::Controls::FreeFaces* >( f.get() ) ) type = QObject::tr( "FREE_FACES" ); + else if ( dynamic_cast< SMESH::Controls::BareBorderVolume* >( f.get() ) ) + type = QObject::tr( "BARE_BORDER_VOLUME" ); + else if ( dynamic_cast< SMESH::Controls::BareBorderFace* >( f.get() ) ) + type = QObject::tr( "BARE_BORDER_FACE" ); + else if ( dynamic_cast< SMESH::Controls::OverConstrainedVolume* >( f.get() ) ) + type = QObject::tr( "OVER_CONSTRAINED_VOLUME" ); + else if ( dynamic_cast< SMESH::Controls::OverConstrainedFace* >( f.get() ) ) + type = QObject::tr( "OVER_CONSTRAINED_FACE" ); return type; } @@ -779,10 +789,26 @@ if ( aScalarBarActor && aFunctor ) { SMESH::Controls::NumericalFunctor* aNumFun = dynamic_cast( aFunctor.get() ); if ( aNumFun ) { - int nbRanges = aScalarBarActor->GetMaximumNumberOfColors(); + std::vector elements; + SMESH::SMESH_Mesh_var mesh = SMESH::IObjectToInterface(anIO); + if ( mesh->_is_nil() ) { + SMESH::SMESH_IDSource_var idSource = + SMESH::IObjectToInterface(anIO); + if ( !idSource->_is_nil() ) + { + SMESH::long_array_var ids = idSource->GetIDs(); + elements.resize( ids->length() ); + for ( unsigned i = 0; i < elements.size(); ++i ) + elements[i] = ids[i]; + } + } + int nbIntervals = aScalarBarActor->GetMaximumNumberOfColors(); + vtkLookupTable* lookupTable = + static_cast(aScalarBarActor->GetLookupTable()); + double * minmax = lookupTable->GetRange(); std::vector nbEvents; std::vector funValues; - aNumFun->GetHistogram( nbRanges, nbEvents, funValues ); + aNumFun->GetHistogram( nbIntervals, nbEvents, funValues, elements, minmax ); QString anInitialPath = ""; if ( SUIT_FileDlg::getLastVisitedPath().isEmpty() ) anInitialPath = QDir::currentPath(); @@ -826,11 +852,11 @@ if ( selected.Extent() == 1 ) { Handle(SALOME_InteractiveObject) anIO = selected.First(); if ( anIO->hasEntry() ) { - SMESH_Actor* anActor = SMESH::FindActorByEntry( anIO->getEntry() ); - if ( anActor && anActor->GetScalarBarActor() && anActor->GetControlMode() != SMESH_Actor::eNone ) { - SMESH_ScalarBarActor *aScalarBarActor = anActor->GetScalarBarActor(); - aScalarBarActor->SetDistributionVisibility(!aScalarBarActor->GetDistributionVisibility()); - } + SMESH_Actor* anActor = SMESH::FindActorByEntry( anIO->getEntry() ); + if ( anActor && anActor->GetScalarBarActor() && anActor->GetControlMode() != SMESH_Actor::eNone ) { + SMESH_ScalarBarActor *aScalarBarActor = anActor->GetScalarBarActor(); + aScalarBarActor->SetDistributionVisibility(!aScalarBarActor->GetDistributionVisibility()); + } } } } @@ -1178,6 +1204,18 @@ case 6023: aControl = SMESH_Actor::eMaxElementLength3D; break; + case 6024: + aControl = SMESH_Actor::eBareBorderVolume; + break; + case 6025: + aControl = SMESH_Actor::eBareBorderFace; + break; + case 6026: + aControl = SMESH_Actor::eOverConstrainedVolume; + break; + case 6027: + aControl = SMESH_Actor::eOverConstrainedFace; + break; } anActor->SetControlMode(aControl); anActor->GetScalarBarActor()->SetTitle( functorToString( anActor->GetFunctor() ).toLatin1().constData() ); @@ -2024,6 +2062,13 @@ bool SMESHGUI::OnGUIEvent( int theCommandID ) case 704: // Edit mesh/sub-mesh startOperation( theCommandID ); break; + case 705: // copy mesh + { + if (checkLock(aStudy)) break; + EmitSignalDeactivateDialog(); + ( new SMESHGUI_CopyMeshDlg( this ) )->show(); + } + break; case 710: // Build compound mesh { if (checkLock(aStudy)) break; @@ -2973,6 +3018,10 @@ bool SMESHGUI::OnGUIEvent( int theCommandID ) case 6021: case 6022: case 6023: + case 6024: + case 6025: + case 6026: + case 6027: if ( vtkwnd ) { LightApp_SelectionMgr* mgr = selectionMgr(); @@ -3189,6 +3238,7 @@ void SMESHGUI::initialize( CAM_Application* app ) createSMESHAction( 702, "CREATE_MESH", "ICON_DLG_INIT_MESH" ); createSMESHAction( 703, "CREATE_SUBMESH", "ICON_DLG_ADD_SUBMESH" ); createSMESHAction( 704, "EDIT_MESHSUBMESH","ICON_DLG_EDIT_MESH" ); + createSMESHAction( 705, "COPY_MESH", "ICON_COPY_MESH" ); createSMESHAction( 710, "BUILD_COMPOUND", "ICON_BUILD_COMPOUND" ); createSMESHAction( 711, "PRECOMPUTE", "ICON_PRECOMPUTE" ); createSMESHAction( 712, "EVALUATE", "ICON_COMPUTE" ); @@ -3214,6 +3264,10 @@ void SMESHGUI::initialize( CAM_Application* app ) createSMESHAction( 6021, "FREE_FACES", "ICON_FREE_FACES", 0, true ); createSMESHAction( 6022, "MAX_ELEMENT_LENGTH_2D", "ICON_MAX_ELEMENT_LENGTH_2D", 0, true ); createSMESHAction( 6023, "MAX_ELEMENT_LENGTH_3D", "ICON_MAX_ELEMENT_LENGTH_3D", 0, true ); + createSMESHAction( 6024, "BARE_BORDER_VOLUME","ICON_BARE_BORDER_VOLUME", 0, true ); + createSMESHAction( 6025, "BARE_BORDER_FACE","ICON_BARE_BORDER_FACE", 0, true ); + createSMESHAction( 6026, "OVER_CONSTRAINED_VOLUME","ICON_OVER_CONSTRAINED_VOLUME", 0, true ); + createSMESHAction( 6027, "OVER_CONSTRAINED_FACE","ICON_OVER_CONSTRAINED_FACE", 0, true ); createSMESHAction( 6003, "FREE_BORDER", "ICON_FREE_EDGE_2D", 0, true ); createSMESHAction( 6004, "CONNECTION", "ICON_CONNECTION", 0, true ); createSMESHAction( 6005, "FREE_NODE", "ICON_FREE_NODE", 0, true ); @@ -3353,6 +3407,7 @@ void SMESHGUI::initialize( CAM_Application* app ) createMenu( 703, meshId, -1 ); createMenu( 704, meshId, -1 ); createMenu( 710, meshId, -1 ); + createMenu( 705, meshId, -1 ); createMenu( separator(), meshId, -1 ); createMenu( 701, meshId, -1 ); createMenu( 711, meshId, -1 ); @@ -3371,8 +3426,6 @@ void SMESHGUI::initialize( CAM_Application* app ) createMenu( separator(), meshId, -1 ); createMenu( 814, meshId, -1 ); createMenu( separator(), meshId, -1 ); - createMenu( 813, meshId, -1 ); - createMenu( separator(), meshId, -1 ); createMenu( 900, meshId, -1 ); //createMenu( 902, meshId, -1 ); createMenu( 903, meshId, -1 ); @@ -3385,6 +3438,8 @@ void SMESHGUI::initialize( CAM_Application* app ) createMenu( 6001, edgeId, -1 ); createMenu( 6004, edgeId, -1 ); createMenu( 6021, faceId, -1 ); + createMenu( 6025, faceId, -1 ); + createMenu( 6027, faceId, -1 ); createMenu( 6018, faceId, -1 ); createMenu( 6019, faceId, -1 ); createMenu( 6011, faceId, -1 ); @@ -3397,6 +3452,8 @@ void SMESHGUI::initialize( CAM_Application* app ) createMenu( 6017, volumeId, -1 ); createMenu( 6009, volumeId, -1 ); createMenu( 6023, volumeId, -1 ); + createMenu( 6024, volumeId, -1 ); + createMenu( 6026, volumeId, -1 ); createMenu( 4000, addId, -1 ); createMenu( 4009, addId, -1 ); @@ -3420,6 +3477,8 @@ void SMESHGUI::initialize( CAM_Application* app ) createMenu( 4042, removeId, -1 ); createMenu( 4044, removeId, -1 ); createMenu( separator(), removeId, -1 ); + createMenu( 813, removeId, -1 ); + createMenu( separator(), removeId, -1 ); createMenu( 4043, removeId, -1 ); createMenu( 4051, renumId, -1 ); @@ -3464,6 +3523,7 @@ void SMESHGUI::initialize( CAM_Application* app ) createTool( 703, meshTb ); createTool( 704, meshTb ); createTool( 710, meshTb ); + createTool( 705, meshTb ); createTool( separator(), meshTb ); createTool( 701, meshTb ); createTool( 711, meshTb ); @@ -3490,6 +3550,8 @@ void SMESHGUI::initialize( CAM_Application* app ) createTool( 6004, ctrlTb ); createTool( separator(), ctrlTb ); createTool( 6021, ctrlTb ); + createTool( 6025, ctrlTb ); + createTool( 6027, ctrlTb ); createTool( 6018, ctrlTb ); createTool( 6019, ctrlTb ); createTool( 6011, ctrlTb ); @@ -3503,6 +3565,8 @@ void SMESHGUI::initialize( CAM_Application* app ) createTool( 6017, ctrlTb ); createTool( 6009, ctrlTb ); createTool( 6023, ctrlTb ); + createTool( 6024, ctrlTb ); + createTool( 6026, ctrlTb ); createTool( separator(), ctrlTb ); createTool( 4000, addRemTb ); @@ -3805,50 +3869,58 @@ void SMESHGUI::initialize( CAM_Application* app ) aSubId = popupMgr()->insert( tr( "MEN_FACE_CTRL" ), anId, -1 ); // FACE CONTROLS - popupMgr()->insert( action( 6021 ), aSubId, -1 ); // FREE_FACE + popupMgr()->insert ( action( 6021 ), aSubId, -1 ); // FREE_FACE popupMgr()->setRule( action( 6021 ), aMeshInVtkHasFaces /*aMeshInVtkHasVolumes*/, QtxPopupMgr::VisibleRule ); popupMgr()->setRule( action( 6021 ), "controlMode = 'eFreeFaces'", QtxPopupMgr::ToggleRule ); - popupMgr()->insert( action( 6018 ), aSubId, -1 ); // LENGTH_2D + popupMgr()->insert ( action( 6018 ), aSubId, -1 ); // LENGTH_2D popupMgr()->setRule( action( 6018 ), aMeshInVtkHasFaces, QtxPopupMgr::VisibleRule ); popupMgr()->setRule( action( 6018 ), "controlMode = 'eLength2D'", QtxPopupMgr::ToggleRule ); - popupMgr()->insert( action( 6019 ), aSubId, -1 ); // CONNECTION_2D + popupMgr()->insert ( action( 6019 ), aSubId, -1 ); // CONNECTION_2D popupMgr()->setRule( action( 6019 ), aMeshInVtkHasFaces, QtxPopupMgr::VisibleRule ); popupMgr()->setRule( action( 6019 ), "controlMode = 'eMultiConnection2D'", QtxPopupMgr::ToggleRule ); - popupMgr()->insert( action( 6011 ), aSubId, -1 ); // AREA + popupMgr()->insert ( action( 6011 ), aSubId, -1 ); // AREA popupMgr()->setRule( action( 6011 ), aMeshInVtkHasFaces, QtxPopupMgr::VisibleRule ); popupMgr()->setRule( action( 6011 ), "controlMode = 'eArea'", QtxPopupMgr::ToggleRule ); - popupMgr()->insert( action( 6012 ), aSubId, -1 ); // TAPER + popupMgr()->insert ( action( 6012 ), aSubId, -1 ); // TAPER popupMgr()->setRule( action( 6012 ), aMeshInVtkHasFaces, QtxPopupMgr::VisibleRule ); popupMgr()->setRule( action( 6012 ), "controlMode = 'eTaper'", QtxPopupMgr::ToggleRule ); - popupMgr()->insert( action( 6013 ), aSubId, -1 ); // ASPECT + popupMgr()->insert ( action( 6013 ), aSubId, -1 ); // ASPECT popupMgr()->setRule( action( 6013 ), aMeshInVtkHasFaces, QtxPopupMgr::VisibleRule ); popupMgr()->setRule( action( 6013 ), "controlMode = 'eAspectRatio'", QtxPopupMgr::ToggleRule ); - popupMgr()->insert( action( 6014 ), aSubId, -1 ); // MIN_ANG + popupMgr()->insert ( action( 6014 ), aSubId, -1 ); // MIN_ANG popupMgr()->setRule( action( 6014 ), aMeshInVtkHasFaces, QtxPopupMgr::VisibleRule ); popupMgr()->setRule( action( 6014 ), "controlMode = 'eMinimumAngle'", QtxPopupMgr::ToggleRule ); - popupMgr()->insert( action( 6015 ), aSubId, -1 ); // WARP + popupMgr()->insert ( action( 6015 ), aSubId, -1 ); // WARP popupMgr()->setRule( action( 6015 ), aMeshInVtkHasFaces, QtxPopupMgr::VisibleRule ); popupMgr()->setRule( action( 6015 ), "controlMode = 'eWarping'", QtxPopupMgr::ToggleRule ); - popupMgr()->insert( action( 6016 ), aSubId, -1 ); // SKEW + popupMgr()->insert ( action( 6016 ), aSubId, -1 ); // SKEW popupMgr()->setRule( action( 6016 ), aMeshInVtkHasFaces, QtxPopupMgr::VisibleRule ); popupMgr()->setRule( action( 6016 ), "controlMode = 'eSkew'", QtxPopupMgr::ToggleRule ); - popupMgr()->insert( action( 6022 ), aSubId, -1 ); // MAX_ELEMENT_LENGTH_2D + popupMgr()->insert ( action( 6022 ), aSubId, -1 ); // MAX_ELEMENT_LENGTH_2D popupMgr()->setRule( action( 6022 ), aMeshInVtkHasFaces, QtxPopupMgr::VisibleRule ); popupMgr()->setRule( action( 6022 ), "controlMode = 'eMaxElementLength2D'", QtxPopupMgr::ToggleRule ); + popupMgr()->insert ( action( 6025 ), aSubId, -1 ); // BARE_BORDER_FACE + popupMgr()->setRule( action( 6025 ), aMeshInVtkHasFaces, QtxPopupMgr::VisibleRule ); + popupMgr()->setRule( action( 6025 ), "controlMode = 'eBareBorderFace'", QtxPopupMgr::ToggleRule ); + + popupMgr()->insert ( action( 6027 ), aSubId, -1 ); // OVER_CONSTRAINED_FACE + popupMgr()->setRule( action( 6027 ), aMeshInVtkHasFaces, QtxPopupMgr::VisibleRule ); + popupMgr()->setRule( action( 6027 ), "controlMode = 'eOverConstrainedFace'", QtxPopupMgr::ToggleRule ); + aSubId = popupMgr()->insert( tr( "MEN_VOLUME_CTRL" ), anId, -1 ); // VOLUME CONTROLS - popupMgr()->insert( action( 6017 ), aSubId, -1 ); // ASPECT_3D + popupMgr()->insert ( action( 6017 ), aSubId, -1 ); // ASPECT_3D popupMgr()->setRule( action( 6017 ), aMeshInVtkHasVolumes, QtxPopupMgr::VisibleRule ); popupMgr()->setRule( action( 6017 ), "controlMode = 'eAspectRatio3D'", QtxPopupMgr::ToggleRule ); @@ -3856,10 +3928,18 @@ void SMESHGUI::initialize( CAM_Application* app ) popupMgr()->setRule( action( 6009 ), aMeshInVtkHasVolumes, QtxPopupMgr::VisibleRule ); popupMgr()->setRule( action( 6009 ), "controlMode = 'eVolume3D'", QtxPopupMgr::ToggleRule ); - popupMgr()->insert( action( 6023 ), aSubId, -1 ); // MAX_ELEMENT_LENGTH_3D + popupMgr()->insert ( action( 6023 ), aSubId, -1 ); // MAX_ELEMENT_LENGTH_3D popupMgr()->setRule( action( 6023 ), aMeshInVtkHasVolumes, QtxPopupMgr::VisibleRule ); popupMgr()->setRule( action( 6023 ), "controlMode = 'eMaxElementLength3D'", QtxPopupMgr::ToggleRule ); + popupMgr()->insert ( action( 6024 ), aSubId, -1 ); // BARE_BORDER_VOLUME + popupMgr()->setRule( action( 6024 ), aMeshInVtkHasVolumes, QtxPopupMgr::VisibleRule ); + popupMgr()->setRule( action( 6024 ), "controlMode = 'eBareBorderVolume'", QtxPopupMgr::ToggleRule ); + + popupMgr()->insert ( action( 6026 ), aSubId, -1 ); // OVER_CONSTRAINED_VOLUME + popupMgr()->setRule( action( 6026 ), aMeshInVtkHasVolumes, QtxPopupMgr::VisibleRule ); + popupMgr()->setRule( action( 6026 ), "controlMode = 'eOverConstrainedVolume'", QtxPopupMgr::ToggleRule ); + popupMgr()->insert( separator(), anId, -1 ); popupMgr()->insert( action( 201 ), anId, -1 ); // SCALAR_BAR_PROP @@ -5359,7 +5439,15 @@ void SMESHGUI::restoreVisualParameters (int savePoint) aPlaneInfo.PlaneId = aPlaneId; aPlaneInfo.ActorList.push_back( aSmeshActor ); aPlaneInfo.ViewManager = vman; - aPlaneInfoList.push_back( aPlaneInfo ); + + // to make the list sorted by plane id + anIter = aPlaneInfoList.begin(); + for( ; anIter != aPlaneInfoList.end(); anIter++ ) { + const TPlaneInfo& aPlaneInfoRef = *anIter; + if( aPlaneInfoRef.PlaneId > aPlaneId ) + break; + } + aPlaneInfoList.insert( anIter, aPlaneInfo ); } } } @@ -5370,6 +5458,52 @@ void SMESHGUI::restoreVisualParameters (int savePoint) } // for names/parameters iterator } // for entries iterator + // take into account planes with empty list of actors referred to them + QList aVMList; + getApp()->viewManagers(SVTK_Viewer::Type(), aVMList); + + TPlaneDataMap::const_iterator aPlaneDataIter = aPlaneDataMap.begin(); + for( ; aPlaneDataIter != aPlaneDataMap.end(); aPlaneDataIter++ ) { + int aViewId = aPlaneDataIter->first; + if( aViewId >= 0 && aViewId < aVMList.count() ) { + SUIT_ViewManager* aViewManager = aVMList.at( aViewId ); + + const TPlaneDataList& aPlaneDataList = aPlaneDataIter->second; + + TPlaneInfoList& aPlaneInfoList = aPlaneInfoMap[ aViewId ]; + TPlaneDataList::const_iterator anIter2 = aPlaneDataList.begin(); + for( ; anIter2 != aPlaneDataList.end(); anIter2++ ) { + const TPlaneData& aPlaneData = *anIter2; + int aPlaneId = aPlaneData.Id; + + bool anIsFound = false; + TPlaneInfoList::const_iterator anIter3 = aPlaneInfoList.begin(); + for( ; anIter3 != aPlaneInfoList.end(); anIter3++ ) { + const TPlaneInfo& aPlaneInfo = *anIter3; + if( aPlaneInfo.PlaneId == aPlaneId ) { + anIsFound = true; + break; + } + } + + if( !anIsFound ) { + TPlaneInfo aPlaneInfo; // ActorList field is empty + aPlaneInfo.PlaneId = aPlaneId; + aPlaneInfo.ViewManager = aViewManager; + + // to make the list sorted by plane id + TPlaneInfoList::iterator anIter4 = aPlaneInfoList.begin(); + for( ; anIter4 != aPlaneInfoList.end(); anIter4++ ) { + const TPlaneInfo& aPlaneInfoRef = *anIter4; + if( aPlaneInfoRef.PlaneId > aPlaneId ) + break; + } + aPlaneInfoList.insert( anIter4, aPlaneInfo ); + } + } + } + } + // add clipping planes to actors according to the restored parameters // and update the clipping plane map TPlaneInfoMap::const_iterator anIter1 = aPlaneInfoMap.begin(); diff --git a/src/SMESHGUI/SMESHGUI_ClippingDlg.cxx b/src/SMESHGUI/SMESHGUI_ClippingDlg.cxx index ac190be77..486a859ac 100644 --- a/src/SMESHGUI/SMESHGUI_ClippingDlg.cxx +++ b/src/SMESHGUI/SMESHGUI_ClippingDlg.cxx @@ -194,7 +194,8 @@ private: struct TSetVisibility { TSetVisibility(int theIsVisible): myIsVisible(theIsVisible){} void operator()(SMESH::TPlaneData& thePlaneData){ - thePlaneData.Plane.GetPointer()->myActor->SetVisibility(myIsVisible); + bool anIsEmpty = thePlaneData.ActorList.empty(); + thePlaneData.Plane.GetPointer()->myActor->SetVisibility(myIsVisible && !anIsEmpty); } int myIsVisible; }; @@ -261,11 +262,22 @@ SMESH::OrientedPlane* SMESHGUI_ClippingDlg::AddPlane (SMESH::TActorList vtkFloatingPointType aBounds[6]; vtkFloatingPointType anOrigin[3]; - bool anIsOk = SMESH::ComputeClippingPlaneParameters( theActorList, - aNormal, - theDistance, - aBounds, - anOrigin ); + + bool anIsOk = false; + if( theActorList.empty() ) { + // to support planes with empty actor list we should create + // a nullified plane that will be initialized later + anOrigin[0] = anOrigin[1] = anOrigin[2] = 0; + aBounds[0] = aBounds[2] = aBounds[4] = 0; + aBounds[1] = aBounds[3] = aBounds[5] = 0; + anIsOk = true; + } + else + anIsOk = SMESH::ComputeClippingPlaneParameters( theActorList, + aNormal, + theDistance, + aBounds, + anOrigin ); if( !anIsOk ) return NULL; @@ -545,8 +557,10 @@ void SMESHGUI_ClippingDlg::ClickOnApply() SMESH::TPlaneData aPlaneData = *anIter2; SMESH::TPlane aPlane = aPlaneData.Plane; SMESH::TActorList anActorList = aPlaneData.ActorList; - if( anActorList.empty() ) - continue; + + // the check is disabled to support planes with empty actor list + //if( anActorList.empty() ) + // continue; SMESH::OrientedPlane* anOrientedPlane = SMESH::OrientedPlane::New(myViewWindow); anOrientedPlane->ShallowCopy(aPlane.GetPointer()); diff --git a/src/SMESHGUI/SMESHGUI_CopyMeshDlg.cxx b/src/SMESHGUI/SMESHGUI_CopyMeshDlg.cxx new file mode 100644 index 000000000..f4b6950bf --- /dev/null +++ b/src/SMESHGUI/SMESHGUI_CopyMeshDlg.cxx @@ -0,0 +1,667 @@ +// Copyright (C) 2007-2010 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// +// SMESH SMESHGUI : GUI for SMESH component +// File : SMESHGUI_CopyMeshDlg.cxx + +#include "SMESHGUI_CopyMeshDlg.h" + +#include "SMESHGUI.h" +#include "SMESHGUI_SpinBox.h" +#include "SMESHGUI_Utils.h" +#include "SMESHGUI_VTKUtils.h" +#include "SMESHGUI_MeshUtils.h" +#include "SMESHGUI_IdValidator.h" +#include "SMESHGUI_FilterDlg.h" + +#include +#include +#include + +// SALOME GUI includes +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +// SALOME KERNEL includes +#include + +// OCCT includes +#include + +// Qt includes +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// IDL includes +#include +#include CORBA_SERVER_HEADER(SMESH_Group) +#include CORBA_SERVER_HEADER(SMESH_MeshEditor) + +/*! + \class BusyLocker + \brief Simple 'busy state' flag locker. + \internal +*/ + +namespace +{ + class BusyLocker + { + public: + //! Constructor. Sets passed boolean flag to \c true. + BusyLocker( bool& busy ) : myBusy( busy ) { myBusy = true; } + //! Destructor. Clear external boolean flag passed as parameter to the constructor to \c false. + ~BusyLocker() { myBusy = false; } + private: + bool& myBusy; //! External 'busy state' boolean flag + }; +} + +#define SPACING 6 +#define MARGIN 11 + +//To disable automatic genericobj management, the following line should be commented. +//Otherwise, it should be uncommented. Refer to KERNEL_SRC/src/SALOMEDSImpl/SALOMEDSImpl_AttributeIOR.cxx +#define WITHGENERICOBJ + + +//================================================================================ +/*! + * \brief Constructor + */ +//================================================================================ + +SMESHGUI_CopyMeshDlg::SMESHGUI_CopyMeshDlg( SMESHGUI* theModule ) + : QDialog( SMESH::GetDesktop( theModule ) ), + mySMESHGUI( theModule ), + mySelectionMgr( SMESH::GetSelectionMgr( theModule ) ), + myFilterDlg(0), + mySelectedObject(SMESH::SMESH_IDSource::_nil()) +{ + QPixmap image (SMESH::GetResourceMgr( mySMESHGUI )->loadPixmap("SMESH", tr("ICON_COPY_MESH"))); + + setModal(false); + setAttribute(Qt::WA_DeleteOnClose, true); + setWindowTitle(tr("SMESH_COPY_MESH_TITLE")); + setSizeGripEnabled(true); + + QVBoxLayout* SMESHGUI_CopyMeshDlgLayout = new QVBoxLayout(this); + SMESHGUI_CopyMeshDlgLayout->setSpacing(SPACING); + SMESHGUI_CopyMeshDlgLayout->setMargin(MARGIN); + + /***************************************************************/ + ConstructorsBox = new QGroupBox(tr("SMESH_COPY_MESH_TITLE"), this); + QButtonGroup* GroupConstructors = new QButtonGroup(this); + QHBoxLayout* ConstructorsBoxLayout = new QHBoxLayout(ConstructorsBox); + ConstructorsBoxLayout->setSpacing(SPACING); + ConstructorsBoxLayout->setMargin(MARGIN); + + QRadioButton* RadioButton1= new QRadioButton(ConstructorsBox); + RadioButton1->setIcon(image); + GroupConstructors->addButton(RadioButton1, 0); + + ConstructorsBoxLayout->addWidget(RadioButton1); + RadioButton1->setChecked(true); + GroupConstructors->addButton(RadioButton1, 0); + + /***************************************************************/ + GroupArguments = new QGroupBox(tr("SMESH_ARGUMENTS"), this); + QGridLayout* GroupArgumentsLayout = new QGridLayout(GroupArguments); + GroupArgumentsLayout->setSpacing(SPACING); + GroupArgumentsLayout->setMargin(MARGIN); + + myIdValidator = new SMESHGUI_IdValidator(this); + + // Controls for idSource/elements selection + myTextLabelElements = new QLabel(tr("OBJECT_NAME"), GroupArguments); + myLineEditElements = new QLineEdit(GroupArguments); + myLineEditElements->setValidator(myIdValidator); + myLineEditElements->setMaxLength(-1); + myFilterBtn = new QPushButton( tr( "SMESH_BUT_FILTER" ), GroupArguments ); + connect(myFilterBtn, SIGNAL(clicked()), this, SLOT(setFilters())); + + // Control for the mesh objects selection + myIdSourceCheck = new QCheckBox(tr("SMESH_SELECT_WHOLE_MESH"), GroupArguments); + + // Name of a mesh to create + QLabel* meshNameLabel = new QLabel(tr("NEW_NAME"), GroupArguments); + myMeshNameEdit = new QLineEdit(GroupArguments); + + // CheckBox for copying groups + myCopyGroupsCheck = new QCheckBox(tr("SMESH_MAKE_GROUPS"), GroupArguments); + myCopyGroupsCheck->setChecked(false); + + // CheckBox for keeping ids + myKeepIdsCheck = new QCheckBox(tr("SMESH_KEEP_IDS"), GroupArguments); + myKeepIdsCheck->setChecked(true); + + // layout + GroupArgumentsLayout->addWidget(myTextLabelElements, 0, 0); + GroupArgumentsLayout->addWidget(myLineEditElements, 0, 1, 1, 5); + GroupArgumentsLayout->addWidget(myFilterBtn, 0, 6); + GroupArgumentsLayout->addWidget(myIdSourceCheck, 1, 0, 1, 6); + GroupArgumentsLayout->addWidget(meshNameLabel, 2, 0); + GroupArgumentsLayout->addWidget(myMeshNameEdit, 2, 1, 1, 5); + GroupArgumentsLayout->addWidget(myCopyGroupsCheck, 3, 0, 1, 6); + GroupArgumentsLayout->addWidget(myKeepIdsCheck, 4, 0, 1, 6); + + /***************************************************************/ + GroupButtons = new QGroupBox(this); + QHBoxLayout* GroupButtonsLayout = new QHBoxLayout(GroupButtons); + GroupButtonsLayout->setSpacing(SPACING); + GroupButtonsLayout->setMargin(MARGIN); + + buttonOk = new QPushButton(tr("SMESH_BUT_APPLY_AND_CLOSE"), GroupButtons); + buttonOk->setAutoDefault(true); + buttonOk->setDefault(true); + buttonApply = new QPushButton(tr("SMESH_BUT_APPLY"), GroupButtons); + buttonApply->setAutoDefault(true); + buttonCancel = new QPushButton(tr("SMESH_BUT_CLOSE"), GroupButtons); + buttonCancel->setAutoDefault(true); + buttonHelp = new QPushButton(tr("SMESH_BUT_HELP"), GroupButtons); + buttonHelp->setAutoDefault(true); + + GroupButtonsLayout->addWidget(buttonOk); + GroupButtonsLayout->addSpacing(10); + GroupButtonsLayout->addWidget(buttonApply); + GroupButtonsLayout->addSpacing(10); + GroupButtonsLayout->addStretch(); + GroupButtonsLayout->addWidget(buttonCancel); + GroupButtonsLayout->addWidget(buttonHelp); + + /***************************************************************/ + SMESHGUI_CopyMeshDlgLayout->addWidget(ConstructorsBox); + SMESHGUI_CopyMeshDlgLayout->addWidget(GroupArguments); + SMESHGUI_CopyMeshDlgLayout->addWidget(GroupButtons); + + /* Initialisations */ + mySelector = (SMESH::GetViewWindow( mySMESHGUI ))->GetSelector(); + + mySMESHGUI->SetActiveDialogBox((QDialog*)this); + + // Selection filter + myIdSourceFilter = new SMESH_TypeFilter( IDSOURCE ); + + myHelpFileName = "copy_mesh_page.html"; + + Init(); + + /* signals and slots connections */ + connect(buttonOk, SIGNAL(clicked()), this, SLOT(ClickOnOk())); + connect(buttonCancel, SIGNAL(clicked()), this, SLOT(ClickOnCancel())); + connect(buttonApply, SIGNAL(clicked()), this, SLOT(ClickOnApply())); + connect(buttonHelp, SIGNAL(clicked()), this, SLOT(ClickOnHelp())); + + connect(mySMESHGUI, SIGNAL (SignalDeactivateActiveDialog()), + this, SLOT (DeactivateActiveDialog())); + connect(mySelectionMgr, SIGNAL (currentSelectionChanged()), + this, SLOT (SelectionIntoArgument())); + connect(mySMESHGUI, SIGNAL (SignalCloseAllDialogs()),/* to close dialog if study change */ + this, SLOT (ClickOnCancel())); + + connect(myLineEditElements, SIGNAL(textChanged(const QString&)), + this, SLOT (onTextChange(const QString&))); + connect(myIdSourceCheck, SIGNAL(toggled(bool)), + this, SLOT (onSelectIdSource(bool))); + + SelectionIntoArgument(); +} + +//================================================================================= +// function : ~SMESHGUI_CopyMeshDlg() +// purpose : Destroys the object and frees any allocated resources +//================================================================================= + +SMESHGUI_CopyMeshDlg::~SMESHGUI_CopyMeshDlg() +{ + if ( myFilterDlg ) + { + myFilterDlg->setParent( 0 ); + delete myFilterDlg; myFilterDlg = 0; + } + if ( myIdSourceFilter ) + { + if ( mySelectionMgr ) + mySelectionMgr->removeFilter( myIdSourceFilter ); + delete myIdSourceFilter; myIdSourceFilter=0; + } +} + +//================================================================================= +// function : Init() +// purpose : +//================================================================================= +void SMESHGUI_CopyMeshDlg::Init (bool ResetControls) +{ + myBusy = false; + + myMeshNameEdit->setText( SMESH::UniqueMeshName("Mesh")); + if ( ResetControls ) + { + myLineEditElements->clear(); + //myElementsId = ""; + myNbOkElements = 0; + + buttonOk->setEnabled(false); + buttonApply->setEnabled(false); + + myActor = 0; + myMesh = SMESH::SMESH_Mesh::_nil(); + + myIdSourceCheck->setChecked(true); + myCopyGroupsCheck->setChecked(false); + myKeepIdsCheck->setChecked(false); + + onSelectIdSource( myIdSourceCheck->isChecked() ); + } +} + +//================================================================================= +// function : ClickOnApply() +// purpose : +//================================================================================= + +bool SMESHGUI_CopyMeshDlg::ClickOnApply() +{ + if (mySMESHGUI->isActiveStudyLocked()) + return false; + + if( !isValid() ) + return false; + + try + { + SUIT_OverrideCursor aWaitCursor; + SMESH::SMESH_IDSource_var aPartToCopy; + if ( myIdSourceCheck->isChecked()) + { + aPartToCopy = mySelectedObject; + } + else + { + QStringList aListElementsId = myLineEditElements->text().split(" ", QString::SkipEmptyParts); + SMESH::long_array_var anElementsId = new SMESH::long_array; + anElementsId->length(aListElementsId.count()); + for (int i = 0; i < aListElementsId.count(); i++) + anElementsId[i] = aListElementsId[i].toInt(); + + SMESH::SMESH_MeshEditor_var aMeshEditor = myMesh->GetMeshEditor(); + aPartToCopy = aMeshEditor->MakeIDSource( anElementsId, SMESH::ALL ); + } + QByteArray meshName = myMeshNameEdit->text().toLatin1(); + bool toCopyGroups = ( myCopyGroupsCheck->isChecked() ); + bool toKeepIDs = ( myKeepIdsCheck->isChecked() ); + + SMESH::SMESH_Gen_var gen = SMESHGUI::GetSMESHGen(); + SMESH::SMESH_Mesh_var newMesh = + gen->CopyMesh(aPartToCopy, meshName.constData(), toCopyGroups, toKeepIDs); +#ifdef WITHGENERICOBJ + // obj has been published in study. Its refcount has been incremented. + // It is safe to decrement its refcount + // so that it will be destroyed when the entry in study will be removed + newMesh->Destroy(); +#endif + } catch (...) { + } + + mySMESHGUI->updateObjBrowser(true); + SMESHGUI::Modified(); + + Init(false); + mySelectedObject = SMESH::SMESH_IDSource::_nil(); + SelectionIntoArgument(); + + return true; +} + +//================================================================================= +// function : ClickOnOk() +// purpose : +//================================================================================= +void SMESHGUI_CopyMeshDlg::ClickOnOk() +{ + if( ClickOnApply() ) + ClickOnCancel(); +} + +//================================================================================= +// function : ClickOnCancel() +// purpose : +//================================================================================= +void SMESHGUI_CopyMeshDlg::ClickOnCancel() +{ + disconnect(mySelectionMgr, 0, this, 0); + if ( mySelectionMgr ) + mySelectionMgr->removeFilter( myIdSourceFilter ); + if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI )) + aViewWindow->SetSelectionMode( ActorSelection ); + mySMESHGUI->ResetState(); + reject(); +} + +//================================================================================= +// function : ClickOnHelp() +// purpose : +//================================================================================= +void SMESHGUI_CopyMeshDlg::ClickOnHelp() +{ + LightApp_Application* app = (LightApp_Application*)(SUIT_Session::session()->activeApplication()); + if (app) + app->onHelpContextModule(mySMESHGUI ? app->moduleName(mySMESHGUI->moduleName()) : QString(""), myHelpFileName); + else { + QString platform; +#ifdef WIN32 + platform = "winapplication"; +#else + platform = "application"; +#endif + SUIT_MessageBox::warning(this, tr("WRN_WARNING"), + tr("EXTERNAL_BROWSER_CANNOT_SHOW_PAGE"). + arg(app->resourceMgr()->stringValue("ExternalBrowser", + platform)). + arg(myHelpFileName)); + } +} + +//======================================================================= +// function : onTextChange() +// purpose : +//======================================================================= + +void SMESHGUI_CopyMeshDlg::onTextChange (const QString& theNewText) +{ + QLineEdit* send = (QLineEdit*)sender(); + + if (myBusy) return; + BusyLocker lock( myBusy ); + + //if (send == myLineEditElements) + myNbOkElements = 0; + + buttonOk->setEnabled(false); + buttonApply->setEnabled(false); + + // hilight entered elements + SMDS_Mesh* aMesh = 0; + if (myActor) + aMesh = myActor->GetObject()->GetMesh(); + + QStringList aListId = theNewText.split(" ", QString::SkipEmptyParts); + if (myActor && aMesh) + { + TColStd_MapOfInteger newIndices; + if (send == myLineEditElements) { + for (int i = 0; i < aListId.count(); i++) + if ( const SMDS_MeshElement * e = aMesh->FindElement(aListId[ i ].toInt())) + { + newIndices.Add(e->GetID()); + } + } + myNbOkElements = newIndices.Extent(); + + Handle(SALOME_InteractiveObject) anIO = myActor->getIO(); + mySelector->AddOrRemoveIndex( anIO, newIndices, false ); + if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI )) + aViewWindow->highlight( anIO, true, true ); + } + else + { + myNbOkElements = aListId.count(); + } + + if (myNbOkElements) { + buttonOk->setEnabled(true); + buttonApply->setEnabled(true); + } +} + +//================================================================================= +// function : SelectionIntoArgument() +// purpose : Called when selection as changed or other case +//================================================================================= + +void SMESHGUI_CopyMeshDlg::SelectionIntoArgument() +{ + if (myBusy) return; + BusyLocker lock( myBusy ); + + // clear + myActor = 0; + QString aString = ""; + + myLineEditElements->setText(aString); + myNbOkElements = 0; + buttonOk->setEnabled(false); + buttonApply->setEnabled(false); + myFilterBtn->setEnabled(false); + + // get selected mesh + SALOME_ListIO aList; + mySelectionMgr->selectedObjects(aList,SVTK_Viewer::Type()); + int nbSel = aList.Extent(); + if (nbSel != 1) + return; + + Handle(SALOME_InteractiveObject) IO = aList.First(); + mySelectedObject = SMESH::IObjectToInterface( IO ); + if ( mySelectedObject->_is_nil() ) + return; + + myMesh = SMESH::GetMeshByIO(IO); + if (myMesh->_is_nil()) + return; + + myActor = SMESH::FindActorByEntry(IO->getEntry()); + if (!myActor) + myActor = SMESH::FindActorByObject(myMesh); + + if (myIdSourceCheck->isChecked()) + { + SMESH::GetNameOfSelectedIObjects( mySelectionMgr, aString ); + if ( aString.isEmpty() ) aString = " "; + } + else + { + SMESH::GetNameOfSelectedElements( mySelector, IO, aString ); + myNbOkElements = aString.size(); + myFilterBtn->setEnabled(true); + } + myLineEditElements->setText( aString ); + bool ok = !aString.isEmpty(); + + buttonOk->setEnabled(ok); + buttonApply->setEnabled(ok); +} + +//======================================================================= +//function : onSelectIdSource +//purpose : +//======================================================================= +void SMESHGUI_CopyMeshDlg::onSelectIdSource (bool toSelectMesh) +{ + if (toSelectMesh) + myTextLabelElements->setText(tr("OBJECT_NAME")); + else + myTextLabelElements->setText(tr("ELEM_IDS")); + + if (toSelectMesh) { + myLineEditElements->clear(); + } + + mySelectionMgr->clearFilters(); + mySelectionMgr->installFilter(myIdSourceFilter); + SMESH::SetPointRepresentation(false); + + if (toSelectMesh) { + if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI )) + aViewWindow->SetSelectionMode( ActorSelection ); + myLineEditElements->setReadOnly(true); + myLineEditElements->setValidator(0); + } + else + { + if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI )) + aViewWindow->SetSelectionMode( CellSelection ); + myLineEditElements->setReadOnly(false); + myLineEditElements->setValidator(myIdValidator); + onTextChange(myLineEditElements->text()); + } + + SelectionIntoArgument(); +} + +//================================================================================= +// function : isValid +// purpose : +//================================================================================= + +bool SMESHGUI_CopyMeshDlg::isValid() +{ + if ( myIdSourceCheck->isChecked() ) + return !mySelectedObject->_is_nil(); + + return myNbOkElements > 0; +} + +//================================================================================= +// function : DeactivateActiveDialog() +// purpose : +//================================================================================= +void SMESHGUI_CopyMeshDlg::DeactivateActiveDialog() +{ + if (ConstructorsBox->isEnabled()) { + ConstructorsBox->setEnabled(false); + GroupArguments->setEnabled(false); + GroupButtons->setEnabled(false); + mySMESHGUI->ResetState(); + mySMESHGUI->SetActiveDialogBox(0); + if ( mySelectionMgr ) + mySelectionMgr->removeFilter( myIdSourceFilter ); + } +} + +//================================================================================= +// function : ActivateThisDialog() +// purpose : +//================================================================================= +void SMESHGUI_CopyMeshDlg::ActivateThisDialog() +{ + /* Emit a signal to deactivate the active dialog */ + mySMESHGUI->EmitSignalDeactivateDialog(); + ConstructorsBox->setEnabled(true); + GroupArguments->setEnabled(true); + GroupButtons->setEnabled(true); + + mySMESHGUI->SetActiveDialogBox((QDialog*)this); + + onSelectIdSource( myIdSourceCheck->isChecked() ); + + SelectionIntoArgument(); +} + +//================================================================================= +// function : enterEvent() +// purpose : +//================================================================================= +void SMESHGUI_CopyMeshDlg::enterEvent (QEvent*) +{ + if (!ConstructorsBox->isEnabled()) + ActivateThisDialog(); +} + +//================================================================================= +// function : closeEvent() +// purpose : +//================================================================================= +void SMESHGUI_CopyMeshDlg::closeEvent (QCloseEvent*) +{ + /* same than click on cancel button */ + ClickOnCancel(); +} + +//======================================================================= +//function : hideEvent +//purpose : caused by ESC key +//======================================================================= +void SMESHGUI_CopyMeshDlg::hideEvent (QHideEvent*) +{ + if (!isMinimized()) + ClickOnCancel(); +} + +//================================================================================= +// function : keyPressEvent() +// purpose : +//================================================================================= +void SMESHGUI_CopyMeshDlg::keyPressEvent( QKeyEvent* e ) +{ + QDialog::keyPressEvent( e ); + if ( e->isAccepted() ) + return; + + if ( e->key() == Qt::Key_F1 ) { + e->accept(); + ClickOnHelp(); + } +} + +//================================================================================= +// function : setFilters() +// purpose : SLOT. Called when "Filter" button pressed. +//================================================================================= +void SMESHGUI_CopyMeshDlg::setFilters() +{ + if(myMesh->_is_nil()) { + SUIT_MessageBox::critical(this, + tr("SMESH_ERROR"), + tr("NO_MESH_SELECTED")); + return; + } + if ( !myFilterDlg ) + myFilterDlg = new SMESHGUI_FilterDlg( mySMESHGUI, SMESH::ALL ); + + myFilterDlg->SetSelection(); + myFilterDlg->SetMesh( myMesh ); + myFilterDlg->SetSourceWg( myLineEditElements ); + + myFilterDlg->show(); +} diff --git a/src/SMESHGUI/SMESHGUI_CopyMeshDlg.h b/src/SMESHGUI/SMESHGUI_CopyMeshDlg.h new file mode 100644 index 000000000..83fcd095b --- /dev/null +++ b/src/SMESHGUI/SMESHGUI_CopyMeshDlg.h @@ -0,0 +1,125 @@ +// Copyright (C) 2007-2010 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +// SMESH SMESHGUI : GUI for SMESH component +// File : SMESHGUI_CopyMeshDlg.h +// +#ifndef SMESHGUI_CopyMeshDLG_H +#define SMESHGUI_CopyMeshDLG_H + +// SMESH includes +#include "SMESH_SMESHGUI.hxx" + +// Qt includes +#include + +// IDL includes +#include +#include CORBA_SERVER_HEADER(SMESH_Mesh) + +class QCheckBox; +class QGroupBox; +class QLabel; +class QLineEdit; +class QPushButton; + +class SMESHGUI; +class SMESHGUI_IdValidator; +class SMESHGUI_FilterDlg; +class SMESH_Actor; +class SVTK_Selector; +class LightApp_SelectionMgr; +class SUIT_SelectionFilter; + +//================================================================================= +// class : SMESHGUI_CopyMeshDlg +// purpose : copy some elements or a mesh object into a new mesh +//================================================================================= + +class SMESHGUI_EXPORT SMESHGUI_CopyMeshDlg : public QDialog +{ + Q_OBJECT + +public: + SMESHGUI_CopyMeshDlg( SMESHGUI* ); + ~SMESHGUI_CopyMeshDlg(); + +private: + void Init( bool = true ); + void closeEvent( QCloseEvent* ); + void enterEvent( QEvent* ); /* mouse enter the QWidget */ + void hideEvent( QHideEvent* ); /* ESC key */ + void keyPressEvent( QKeyEvent* ); + int GetConstructorId(); + void setNewMeshName(); + + bool isValid(); + + SMESHGUI* mySMESHGUI; /* Current SMESHGUI object */ + SMESHGUI_IdValidator* myIdValidator; + LightApp_SelectionMgr* mySelectionMgr; /* User shape selection */ + int myNbOkElements; /* to check when elements are defined */ + + SVTK_Selector* mySelector; + + bool myBusy; + SMESH::SMESH_Mesh_var myMesh; + SMESH_Actor* myActor; + SUIT_SelectionFilter* myIdSourceFilter; + + SMESH::SMESH_IDSource_var mySelectedObject; + + QGroupBox* ConstructorsBox; + QGroupBox* GroupArguments; + QGroupBox* GroupButtons; + + QPushButton* buttonOk; + QPushButton* buttonCancel; + QPushButton* buttonApply; + QPushButton* buttonHelp; + + QLabel* myTextLabelElements; + QLineEdit* myLineEditElements; + QLineEdit* myMeshNameEdit; + QCheckBox* myIdSourceCheck; + QCheckBox* myCopyGroupsCheck; + QCheckBox* myKeepIdsCheck; + + QPushButton* myFilterBtn; + SMESHGUI_FilterDlg* myFilterDlg; + + QString myHelpFileName; + +private slots: + void ClickOnOk(); + void ClickOnCancel(); + bool ClickOnApply(); + void ClickOnHelp(); + void SelectionIntoArgument(); + void DeactivateActiveDialog(); + void ActivateThisDialog(); + void onTextChange( const QString& ); + void onSelectIdSource( bool ); + void setFilters(); +}; + +#endif // SMESHGUI_CopyMeshDLG_H diff --git a/src/SMESHGUI/SMESHGUI_FilterDlg.cxx b/src/SMESHGUI/SMESHGUI_FilterDlg.cxx index ee88f7662..de2d8e05d 100755 --- a/src/SMESHGUI/SMESHGUI_FilterDlg.cxx +++ b/src/SMESHGUI/SMESHGUI_FilterDlg.cxx @@ -1169,18 +1169,22 @@ void SMESHGUI_FilterTable::SetCriterion (const int theRow, aTable->item( theRow, 2 )->setText( QString( theCriterion.ThresholdID ) ); } else if (theCriterion.Type != SMESH::FT_RangeOfIds && - theCriterion.Type != SMESH::FT_BelongToGeom && - theCriterion.Type != SMESH::FT_BelongToPlane && - theCriterion.Type != SMESH::FT_BelongToCylinder && - theCriterion.Type != SMESH::FT_BelongToGenSurface && - theCriterion.Type != SMESH::FT_LyingOnGeom && - theCriterion.Type != SMESH::FT_CoplanarFaces && - theCriterion.Type != SMESH::FT_FreeBorders && - theCriterion.Type != SMESH::FT_FreeEdges && - theCriterion.Type != SMESH::FT_FreeNodes && - theCriterion.Type != SMESH::FT_FreeFaces && - theCriterion.Type != SMESH::FT_BadOrientedVolume && - theCriterion.Type != SMESH::FT_LinearOrQuadratic) + theCriterion.Type != SMESH::FT_BelongToGeom && + theCriterion.Type != SMESH::FT_BelongToPlane && + theCriterion.Type != SMESH::FT_BelongToCylinder && + theCriterion.Type != SMESH::FT_BelongToGenSurface && + theCriterion.Type != SMESH::FT_LyingOnGeom && + theCriterion.Type != SMESH::FT_CoplanarFaces && + theCriterion.Type != SMESH::FT_FreeBorders && + theCriterion.Type != SMESH::FT_FreeEdges && + theCriterion.Type != SMESH::FT_FreeNodes && + theCriterion.Type != SMESH::FT_FreeFaces && + theCriterion.Type != SMESH::FT_BadOrientedVolume && + theCriterion.Type != SMESH::FT_BareBorderFace && + theCriterion.Type != SMESH::FT_BareBorderVolume && + theCriterion.Type != SMESH::FT_OverConstrainedFace && + theCriterion.Type != SMESH::FT_OverConstrainedVolume && + theCriterion.Type != SMESH::FT_LinearOrQuadratic) { aTable->item( theRow, 2 )->setText(QString("%1").arg(theCriterion.Threshold, 0, 'g', 15)); } @@ -1341,10 +1345,14 @@ void SMESHGUI_FilterTable::updateAdditionalWidget() aCriterion != SMESH::FT_RangeOfIds && aCriterion != SMESH::FT_FreeEdges && aCriterion != SMESH::FT_FreeFaces && - aCriterion != SMESH::FT_BadOrientedVolume) + aCriterion != SMESH::FT_BadOrientedVolume && + aCriterion != SMESH::FT_BareBorderFace && + aCriterion != SMESH::FT_BareBorderVolume && + aCriterion != SMESH::FT_OverConstrainedFace && + aCriterion != SMESH::FT_OverConstrainedVolume) || aCriterion == SMESH::FT_CoplanarFaces); - + if (!myAddWidgets.contains(anItem)) { myAddWidgets[ anItem ] = new AdditionalWidget(myWgStack); @@ -1520,9 +1528,13 @@ void SMESHGUI_FilterTable::onCriterionChanged (const int row, const int col, con if ((aType == SMESH::NODE && aCriterionType == SMESH::FT_FreeNodes ) || (aType == SMESH::EDGE && aCriterionType == SMESH::FT_FreeBorders ) || - (aType == SMESH::FACE && (aCriterionType == SMESH::FT_FreeEdges || + (aType == SMESH::FACE && (aCriterionType == SMESH::FT_BareBorderFace || + aCriterionType == SMESH::FT_OverConstrainedFace || + aCriterionType == SMESH::FT_FreeEdges || aCriterionType == SMESH::FT_FreeFaces)) || - (aType == SMESH::VOLUME && aCriterionType == SMESH::FT_BadOrientedVolume) || + (aType == SMESH::VOLUME && (aCriterionType == SMESH::FT_BadOrientedVolume || + aCriterionType == SMESH::FT_OverConstrainedVolume || + aCriterionType == SMESH::FT_BareBorderVolume)) || aCriterionType == SMESH::FT_LinearOrQuadratic || aCriterionType == SMESH::FT_GroupColor || aCriterionType == SMESH::FT_ElemGeomType || @@ -1808,6 +1820,8 @@ const QMap& SMESHGUI_FilterTable::getCriteria (const int theType) aCriteria[ SMESH::FT_Length2D ] = tr("LENGTH2D"); aCriteria[ SMESH::FT_MultiConnection2D ] = tr("MULTI2D_BORDERS"); aCriteria[ SMESH::FT_FreeFaces ] = tr("FREE_FACES"); + aCriteria[ SMESH::FT_BareBorderFace ] = tr("BARE_BORDER_FACE"); + aCriteria[ SMESH::FT_OverConstrainedFace] = tr("OVER_CONSTRAINED_FACE"); aCriteria[ SMESH::FT_LinearOrQuadratic ] = tr("LINEAR"); aCriteria[ SMESH::FT_GroupColor ] = tr("GROUP_COLOR"); aCriteria[ SMESH::FT_ElemGeomType ] = tr("GEOM_TYPE"); @@ -1820,16 +1834,18 @@ const QMap& SMESHGUI_FilterTable::getCriteria (const int theType) static QMap aCriteria; if (aCriteria.isEmpty()) { - aCriteria[ SMESH::FT_AspectRatio3D ] = tr("ASPECT_RATIO_3D"); - aCriteria[ SMESH::FT_RangeOfIds ] = tr("RANGE_OF_IDS"); - aCriteria[ SMESH::FT_BelongToGeom ] = tr("BELONG_TO_GEOM"); - aCriteria[ SMESH::FT_LyingOnGeom ] = tr("LYING_ON_GEOM"); - aCriteria[ SMESH::FT_BadOrientedVolume ] = tr("BAD_ORIENTED_VOLUME"); - aCriteria[ SMESH::FT_Volume3D ] = tr("VOLUME_3D"); - aCriteria[ SMESH::FT_MaxElementLength3D ] = tr("MAX_ELEMENT_LENGTH_3D"); - aCriteria[ SMESH::FT_LinearOrQuadratic ] = tr("LINEAR"); - aCriteria[ SMESH::FT_GroupColor ] = tr("GROUP_COLOR"); - aCriteria[ SMESH::FT_ElemGeomType ] = tr("GEOM_TYPE"); + aCriteria[ SMESH::FT_AspectRatio3D ] = tr("ASPECT_RATIO_3D"); + aCriteria[ SMESH::FT_RangeOfIds ] = tr("RANGE_OF_IDS"); + aCriteria[ SMESH::FT_BelongToGeom ] = tr("BELONG_TO_GEOM"); + aCriteria[ SMESH::FT_LyingOnGeom ] = tr("LYING_ON_GEOM"); + aCriteria[ SMESH::FT_BadOrientedVolume ] = tr("BAD_ORIENTED_VOLUME"); + aCriteria[ SMESH::FT_BareBorderVolume ] = tr("BARE_BORDER_VOLUME"); + aCriteria[ SMESH::FT_OverConstrainedVolume] = tr("OVER_CONSTRAINED_VOLUME"); + aCriteria[ SMESH::FT_Volume3D ] = tr("VOLUME_3D"); + aCriteria[ SMESH::FT_MaxElementLength3D ] = tr("MAX_ELEMENT_LENGTH_3D"); + aCriteria[ SMESH::FT_LinearOrQuadratic ] = tr("LINEAR"); + aCriteria[ SMESH::FT_GroupColor ] = tr("GROUP_COLOR"); + aCriteria[ SMESH::FT_ElemGeomType ] = tr("GEOM_TYPE"); } return aCriteria; } diff --git a/src/SMESHGUI/SMESHGUI_Hypotheses.cxx b/src/SMESHGUI/SMESHGUI_Hypotheses.cxx index a964d8cfc..30aeaa3c8 100644 --- a/src/SMESHGUI/SMESHGUI_Hypotheses.cxx +++ b/src/SMESHGUI/SMESHGUI_Hypotheses.cxx @@ -309,7 +309,7 @@ void SMESHGUI_GenericHypothesisCreator::onDialogFinished( int result ) disconnect( myDlg, SIGNAL( finished( int ) ), this, SLOT( onDialogFinished( int ) ) ); myDlg->close(); - //delete myDlg; + //delete myDlg; since WA_DeleteOnClose==true myDlg = 0; emit finished( result ); } @@ -557,6 +557,8 @@ QString SMESHGUI_GenericHypothesisCreator::helpPage() const aHelpFileName = "segments_around_vertex_algo_page.html"; else if ( aHypType == "QuadrangleParams") aHelpFileName = "a2d_meshing_hypo_page.html#hypo_quad_params_anchor"; + else if ( aHypType == "ImportSource1D" || aHypType == "ImportSource2D") + aHelpFileName = "import_algos_page.html"; return aHelpFileName; } diff --git a/src/SMESHGUI/SMESHGUI_MeshInfo.cxx b/src/SMESHGUI/SMESHGUI_MeshInfo.cxx index 255951008..15ab58726 100644 --- a/src/SMESHGUI/SMESHGUI_MeshInfo.cxx +++ b/src/SMESHGUI/SMESHGUI_MeshInfo.cxx @@ -60,8 +60,9 @@ #include #include CORBA_SERVER_HEADER(SMESH_Group) -const int SPACING = 6; -const int MARGIN = 9; +const int SPACING = 6; +const int MARGIN = 9; +const int MAXITEMS = 10; /*! \class SMESHGUI_MeshInfo @@ -465,8 +466,29 @@ void SMESHGUI_MeshInfo::setFieldsVisible( int start, int end, bool on ) \param parent parent widget */ SMESHGUI_ElemInfo::SMESHGUI_ElemInfo( QWidget* parent ) -: QWidget( parent ), myActor( 0 ), myID( 0 ), myIsElement( -1 ) +: QWidget( parent ), myActor( 0 ), myIsElement( -1 ) { + myFrame = new QWidget( this ); + myExtra = new QWidget( this ); + myCurrent = new QLabel( "10/43 items shown", myExtra ); + myCurrent->setAlignment( Qt::AlignRight | Qt::AlignVCenter ); + myPrev = new QPushButton( tr( "<<" ), myExtra ); + myNext = new QPushButton( tr( ">>" ), myExtra ); + QHBoxLayout* hbl = new QHBoxLayout( myExtra ); + hbl->setContentsMargins( 0, SPACING, 0, 0 ); + hbl->setSpacing( SPACING ); + hbl->addStretch(); + hbl->addWidget( myCurrent ); + hbl->addWidget( myPrev ); + hbl->addWidget( myNext ); + QVBoxLayout* vbl = new QVBoxLayout( this ); + vbl->setMargin( 0 ); + vbl->setSpacing( 0 ); + vbl->addWidget( myFrame ); + vbl->addWidget( myExtra ); + connect( myPrev, SIGNAL( clicked() ), this, SLOT( showPrevious() ) ); + connect( myNext, SIGNAL( clicked() ), this, SLOT( showNext() ) ); + clear(); } /*! @@ -484,7 +506,6 @@ void SMESHGUI_ElemInfo::setSource( SMESH_Actor* actor ) { if ( myActor != actor ) { myActor = actor; - myID = 0; myIsElement = -1; clear(); } @@ -492,19 +513,87 @@ void SMESHGUI_ElemInfo::setSource( SMESH_Actor* actor ) /*! \brief Show mesh element information - \param long id mesh node / element ID + \param id mesh node / element ID \param isElem show mesh element information if \c true or mesh node information if \c false */ void SMESHGUI_ElemInfo::showInfo( long id, bool isElem ) { - myID = id; + QSet ids; + ids << id; + showInfo( ids, isElem ); +} + +/*! + \brief Show mesh element information + \param ids mesh nodes / elements identifiers + \param isElem show mesh element information if \c true or mesh node information if \c false +*/ +void SMESHGUI_ElemInfo::showInfo( QSet ids, bool isElem ) +{ + QList newIds = ids.toList(); + qSort( newIds ); + if ( myIDs == newIds && myIsElement == isElem ) return; + + myIDs = newIds; myIsElement = isElem; + myIndex = 0; + updateControls(); + information( myIDs.mid( myIndex*MAXITEMS, MAXITEMS ) ); } /*! - \fn void SMESHGUI_ElemInfo::clear() \brief Clear mesh element information widget */ +void SMESHGUI_ElemInfo::clear() +{ + myIDs.clear(); + myIndex = 0; + clearInternal(); + updateControls(); +} + +/*! + \brief Get central area widget + \return central widget +*/ +QWidget* SMESHGUI_ElemInfo::frame() const +{ + return myFrame; +} + +/*! + \brief Get actor + \return actor being used +*/ +SMESH_Actor* SMESHGUI_ElemInfo::actor() const +{ + return myActor; +} + +/*! + \brief Get current info mode. + \return \c true if mesh element information is shown or \c false if node information is shown +*/ +bool SMESHGUI_ElemInfo::isElements() const +{ + return myIsElement; +} + +/*! + \fn void SMESHGUI_ElemInfo::information( const QList& ids ) + \brief Show information on the specified nodes / elements + + This function is to be redefined in sub-classes. + + \param ids nodes / elements identifiers information is to be shown on +*/ + +/*! + \brief Internal clean-up (reset widget) +*/ +void SMESHGUI_ElemInfo::clearInternal() +{ +} /*! \brief Get node connectivity @@ -560,6 +649,39 @@ SMESHGUI_ElemInfo::XYZ SMESHGUI_ElemInfo::gravityCenter( const SMDS_MeshElement* return xyz; } +/*! + \brief This slot is called from "Show Previous" button click. + Shows information on the previous group of the items. +*/ +void SMESHGUI_ElemInfo::showPrevious() +{ + myIndex = qMax( 0, myIndex-1 ); + updateControls(); + information( myIDs.mid( myIndex*MAXITEMS, MAXITEMS ) ); +} + +/*! + \brief This slot is called from "Show Next" button click. + Shows information on the next group of the items. +*/ +void SMESHGUI_ElemInfo::showNext() +{ + myIndex = qMin( myIndex+1, myIDs.count() / MAXITEMS ); + updateControls(); + information( myIDs.mid( myIndex*MAXITEMS, MAXITEMS ) ); +} + +/*! + \brief Update widgets state +*/ +void SMESHGUI_ElemInfo::updateControls() +{ + myExtra->setVisible( myIDs.count() > MAXITEMS ); + myCurrent->setText( tr( "X_FROM_Y_ITEMS_SHOWN" ).arg( myIndex*MAXITEMS+1 ).arg(qMin(myIndex*MAXITEMS+MAXITEMS, myIDs.count())).arg( myIDs.count() ) ); + myPrev->setEnabled( myIndex > 0 ); + myNext->setEnabled( (myIndex+1)*MAXITEMS < myIDs.count() ); +} + /*! \class SMESHGUI_SimpleElemInfo \brief Represents mesh element information in the simple text area. @@ -572,148 +694,43 @@ SMESHGUI_ElemInfo::XYZ SMESHGUI_ElemInfo::gravityCenter( const SMDS_MeshElement* SMESHGUI_SimpleElemInfo::SMESHGUI_SimpleElemInfo( QWidget* parent ) : SMESHGUI_ElemInfo( parent ) { - myInfo = new QTextBrowser( this ); - QVBoxLayout* l = new QVBoxLayout( this ); + myInfo = new QTextBrowser( frame() ); + QVBoxLayout* l = new QVBoxLayout( frame() ); l->setMargin( 0 ); l->addWidget( myInfo ); } /*! \brief Show mesh element information - \param long id mesh node / element ID - \param isElem show mesh element information if \c true or mesh node information if \c false + \param ids mesh nodes / elements identifiers */ -void SMESHGUI_SimpleElemInfo::showInfo( long id, bool isElem ) +void SMESHGUI_SimpleElemInfo::information( const QList& ids ) { - if ( myID == id && myIsElement == isElem ) return; - - SMESHGUI_ElemInfo::showInfo( id, isElem ); - - clear(); + clearInternal(); - if ( myActor ) { + if ( actor() ) { int precision = SMESHGUI::resourceMgr()->integerValue( "SMESH", "length_precision", 6 ); - if ( !isElem ) { - // - // show node info - // - const SMDS_MeshElement* e = myActor->GetObject()->GetMesh()->FindNode( id ); - if ( !e ) return; - const SMDS_MeshNode* node = static_cast( e ); - - // node ID - myInfo->append( QString( "%1 #%2" ).arg( tr( "NODE" ) ).arg( id ) ); - // separator - myInfo->append( "" ); - // coordinates - myInfo->append( QString( "%1: (%2, %3, %4)" ).arg( tr( "COORDINATES" ) ). - arg( node->X(), 0, precision > 0 ? 'f' : 'g', qAbs( precision ) ). - arg( node->Y(), 0, precision > 0 ? 'f' : 'g', qAbs( precision ) ). - arg( node->Z(), 0, precision > 0 ? 'f' : 'g', qAbs( precision ) ) ); - // separator - myInfo->append( "" ); - // connectivity - Connectivity connectivity = nodeConnectivity( node ); - if ( !connectivity.isEmpty() ) { - myInfo->append( QString( "%1:" ).arg( tr( "CONNECTIVITY" ) ) ); - QString con = formatConnectivity( connectivity, SMDSAbs_0DElement ); - if ( !con.isEmpty() ) - myInfo->append( QString( "- %1: %2" ).arg( tr( "0D_ELEMENTS" ) ).arg( con ) ); - con = formatConnectivity( connectivity, SMDSAbs_Edge ); - if ( !con.isEmpty() ) - myInfo->append( QString( "- %1: %2" ).arg( tr( "EDGES" ) ).arg( con ) ); - con = formatConnectivity( connectivity, SMDSAbs_Face ); - if ( !con.isEmpty() ) - myInfo->append( QString( "- %1: %2" ).arg( tr( "FACES" ) ).arg( con ) ); - con = formatConnectivity( connectivity, SMDSAbs_Volume ); - if ( !con.isEmpty() ) - myInfo->append( QString( "- %1: %2" ).arg( tr( "VOLUMES" ) ).arg( con ) ); - } - else { - myInfo->append( QString( "%1" ).arg( tr( "FREE_NODE" ) ).arg( id ) ); - } - } - else { - // - // show element info - // - const SMDS_MeshElement* e = myActor->GetObject()->GetMesh()->FindElement( id ); - if ( !e ) return; - - // element ID && type - QString stype; - switch( e->GetType() ) { - case SMDSAbs_0DElement: - stype = tr( "0D ELEMENT" ); break; - case SMDSAbs_Edge: - stype = tr( "EDGE" ); break; - case SMDSAbs_Face: - stype = tr( "FACE" ); break; - case SMDSAbs_Volume: - stype = tr( "VOLUME" ); break; - default: - break; - } - if ( stype.isEmpty() ) return; - myInfo->append( QString( "%1 #%2" ).arg( stype ).arg( id ) ); - // separator - myInfo->append( "" ); - // geometry type - QString gtype; - switch( e->GetEntityType() ) { - case SMDSEntity_Triangle: - case SMDSEntity_Quad_Triangle: - gtype = tr( "TRIANGLE" ); break; - case SMDSEntity_Quadrangle: - case SMDSEntity_Quad_Quadrangle: - gtype = tr( "QUADRANGLE" ); break; - case SMDSEntity_Polygon: - case SMDSEntity_Quad_Polygon: - gtype = tr( "POLYGON" ); break; - case SMDSEntity_Tetra: - case SMDSEntity_Quad_Tetra: - gtype = tr( "TETRAHEDRON" ); break; - case SMDSEntity_Pyramid: - case SMDSEntity_Quad_Pyramid: - gtype = tr( "PYRAMID" ); break; - case SMDSEntity_Hexa: - case SMDSEntity_Quad_Hexa: - gtype = tr( "HEXAHEDRON" ); break; - case SMDSEntity_Penta: - case SMDSEntity_Quad_Penta: - gtype = tr( "PRISM" ); break; - case SMDSEntity_Polyhedra: - case SMDSEntity_Quad_Polyhedra: - gtype = tr( "POLYHEDRON" ); break; - default: - break; - } - if ( !gtype.isEmpty() ) - myInfo->append( QString( "%1: %2" ).arg( tr( "TYPE" ) ).arg( gtype ) ); - // quadratic flag and gravity center (any element except 0D) - if ( e->GetEntityType() > SMDSEntity_0D && e->GetEntityType() < SMDSEntity_Last ) { - // quadratic flag - myInfo->append( QString( "%1? %2" ).arg( tr( "QUADRATIC" ) ).arg( e->IsQuadratic() ? tr( "YES" ) : tr( "NO" ) ) ); + foreach ( long id, ids ) { + if ( !isElements() ) { + // + // show node info + // + const SMDS_MeshElement* e = actor()->GetObject()->GetMesh()->FindNode( id ); + if ( !e ) return; + const SMDS_MeshNode* node = static_cast( e ); + + // node ID + myInfo->append( QString( "%1 #%2" ).arg( tr( "NODE" ) ).arg( id ) ); // separator myInfo->append( "" ); - // gravity center - XYZ gc = gravityCenter( e ); - myInfo->append( QString( "%1: (%2, %3, %4)" ).arg( tr( "GRAVITY_CENTER" ) ).arg( gc.x() ).arg( gc.y() ).arg( gc.z() ) ); - } - // separator - myInfo->append( "" ); - // connectivity - SMDS_ElemIteratorPtr nodeIt = e->nodesIterator(); - for ( int idx = 1; nodeIt->more(); idx++ ) { - const SMDS_MeshNode* node = static_cast( nodeIt->next() ); - // node number and ID - myInfo->append( QString( "%1 %2/%3 - #%4" ).arg( tr( "NODE" ) ).arg( idx ).arg( e->NbNodes() ).arg( node->GetID() ) ); - // node coordinates + // coordinates myInfo->append( QString( "%1: (%2, %3, %4)" ).arg( tr( "COORDINATES" ) ). arg( node->X(), 0, precision > 0 ? 'f' : 'g', qAbs( precision ) ). arg( node->Y(), 0, precision > 0 ? 'f' : 'g', qAbs( precision ) ). arg( node->Z(), 0, precision > 0 ? 'f' : 'g', qAbs( precision ) ) ); - // node connectivity + // separator + myInfo->append( "" ); + // connectivity Connectivity connectivity = nodeConnectivity( node ); if ( !connectivity.isEmpty() ) { myInfo->append( QString( "%1:" ).arg( tr( "CONNECTIVITY" ) ) ); @@ -733,17 +750,123 @@ void SMESHGUI_SimpleElemInfo::showInfo( long id, bool isElem ) else { myInfo->append( QString( "%1" ).arg( tr( "FREE_NODE" ) ).arg( id ) ); } + } + else { + // + // show element info + // + const SMDS_MeshElement* e = actor()->GetObject()->GetMesh()->FindElement( id ); + if ( !e ) return; + + // element ID && type + QString stype; + switch( e->GetType() ) { + case SMDSAbs_0DElement: + stype = tr( "0D ELEMENT" ); break; + case SMDSAbs_Edge: + stype = tr( "EDGE" ); break; + case SMDSAbs_Face: + stype = tr( "FACE" ); break; + case SMDSAbs_Volume: + stype = tr( "VOLUME" ); break; + default: + break; + } + if ( stype.isEmpty() ) return; + myInfo->append( QString( "%1 #%2" ).arg( stype ).arg( id ) ); // separator myInfo->append( "" ); + // geometry type + QString gtype; + switch( e->GetEntityType() ) { + case SMDSEntity_Triangle: + case SMDSEntity_Quad_Triangle: + gtype = tr( "TRIANGLE" ); break; + case SMDSEntity_Quadrangle: + case SMDSEntity_Quad_Quadrangle: + gtype = tr( "QUADRANGLE" ); break; + case SMDSEntity_Polygon: + case SMDSEntity_Quad_Polygon: + gtype = tr( "POLYGON" ); break; + case SMDSEntity_Tetra: + case SMDSEntity_Quad_Tetra: + gtype = tr( "TETRAHEDRON" ); break; + case SMDSEntity_Pyramid: + case SMDSEntity_Quad_Pyramid: + gtype = tr( "PYRAMID" ); break; + case SMDSEntity_Hexa: + case SMDSEntity_Quad_Hexa: + gtype = tr( "HEXAHEDRON" ); break; + case SMDSEntity_Penta: + case SMDSEntity_Quad_Penta: + gtype = tr( "PRISM" ); break; + case SMDSEntity_Polyhedra: + case SMDSEntity_Quad_Polyhedra: + gtype = tr( "POLYHEDRON" ); break; + default: + break; + } + if ( !gtype.isEmpty() ) + myInfo->append( QString( "%1: %2" ).arg( tr( "TYPE" ) ).arg( gtype ) ); + // quadratic flag and gravity center (any element except 0D) + if ( e->GetEntityType() > SMDSEntity_0D && e->GetEntityType() < SMDSEntity_Last ) { + // quadratic flag + myInfo->append( QString( "%1? %2" ).arg( tr( "QUADRATIC" ) ).arg( e->IsQuadratic() ? tr( "YES" ) : tr( "NO" ) ) ); + // separator + myInfo->append( "" ); + // gravity center + XYZ gc = gravityCenter( e ); + myInfo->append( QString( "%1: (%2, %3, %4)" ).arg( tr( "GRAVITY_CENTER" ) ).arg( gc.x() ).arg( gc.y() ).arg( gc.z() ) ); + } + // separator + myInfo->append( "" ); + // connectivity + SMDS_ElemIteratorPtr nodeIt = e->nodesIterator(); + for ( int idx = 1; nodeIt->more(); idx++ ) { + const SMDS_MeshNode* node = static_cast( nodeIt->next() ); + // node number and ID + myInfo->append( QString( "%1 %2/%3 - #%4" ).arg( tr( "NODE" ) ).arg( idx ).arg( e->NbNodes() ).arg( node->GetID() ) ); + // node coordinates + myInfo->append( QString( "%1: (%2, %3, %4)" ).arg( tr( "COORDINATES" ) ). + arg( node->X(), 0, precision > 0 ? 'f' : 'g', qAbs( precision ) ). + arg( node->Y(), 0, precision > 0 ? 'f' : 'g', qAbs( precision ) ). + arg( node->Z(), 0, precision > 0 ? 'f' : 'g', qAbs( precision ) ) ); + // node connectivity + Connectivity connectivity = nodeConnectivity( node ); + if ( !connectivity.isEmpty() ) { + myInfo->append( QString( "%1:" ).arg( tr( "CONNECTIVITY" ) ) ); + QString con = formatConnectivity( connectivity, SMDSAbs_0DElement ); + if ( !con.isEmpty() ) + myInfo->append( QString( "- %1: %2" ).arg( tr( "0D_ELEMENTS" ) ).arg( con ) ); + con = formatConnectivity( connectivity, SMDSAbs_Edge ); + if ( !con.isEmpty() ) + myInfo->append( QString( "- %1: %2" ).arg( tr( "EDGES" ) ).arg( con ) ); + con = formatConnectivity( connectivity, SMDSAbs_Face ); + if ( !con.isEmpty() ) + myInfo->append( QString( "- %1: %2" ).arg( tr( "FACES" ) ).arg( con ) ); + con = formatConnectivity( connectivity, SMDSAbs_Volume ); + if ( !con.isEmpty() ) + myInfo->append( QString( "- %1: %2" ).arg( tr( "VOLUMES" ) ).arg( con ) ); + } + else { + myInfo->append( QString( "%1" ).arg( tr( "FREE_NODE" ) ).arg( id ) ); + } + } + } + // separator + if ( ids.count() > 1 ) { + myInfo->append( "" ); + myInfo->append( "------" ); + myInfo->append( "" ); } } } } /*! - \brief Clear mesh element information widget + \brief Internal clean-up (reset widget) */ -void SMESHGUI_SimpleElemInfo::clear() +void SMESHGUI_SimpleElemInfo::clearInternal() { myInfo->clear(); } @@ -791,189 +914,43 @@ QWidget* SMESHGUI_TreeElemInfo::ItemDelegate::createEditor( QWidget* parent, con SMESHGUI_TreeElemInfo::SMESHGUI_TreeElemInfo( QWidget* parent ) : SMESHGUI_ElemInfo( parent ) { - myInfo = new QTreeWidget( this ); + myInfo = new QTreeWidget( frame() ); myInfo->setColumnCount( 2 ); myInfo->setHeaderLabels( QStringList() << tr( "PROPERTY" ) << tr( "VALUE" ) ); myInfo->header()->setStretchLastSection( true ); myInfo->header()->setResizeMode( 0, QHeaderView::ResizeToContents ); myInfo->setItemDelegate( new ItemDelegate( myInfo ) ); - QVBoxLayout* l = new QVBoxLayout( this ); + QVBoxLayout* l = new QVBoxLayout( frame() ); l->setMargin( 0 ); l->addWidget( myInfo ); } /*! \brief Show mesh element information - \param long id mesh node / element ID - \param isElem show mesh element information if \c true or mesh node information if \c false + \param ids mesh nodes / elements identifiers */ -void SMESHGUI_TreeElemInfo::showInfo( long id, bool isElem ) +void SMESHGUI_TreeElemInfo::information( const QList& ids ) { - if ( myID == id && myIsElement == isElem ) return; - - SMESHGUI_ElemInfo::showInfo( id, isElem ); + clearInternal(); - clear(); - - if ( myActor ) { + if ( actor() ) { int precision = SMESHGUI::resourceMgr()->integerValue( "SMESH", "length_precision", 6 ); - if ( !isElem ) { - // - // show node info - // - const SMDS_MeshElement* e = myActor->GetObject()->GetMesh()->FindNode( id ); - if ( !e ) return; - const SMDS_MeshNode* node = static_cast( e ); + foreach ( long id, ids ) { + if ( !isElements() ) { + // + // show node info + // + const SMDS_MeshElement* e = actor()->GetObject()->GetMesh()->FindNode( id ); + if ( !e ) return; + const SMDS_MeshNode* node = static_cast( e ); - // node ID - QTreeWidgetItem* nodeItem = createItem( 0, -1 ); - nodeItem->setText( 0, tr( "NODE" ) ); - nodeItem->setText( 1, QString( "#%1" ).arg( id ) ); - nodeItem->setExpanded( true ); - // coordinates - QTreeWidgetItem* coordItem = createItem( nodeItem, 0 ); - coordItem->setText( 0, tr( "COORDINATES" ) ); - coordItem->setExpanded( true ); - QTreeWidgetItem* xItem = createItem( coordItem ); - xItem->setText( 0, "X" ); - xItem->setText( 1, QString::number( node->X(), precision > 0 ? 'f' : 'g', qAbs( precision ) ) ); - QTreeWidgetItem* yItem = createItem( coordItem ); - yItem->setText( 0, "Y" ); - yItem->setText( 1, QString::number( node->Y(), precision > 0 ? 'f' : 'g', qAbs( precision ) ) ); - QTreeWidgetItem* zItem = createItem( coordItem ); - zItem->setText( 0, "Z" ); - zItem->setText( 1, QString::number( node->Z(), precision > 0 ? 'f' : 'g', qAbs( precision ) ) ); - // connectivity - QTreeWidgetItem* conItem = createItem( nodeItem, 0 ); - conItem->setText( 0, tr( "CONNECTIVITY" ) ); - conItem->setExpanded( true ); - Connectivity connectivity = nodeConnectivity( node ); - if ( !connectivity.isEmpty() ) { - QString con = formatConnectivity( connectivity, SMDSAbs_0DElement ); - if ( !con.isEmpty() ) { - QTreeWidgetItem* i = createItem( conItem ); - i->setText( 0, tr( "0D_ELEMENTS" ) ); - i->setText( 1, con ); - } - con = formatConnectivity( connectivity, SMDSAbs_Edge ); - if ( !con.isEmpty() ) { - QTreeWidgetItem* i = createItem( conItem ); - i->setText( 0, tr( "EDGES" ) ); - i->setText( 1, con ); - } - con = formatConnectivity( connectivity, SMDSAbs_Face ); - if ( !con.isEmpty() ) { - QTreeWidgetItem* i = createItem( conItem ); - i->setText( 0, tr( "FACES" ) ); - i->setText( 1, con ); - } - con = formatConnectivity( connectivity, SMDSAbs_Volume ); - if ( !con.isEmpty() ) { - QTreeWidgetItem* i = createItem( conItem ); - i->setText( 0, tr( "VOLUMES" ) ); - i->setText( 1, con ); - } - } - else { - conItem->setText( 1, tr( "FREE_NODE" ) ); - } - } - else { - // - // show element info - // - const SMDS_MeshElement* e = myActor->GetObject()->GetMesh()->FindElement( id ); - if ( !e ) return; - - // element ID && type - QString stype; - switch( e->GetType() ) { - case SMDSAbs_0DElement: - stype = tr( "0D ELEMENT" ); break; - case SMDSAbs_Edge: - stype = tr( "EDGE" ); break; - case SMDSAbs_Face: - stype = tr( "FACE" ); break; - case SMDSAbs_Volume: - stype = tr( "VOLUME" ); break; - default: - break; - } - if ( stype.isEmpty() ) return; - QTreeWidgetItem* elemItem = createItem( 0, -1 ); - elemItem->setText( 0, stype ); - elemItem->setText( 1, QString( "#%1" ).arg( id ) ); - elemItem->setExpanded( true ); - // geometry type - QString gtype; - switch( e->GetEntityType() ) { - case SMDSEntity_Triangle: - case SMDSEntity_Quad_Triangle: - gtype = tr( "TRIANGLE" ); break; - case SMDSEntity_Quadrangle: - case SMDSEntity_Quad_Quadrangle: - gtype = tr( "QUADRANGLE" ); break; - case SMDSEntity_Polygon: - case SMDSEntity_Quad_Polygon: - gtype = tr( "POLYGON" ); break; - case SMDSEntity_Tetra: - case SMDSEntity_Quad_Tetra: - gtype = tr( "TETRAHEDRON" ); break; - case SMDSEntity_Pyramid: - case SMDSEntity_Quad_Pyramid: - gtype = tr( "PYRAMID" ); break; - case SMDSEntity_Hexa: - case SMDSEntity_Quad_Hexa: - gtype = tr( "HEXAHEDRON" ); break; - case SMDSEntity_Penta: - case SMDSEntity_Quad_Penta: - gtype = tr( "PRISM" ); break; - case SMDSEntity_Polyhedra: - case SMDSEntity_Quad_Polyhedra: - gtype = tr( "POLYHEDRON" ); break; - default: - break; - } - if ( !gtype.isEmpty() ) { - QTreeWidgetItem* typeItem = createItem( elemItem, 0 ); - typeItem->setText( 0, tr( "TYPE" ) ); - typeItem->setText( 1, gtype ); - } - // quadratic flag and gravity center (any element except 0D) - if ( e->GetEntityType() > SMDSEntity_0D && e->GetEntityType() < SMDSEntity_Last ) { - // quadratic flag - QTreeWidgetItem* quadItem = createItem( elemItem, 0 ); - quadItem->setText( 0, tr( "QUADRATIC" ) ); - quadItem->setText( 1, e->IsQuadratic() ? tr( "YES" ) : tr( "NO" ) ); - // gravity center - XYZ gc = gravityCenter( e ); - QTreeWidgetItem* gcItem = createItem( elemItem, 0 ); - gcItem->setText( 0, tr( "GRAVITY_CENTER" ) ); - gcItem->setExpanded( true ); - QTreeWidgetItem* xItem = createItem( gcItem ); - xItem->setText( 0, "X" ); - xItem->setText( 1, QString::number( gc.x(), precision > 0 ? 'f' : 'g', qAbs( precision ) ) ); - QTreeWidgetItem* yItem = createItem( gcItem ); - yItem->setText( 0, "Y" ); - yItem->setText( 1, QString::number( gc.y(), precision > 0 ? 'f' : 'g', qAbs( precision ) ) ); - QTreeWidgetItem* zItem = createItem( gcItem ); - zItem->setText( 0, "Z" ); - zItem->setText( 1, QString::number( gc.z(), precision > 0 ? 'f' : 'g', qAbs( precision ) ) ); - } - // connectivity - QTreeWidgetItem* conItem = createItem( elemItem, 0 ); - conItem->setText( 0, tr( "CONNECTIVITY" ) ); - conItem->setExpanded( true ); - SMDS_ElemIteratorPtr nodeIt = e->nodesIterator(); - for ( int idx = 1; nodeIt->more(); idx++ ) { - const SMDS_MeshNode* node = static_cast( nodeIt->next() ); - // node number and ID - QTreeWidgetItem* nodeItem = createItem( conItem, 0 ); - nodeItem->setText( 0, QString( "%1 %2/%3" ).arg( tr( "NODE" ) ).arg( idx ).arg( e->NbNodes() ) ); - nodeItem->setText( 1, QString( "#%1" ).arg( node->GetID() ) ); - //nodeItem->setExpanded( true ); - // node coordinates - QTreeWidgetItem* coordItem = createItem( nodeItem ); + // node ID + QTreeWidgetItem* nodeItem = createItem( 0, -1 ); + nodeItem->setText( 0, tr( "NODE" ) ); + nodeItem->setText( 1, QString( "#%1" ).arg( id ) ); + nodeItem->setExpanded( true ); + // coordinates + QTreeWidgetItem* coordItem = createItem( nodeItem, 0 ); coordItem->setText( 0, tr( "COORDINATES" ) ); coordItem->setExpanded( true ); QTreeWidgetItem* xItem = createItem( coordItem ); @@ -985,46 +962,189 @@ void SMESHGUI_TreeElemInfo::showInfo( long id, bool isElem ) QTreeWidgetItem* zItem = createItem( coordItem ); zItem->setText( 0, "Z" ); zItem->setText( 1, QString::number( node->Z(), precision > 0 ? 'f' : 'g', qAbs( precision ) ) ); - // node connectivity - QTreeWidgetItem* nconItem = createItem( nodeItem ); - nconItem->setText( 0, tr( "CONNECTIVITY" ) ); - nconItem->setExpanded( true ); + // connectivity + QTreeWidgetItem* conItem = createItem( nodeItem, 0 ); + conItem->setText( 0, tr( "CONNECTIVITY" ) ); + conItem->setExpanded( true ); Connectivity connectivity = nodeConnectivity( node ); if ( !connectivity.isEmpty() ) { QString con = formatConnectivity( connectivity, SMDSAbs_0DElement ); if ( !con.isEmpty() ) { - QTreeWidgetItem* i = createItem( nconItem ); + QTreeWidgetItem* i = createItem( conItem ); i->setText( 0, tr( "0D_ELEMENTS" ) ); i->setText( 1, con ); } con = formatConnectivity( connectivity, SMDSAbs_Edge ); if ( !con.isEmpty() ) { - QTreeWidgetItem* i = createItem( nconItem ); + QTreeWidgetItem* i = createItem( conItem ); i->setText( 0, tr( "EDGES" ) ); i->setText( 1, con ); } con = formatConnectivity( connectivity, SMDSAbs_Face ); if ( !con.isEmpty() ) { - QTreeWidgetItem* i = createItem( nconItem ); + QTreeWidgetItem* i = createItem( conItem ); i->setText( 0, tr( "FACES" ) ); i->setText( 1, con ); } con = formatConnectivity( connectivity, SMDSAbs_Volume ); if ( !con.isEmpty() ) { - QTreeWidgetItem* i = createItem( nconItem ); + QTreeWidgetItem* i = createItem( conItem ); i->setText( 0, tr( "VOLUMES" ) ); i->setText( 1, con ); } } + else { + conItem->setText( 1, tr( "FREE_NODE" ) ); + } + } + else { + // + // show element info + // + const SMDS_MeshElement* e = actor()->GetObject()->GetMesh()->FindElement( id ); + if ( !e ) return; + + // element ID && type + QString stype; + switch( e->GetType() ) { + case SMDSAbs_0DElement: + stype = tr( "0D ELEMENT" ); break; + case SMDSAbs_Edge: + stype = tr( "EDGE" ); break; + case SMDSAbs_Face: + stype = tr( "FACE" ); break; + case SMDSAbs_Volume: + stype = tr( "VOLUME" ); break; + default: + break; + } + if ( stype.isEmpty() ) return; + QTreeWidgetItem* elemItem = createItem( 0, -1 ); + elemItem->setText( 0, stype ); + elemItem->setText( 1, QString( "#%1" ).arg( id ) ); + elemItem->setExpanded( true ); + // geometry type + QString gtype; + switch( e->GetEntityType() ) { + case SMDSEntity_Triangle: + case SMDSEntity_Quad_Triangle: + gtype = tr( "TRIANGLE" ); break; + case SMDSEntity_Quadrangle: + case SMDSEntity_Quad_Quadrangle: + gtype = tr( "QUADRANGLE" ); break; + case SMDSEntity_Polygon: + case SMDSEntity_Quad_Polygon: + gtype = tr( "POLYGON" ); break; + case SMDSEntity_Tetra: + case SMDSEntity_Quad_Tetra: + gtype = tr( "TETRAHEDRON" ); break; + case SMDSEntity_Pyramid: + case SMDSEntity_Quad_Pyramid: + gtype = tr( "PYRAMID" ); break; + case SMDSEntity_Hexa: + case SMDSEntity_Quad_Hexa: + gtype = tr( "HEXAHEDRON" ); break; + case SMDSEntity_Penta: + case SMDSEntity_Quad_Penta: + gtype = tr( "PRISM" ); break; + case SMDSEntity_Polyhedra: + case SMDSEntity_Quad_Polyhedra: + gtype = tr( "POLYHEDRON" ); break; + default: + break; + } + if ( !gtype.isEmpty() ) { + QTreeWidgetItem* typeItem = createItem( elemItem, 0 ); + typeItem->setText( 0, tr( "TYPE" ) ); + typeItem->setText( 1, gtype ); + } + // quadratic flag and gravity center (any element except 0D) + if ( e->GetEntityType() > SMDSEntity_0D && e->GetEntityType() < SMDSEntity_Last ) { + // quadratic flag + QTreeWidgetItem* quadItem = createItem( elemItem, 0 ); + quadItem->setText( 0, tr( "QUADRATIC" ) ); + quadItem->setText( 1, e->IsQuadratic() ? tr( "YES" ) : tr( "NO" ) ); + // gravity center + XYZ gc = gravityCenter( e ); + QTreeWidgetItem* gcItem = createItem( elemItem, 0 ); + gcItem->setText( 0, tr( "GRAVITY_CENTER" ) ); + gcItem->setExpanded( true ); + QTreeWidgetItem* xItem = createItem( gcItem ); + xItem->setText( 0, "X" ); + xItem->setText( 1, QString::number( gc.x(), precision > 0 ? 'f' : 'g', qAbs( precision ) ) ); + QTreeWidgetItem* yItem = createItem( gcItem ); + yItem->setText( 0, "Y" ); + yItem->setText( 1, QString::number( gc.y(), precision > 0 ? 'f' : 'g', qAbs( precision ) ) ); + QTreeWidgetItem* zItem = createItem( gcItem ); + zItem->setText( 0, "Z" ); + zItem->setText( 1, QString::number( gc.z(), precision > 0 ? 'f' : 'g', qAbs( precision ) ) ); + } + // connectivity + QTreeWidgetItem* conItem = createItem( elemItem, 0 ); + conItem->setText( 0, tr( "CONNECTIVITY" ) ); + conItem->setExpanded( true ); + SMDS_ElemIteratorPtr nodeIt = e->nodesIterator(); + for ( int idx = 1; nodeIt->more(); idx++ ) { + const SMDS_MeshNode* node = static_cast( nodeIt->next() ); + // node number and ID + QTreeWidgetItem* nodeItem = createItem( conItem, 0 ); + nodeItem->setText( 0, QString( "%1 %2/%3" ).arg( tr( "NODE" ) ).arg( idx ).arg( e->NbNodes() ) ); + nodeItem->setText( 1, QString( "#%1" ).arg( node->GetID() ) ); + //nodeItem->setExpanded( true ); + // node coordinates + QTreeWidgetItem* coordItem = createItem( nodeItem ); + coordItem->setText( 0, tr( "COORDINATES" ) ); + coordItem->setExpanded( true ); + QTreeWidgetItem* xItem = createItem( coordItem ); + xItem->setText( 0, "X" ); + xItem->setText( 1, QString::number( node->X(), precision > 0 ? 'f' : 'g', qAbs( precision ) ) ); + QTreeWidgetItem* yItem = createItem( coordItem ); + yItem->setText( 0, "Y" ); + yItem->setText( 1, QString::number( node->Y(), precision > 0 ? 'f' : 'g', qAbs( precision ) ) ); + QTreeWidgetItem* zItem = createItem( coordItem ); + zItem->setText( 0, "Z" ); + zItem->setText( 1, QString::number( node->Z(), precision > 0 ? 'f' : 'g', qAbs( precision ) ) ); + // node connectivity + QTreeWidgetItem* nconItem = createItem( nodeItem ); + nconItem->setText( 0, tr( "CONNECTIVITY" ) ); + nconItem->setExpanded( true ); + Connectivity connectivity = nodeConnectivity( node ); + if ( !connectivity.isEmpty() ) { + QString con = formatConnectivity( connectivity, SMDSAbs_0DElement ); + if ( !con.isEmpty() ) { + QTreeWidgetItem* i = createItem( nconItem ); + i->setText( 0, tr( "0D_ELEMENTS" ) ); + i->setText( 1, con ); + } + con = formatConnectivity( connectivity, SMDSAbs_Edge ); + if ( !con.isEmpty() ) { + QTreeWidgetItem* i = createItem( nconItem ); + i->setText( 0, tr( "EDGES" ) ); + i->setText( 1, con ); + } + con = formatConnectivity( connectivity, SMDSAbs_Face ); + if ( !con.isEmpty() ) { + QTreeWidgetItem* i = createItem( nconItem ); + i->setText( 0, tr( "FACES" ) ); + i->setText( 1, con ); + } + con = formatConnectivity( connectivity, SMDSAbs_Volume ); + if ( !con.isEmpty() ) { + QTreeWidgetItem* i = createItem( nconItem ); + i->setText( 0, tr( "VOLUMES" ) ); + i->setText( 1, con ); + } + } + } } } } } /*! - \brief Clear mesh element information widget + \brief Internal clean-up (reset widget) */ -void SMESHGUI_TreeElemInfo::clear() +void SMESHGUI_TreeElemInfo::clearInternal() { myInfo->clear(); myInfo->repaint(); @@ -1092,7 +1212,7 @@ SMESHGUI_MeshInfoDlg::SMESHGUI_MeshInfoDlg( QWidget* parent, int page ) myMode->addButton( new QRadioButton( tr( "ELEM_MODE" ), w ), ElemMode ); myMode->button( NodeMode )->setChecked( true ); myID = new QLineEdit( w ); - myID->setValidator( new SMESHGUI_IdValidator( this, 1 ) ); + myID->setValidator( new SMESHGUI_IdValidator( this ) ); int mode = SMESHGUI::resourceMgr()->integerValue( "SMESH", "mesh_elem_info", 1 ); mode = qMin( 1, qMax( 0, mode ) ); @@ -1173,10 +1293,14 @@ void SMESHGUI_MeshInfoDlg::showInfo( const Handle(SALOME_InteractiveObject)& IO SMESH::GetNameOfSelectedElements( selector, IO, ID ) : SMESH::GetNameOfSelectedNodes( selector, IO, ID ); } - if ( nb == 1 ) { + myElemInfo->setSource( myActor ) ; + if ( nb > 0 ) { myID->setText( ID.trimmed() ); - myElemInfo->setSource( myActor ) ; - myElemInfo->showInfo( ID.toLong(), myMode->checkedId() == ElemMode ); + QSet ids; + QStringList idTxt = ID.split( " ", QString::SkipEmptyParts ); + foreach ( ID, idTxt ) + ids << ID.trimmed().toLong(); + myElemInfo->showInfo( ids, myMode->checkedId() == ElemMode ); } else { myID->clear(); @@ -1247,15 +1371,15 @@ void SMESHGUI_MeshInfoDlg::updateSelection() } } - int oldID = myID->text().toLong(); + QString oldID = myID->text().trimmed(); SMESH_Actor* oldActor = myActor; myID->clear(); connect( selMgr, SIGNAL( currentSelectionChanged() ), this, SLOT( updateInfo() ) ); updateInfo(); - if ( oldActor == myActor && myActor && oldID ) { - myID->setText( QString::number( oldID ) ); + if ( oldActor == myActor && myActor && !oldID.isEmpty() ) { + myID->setText( oldID ); idChanged(); } } @@ -1328,10 +1452,21 @@ void SMESHGUI_MeshInfoDlg::idChanged() if ( myActor && selector ) { Handle(SALOME_InteractiveObject) IO = myActor->getIO(); TColStd_MapOfInteger ID; - ID.Add( myID->text().toLong() ); + QSet ids; + QStringList idTxt = myID->text().split( " ", QString::SkipEmptyParts ); + foreach ( QString tid, idTxt ) { + long id = tid.trimmed().toLong(); + const SMDS_MeshElement* e = myMode->checkedId() == ElemMode ? + myActor->GetObject()->GetMesh()->FindElement( id ) : + myActor->GetObject()->GetMesh()->FindNode( id ); + if ( e ) { + ID.Add( id ); + ids << id; + } + } selector->AddOrRemoveIndex( IO, ID, false ); if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow() ) aViewWindow->highlight( IO, true, true ); - myElemInfo->showInfo( myID->text().toLong(), myMode->checkedId() == ElemMode ); + myElemInfo->showInfo( ids, myMode->checkedId() == ElemMode ); } } diff --git a/src/SMESHGUI/SMESHGUI_MeshInfo.h b/src/SMESHGUI/SMESHGUI_MeshInfo.h index ae22e5ac0..2028fb050 100644 --- a/src/SMESHGUI/SMESHGUI_MeshInfo.h +++ b/src/SMESHGUI/SMESHGUI_MeshInfo.h @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -40,6 +41,7 @@ class QButtonGroup; class QLabel; class QLineEdit; +class QPushButton; class QTabWidget; class QTextBrowser; class QTreeWidget; @@ -121,8 +123,9 @@ public: ~SMESHGUI_ElemInfo(); void setSource( SMESH_Actor* ); - virtual void showInfo( long, bool ); - virtual void clear() = 0; + void showInfo( long, bool ); + void showInfo( QSet, bool ); + void clear(); protected: struct XYZ @@ -137,14 +140,32 @@ protected: }; typedef QMap< int, QList > Connectivity; + QWidget* frame() const; + SMESH_Actor* actor() const; + bool isElements() const; + + virtual void information( const QList& ) = 0; + virtual void clearInternal(); + Connectivity nodeConnectivity( const SMDS_MeshNode* ); QString formatConnectivity( Connectivity, int ); XYZ gravityCenter( const SMDS_MeshElement* ); -protected: - SMESH_Actor* myActor; - long myID; - int myIsElement; +private slots: + void showPrevious(); + void showNext(); + void updateControls(); + +private: + SMESH_Actor* myActor; + QList myIDs; + int myIsElement; + QWidget* myFrame; + QWidget* myExtra; + QLabel* myCurrent; + QPushButton* myPrev; + QPushButton* myNext; + int myIndex; }; class SMESHGUI_EXPORT SMESHGUI_SimpleElemInfo : public SMESHGUI_ElemInfo @@ -152,8 +173,9 @@ class SMESHGUI_EXPORT SMESHGUI_SimpleElemInfo : public SMESHGUI_ElemInfo public: SMESHGUI_SimpleElemInfo( QWidget* = 0 ); - void showInfo( long, bool ); - void clear(); +protected: + void information( const QList& ); + void clearInternal(); private: QTextBrowser* myInfo; @@ -166,8 +188,9 @@ class SMESHGUI_EXPORT SMESHGUI_TreeElemInfo : public SMESHGUI_ElemInfo public: SMESHGUI_TreeElemInfo( QWidget* = 0 ); - void showInfo( long, bool ); - void clear(); +protected: + void information( const QList& ); + void clearInternal(); private: QTreeWidgetItem* createItem( QTreeWidgetItem* = 0, int = 100 ); diff --git a/src/SMESHGUI/SMESHGUI_Preferences_ScalarBarDlg.cxx b/src/SMESHGUI/SMESHGUI_Preferences_ScalarBarDlg.cxx index 43640501e..b1f9284c6 100644 --- a/src/SMESHGUI/SMESHGUI_Preferences_ScalarBarDlg.cxx +++ b/src/SMESHGUI/SMESHGUI_Preferences_ScalarBarDlg.cxx @@ -418,7 +418,7 @@ SMESHGUI_Preferences_ScalarBarDlg::SMESHGUI_Preferences_ScalarBarDlg( SMESHGUI* } QColor distributionColor = mgr->colorValue("SMESH", "distribution_color", - QColor(255, 255, 255)); + QColor(255, 255, 255)); myMonoColorBtn->setColor(distributionColor); @@ -509,18 +509,6 @@ bool SMESHGUI_Preferences_ScalarBarDlg::onApply() myScalarBarActor->SetLabelTextProperty( aLabelsTextPrp ); myScalarBarActor->SetNumberOfLabels( myLabelsSpin->value() ); - if( myColorsSpin->value() != myScalarBarActor->GetMaximumNumberOfColors() ) { - myScalarBarActor->SetMaximumNumberOfColors( myColorsSpin->value() ); - SMESH::Controls::FunctorPtr fn = myActor->GetFunctor(); - SMESH::Controls::NumericalFunctor* aNumericalFunctor = dynamic_cast(fn.get()); - if( aNumericalFunctor ) { - int nbIntervals = myColorsSpin->value(); - std::vector nbEvents; - std::vector funValues; - aNumericalFunctor->GetHistogram(nbIntervals, nbEvents, funValues); - myScalarBarActor->SetDistribution(nbEvents); - } - } if ( myHorizRadioBtn->isChecked() ) myScalarBarActor->SetOrientationToHorizontal(); @@ -550,9 +538,22 @@ bool SMESHGUI_Preferences_ScalarBarDlg::onApply() double aMax = myMaxEdit->text().toDouble(); vtkLookupTable* myLookupTable = static_cast(myScalarBarActor->GetLookupTable()); + double oldMinMax[2] = { myLookupTable->GetRange()[0], myLookupTable->GetRange()[1] }; + bool rangeChanges = ( fabs( oldMinMax[0] - aMin ) + fabs( oldMinMax[1] - aMax ) > + 0.001 * ( aMax-aMin + oldMinMax[1]-oldMinMax[0] )); + + bool nbColorsChanged = (myColorsSpin->value() != myScalarBarActor->GetMaximumNumberOfColors()); + if(nbColorsChanged) + myScalarBarActor->SetMaximumNumberOfColors(myColorsSpin->value()); + + myLookupTable->SetRange( aMin, aMax ); myLookupTable->SetNumberOfTableValues(myColorsSpin->value()); myLookupTable->Build(); + + if( nbColorsChanged || rangeChanges) + myActor->UpdateDistribution(); + SMESH::RepaintCurrentView(); return true; } @@ -655,17 +656,17 @@ void SMESHGUI_Preferences_ScalarBarDlg::onSelectionChanged() myIniH = myScalarBarActor->GetHeight(); setOriginAndSize( myIniX, myIniY, myIniW, myIniH ); - myDistributionGrp->setChecked((bool)myScalarBarActor->GetDistributionVisibility()); - int coloringType = myScalarBarActor->GetDistributionColoringType(); - myScalarBarActor->GetDistributionColor( aTColor ); - myMonoColorBtn->setColor( QColor( (int)( aTColor[0]*255 ), (int)( aTColor[1]*255 ), (int)( aTColor[2]*255 ) ) ); - if ( coloringType == SMESH_MONOCOLOR_TYPE ) { - myDMonoColor->setChecked(true); - onDistributionChanged(myDistribColorGrp->id(myDMonoColor)); - } else { - myDMultiColor->setChecked(true); - onDistributionChanged(myDistribColorGrp->id(myDMultiColor)); - } + myDistributionGrp->setChecked((bool)myScalarBarActor->GetDistributionVisibility()); + int coloringType = myScalarBarActor->GetDistributionColoringType(); + myScalarBarActor->GetDistributionColor( aTColor ); + myMonoColorBtn->setColor( QColor( (int)( aTColor[0]*255 ), (int)( aTColor[1]*255 ), (int)( aTColor[2]*255 ) ) ); + if ( coloringType == SMESH_MONOCOLOR_TYPE ) { + myDMonoColor->setChecked(true); + onDistributionChanged(myDistribColorGrp->id(myDMonoColor)); + } else { + myDMultiColor->setChecked(true); + onDistributionChanged(myDistribColorGrp->id(myDMultiColor)); + } myRangeGrp->setEnabled( true ); myFontGrp->setEnabled( true ); myLabColorGrp->setEnabled( true ); diff --git a/src/SMESHGUI/SMESHGUI_Utils.cxx b/src/SMESHGUI/SMESHGUI_Utils.cxx index dfe778831..331ad9f92 100644 --- a/src/SMESHGUI/SMESHGUI_Utils.cxx +++ b/src/SMESHGUI/SMESHGUI_Utils.cxx @@ -214,7 +214,7 @@ namespace SMESH QString IOR = app->orb()->object_to_string( theObject ); SalomeApp_Study* study = dynamic_cast( app->activeStudy() ); if ( study && !IOR.isEmpty() ) - res = study->studyDS()->FindObjectIOR( IOR.toLatin1().constData() ); + res = study->studyDS()->FindObjectIOR( IOR.toLatin1().constData() ); } return res; } diff --git a/src/SMESHGUI/SMESH_images.ts b/src/SMESHGUI/SMESH_images.ts index 856e88f32..3eff547c5 100644 --- a/src/SMESHGUI/SMESH_images.ts +++ b/src/SMESHGUI/SMESH_images.ts @@ -53,6 +53,10 @@ ICON_BUILD_COMPOUND mesh_build_compound.png + + ICON_COPY_MESH + copy_mesh.png + ICON_COMPUTE mesh_compute.png @@ -109,6 +113,10 @@ ICON_DLG_BUILD_COMPOUND_MESH mesh_build_compound.png + + ICON_DLG_COPY_MESH + copy_mesh.png + ICON_DLG_ELEM0D mesh_vertex.png @@ -457,6 +465,22 @@ ICON_VOLUME_3D mesh_volume_3d.png + + ICON_BARE_BORDER_VOLUME + bare_border_volume.png + + + ICON_BARE_BORDER_FACE + bare_border_face.png + + + ICON_OVER_CONSTRAINED_VOLUME + over_constrained_volume.png + + + ICON_OVER_CONSTRAINED_FACE + over_constrained_face.png + ICON_WARP mesh_wrap.png diff --git a/src/SMESHGUI/SMESH_msg_en.ts b/src/SMESHGUI/SMESH_msg_en.ts index 81e2619ee..9352f1cef 100644 --- a/src/SMESHGUI/SMESH_msg_en.ts +++ b/src/SMESHGUI/SMESH_msg_en.ts @@ -187,6 +187,10 @@ MEN_BUILD_COMPOUND Build Compound + + MEN_COPY_MESH + Copy Mesh + MEN_CLIP Clipping @@ -395,6 +399,22 @@ STB_FIND_ELEM Find Element by Point + + MEN_BARE_BORDER_VOLUME + Volumes with bare border + + + MEN_BARE_BORDER_FACE + Faces with bare border + + + MEN_OVER_CONSTRAINED_VOLUME + Over-constrained volumes + + + MEN_OVER_CONSTRAINED_FACE + Over-constrained faces + MEN_FREE_BORDER Free Borders @@ -1040,6 +1060,14 @@ Please enter correct values and try again SMESH_BUILD_COMPOUND_TITLE Create a Compound + + SMESH_COPY_MESH_TITLE + Copy Mesh + + + SMESH_KEEP_IDS + Preserve IDs of elements + SMESH_BUT_ADD A&dd @@ -1451,7 +1479,8 @@ add the exported data to its contents? SMESH_HYP_12 - Geometry mismatches algorithm's expectation\nCheck algorithm documentation for supported geometry + Geometry mismatches algorithm's expectation +Check algorithm documentation for supported geometry SMESH_HYP_13 @@ -2101,7 +2130,7 @@ add the exported data to its contents? SMESH_VERTICAL Vertical - + SMESH_DISTRIBUTION_COLORING_TYPE Coloring Type @@ -2274,6 +2303,10 @@ Please check preferences of Mesh module. STB_BUILD_COMPOUND Build Compound Mesh + + STB_COPY_MESH + Copy Mesh + STB_CLIP Clipping @@ -2434,6 +2467,22 @@ Please check preferences of Mesh module. STB_FACES Faces + + STB_BARE_BORDER_VOLUME + Volumes with bare border + + + STB_BARE_BORDER_FACE + Faces with bare border + + + STB_OVER_CONSTRAINED_VOLUME + Over-constrained volumes + + + STB_OVER_CONSTRAINED_FACE + Over-constrained faces + STB_FREE_BORDER Free Borders @@ -2614,7 +2663,7 @@ Please check preferences of Mesh module. STB_SAVE_DISTRIBUTION Save distribution to the file - + STB_SHOW_DISTRIBUTION Show Distribution @@ -2810,6 +2859,10 @@ Please check preferences of Mesh module. TOP_BUILD_COMPOUND Build Compound Mesh + + TOP_COPY_MESH + Copy Mesh + TOP_CLIP Clipping @@ -2970,6 +3023,22 @@ Please check preferences of Mesh module. TOP_FACES Faces + + TOP_BARE_BORDER_VOLUME + Volumes with bare border + + + TOP_BARE_BORDER_FACE + Faces with bare border + + + TOP_OVER_CONSTRAINED_VOLUME + Over-constrained volumes + + + TOP_OVER_CONSTRAINED_FACE + Over-constrained faces + TOP_FREE_BORDER Free Borders @@ -3399,7 +3468,7 @@ Input value precision can be adjusted using SMESH_PLUGINS_OTHER SMESH plugins - + SMESHGUI @@ -3565,7 +3634,7 @@ Please, create VTK viewer and try again Mesh information - PREF_HIGHLIGHT_COLOR + PREF_HIGHLIGHT_COLOR Highlight color @@ -4320,6 +4389,22 @@ Please check input data and try again BAD_ORIENTED_VOLUME Bad oriented volume + + BARE_BORDER_VOLUME + Volumes with bare border + + + BARE_BORDER_FACE + Faces with bare border + + + OVER_CONSTRAINED_VOLUME + Over-constrained volumes + + + OVER_CONSTRAINED_FACE + Over-constrained faces + BELONG_TO_CYLINDER Belong to Cylinder @@ -5607,7 +5692,7 @@ It is impossible to read point coordinates from file QUADRANGLES_LAB - Quadrandgles: + Quadrangles: POLYGONS_LAB @@ -5795,10 +5880,6 @@ It is impossible to read point coordinates from file NO No - - GRAVITY_CENTER - GRAVITY CENTER - PROPERTY Property @@ -5807,6 +5888,10 @@ It is impossible to read point coordinates from file VALUE Value + + X_FROM_Y_ITEMS_SHOWN + %1-%2 from %3 items shown + SMESHGUI_MinDistance @@ -5847,6 +5932,21 @@ It is impossible to read point coordinates from file Distance + + SMESHGUI_CopyMeshDlg + + OBJECT_NAME + Source Object + + + ELEM_IDS + Source Element IDs + + + NEW_NAME + New Mesh Name + + SMESHGUI_MeasureDlg diff --git a/src/SMESHGUI/SMESH_msg_fr.ts b/src/SMESHGUI/SMESH_msg_fr.ts index 955e9396b..7ebd1df62 100755 --- a/src/SMESHGUI/SMESH_msg_fr.ts +++ b/src/SMESHGUI/SMESH_msg_fr.ts @@ -3,6 +3,42 @@ @default + + SMESH_EXPORT_MESH + Exporter le maillage + + + MED_FILES_FILTER + Fichiers MED + + + IDEAS_FILES_FILTER + Fichiers IDEAS + + + DAT_FILES_FILTER + Fichiers DAT + + + TEXT_FILES_FILTER + Fichiers TXT + + + MED_VX_FILES_FILTER + Fichiers MED %1 + + + STL_ASCII_FILES_FILTER + Fichiers STL ASCII + + + STL_BIN_FILES_FILTER + Fichiers STL binaires + + + ALL_FILES_FILTER + Tous les fichiers + AREA_ELEMENTS Aire @@ -107,6 +143,14 @@ LOCAL_ALGO Local + + MAX_ELEMENT_LENGTH_2D + Diamètre d'éléments 2D + + + MAX_ELEMENT_LENGTH_3D + Diamètre d'éléments 3D + MEN_ADD Ajouter @@ -143,6 +187,10 @@ MEN_BUILD_COMPOUND Construire un assemblage + + MEN_COPY_MESH + Copier le maillage + MEN_CLIP Plan de coupe @@ -207,6 +255,22 @@ MEN_CTRL Contrôles + + MEN_NODE_CTRL + Contrôles des nœuds + + + MEN_EDGE_CTRL + Contrôles des arêtes + + + MEN_FACE_CTRL + Contrôles des faces + + + MEN_VOLUME_CTRL + Contrôles des volumes + MEN_CUT Découpe des quadrangles @@ -237,7 +301,7 @@ MEN_DISPLAY_ONLY - Afficher uniquement + Afficher uniquement MEN_DISPMODE @@ -335,6 +399,22 @@ STB_FIND_ELEM Trouver un élément par un point + + MEN_BARE_BORDER_VOLUME + Volumes avec frontière libre + + + MEN_BARE_BORDER_FACE + Faces avec frontière libre + + + MEN_OVER_CONSTRAINED_VOLUME + Volumes sur-contraints + + + MEN_OVER_CONSTRAINED_FACE + Faces sur-contraintes + MEN_FREE_BORDER Frontières libres @@ -391,6 +471,14 @@ MEN_MAP Projection de motif + + MEN_MAX_ELEMENT_LENGTH_2D + Diamètre des éléments 2D + + + MEN_MAX_ELEMENT_LENGTH_3D + Diamètre des éléments 3D + MEN_MED Fichier MED @@ -423,6 +511,34 @@ MEN_MODIFY Modification + + MEN_MEASURE + Outils de mesure + + + MEN_MEASURE_MIN_DIST + Distance minimale + + + STB_MEASURE_MIN_DIST + Calculate minimum distance between two objects + + + TOP_MEASURE_MIN_DIST + Minimum distance + + + MEN_MEASURE_BND_BOX + Boîte englobante + + + STB_MEASURE_BND_BOX + Calculate bounding box for the selected object(s) + + + TOP_MEASURE_BND_BOX + Bounding box + MEN_MOVE Déplacer un nœud @@ -539,6 +655,14 @@ MEN_RESET Restaurer + + MEN_SAVE_DISTRIBUTION + Exporter la distribution... + + + MEN_SHOW_DISTRIBUTION + Afficher la distribution + MEN_REVOLUTION Révolution @@ -936,6 +1060,14 @@ Merci de les corriger, puis essayez de nouveau SMESH_BUILD_COMPOUND_TITLE Créer un assemblage + + SMESH_COPY_MESH_TITLE + Copier le maillage + + + SMESH_KEEP_IDS + Conserver les IDs des éléments + SMESH_BUT_ADD A&jouter @@ -1200,13 +1332,15 @@ Voulez-vous continuer ? SMESH_EXPORT_MED_V2_1 - Les éléments polygonaux et polyèdriques seront omis dans le cas d'exportation du maillage "%1" à MED 2.1 + Les éléments polygonaux et polyèdriques seront omis +dans le cas d'exportation du maillage "%1" à MED 2.1 Utilisez MED 2.2 pour l'exportation correcte. Voulez-vous effectuer l'exportation à MED 2.1 ? SMESH_EXPORT_MED_VERSION_COLLISION - La version MED du fichier "%1" n'est pas connue ou ne correspond pas à la version choisie. + La version MED du fichier "%1" n'est pas connue +ou ne correspond pas à la version choisie. Réécrire le fichier ? @@ -1226,7 +1360,8 @@ Réécrire le fichier ? SMESH_EXPORT_UNV - Les éléments pyramides seront omis au cours de l'exportation du maillage "%1" dans le fichier UNV + Les éléments pyramides seront omis au cours de l'exportation +du maillage "%1" dans le fichier UNV SMESH_EXTRUSION @@ -1255,7 +1390,8 @@ Réécrire le fichier ? SMESH_FILE_EXISTS Le fichier "%1" existe déjà. -Voulez-vous le réécrire ou y ajouter les données exportées ? +Voulez-vous le réécrire ou y ajouter +les données exportées ? SMESH_FONT_ARIAL @@ -1742,6 +1878,14 @@ Référez-vous à la documentation sur l'algorithme et la géométrie suppo SMESH_POSITION_SIZE_SCALARBAR Origine && Taille + + SMESH_DISTRIBUTION_SCALARBAR + Distribution + + + SMESH_SHOW_DISTRIBUTION_SCALARBAR + Afficher la distribution + SMESH_PRECISION Précision @@ -1987,6 +2131,22 @@ Référez-vous à la documentation sur l'algorithme et la géométrie suppo SMESH_VERTICAL Verticale + + SMESH_DISTRIBUTION_COLORING_TYPE + Type de coloration + + + SMESH_MONOCOLOR + Monocouleur + + + SMESH_DISTRIBUTION_COLOR + Couleur de la distribution: + + + SMESH_MULTICOLOR + Multicouleur + SMESH_VISU_PROBLEM Impossible de visualiser le maillage, probablement à cause d'un manque de mémoire @@ -2143,6 +2303,10 @@ Vérifiez la limite dans les préférences du module Mesh. STB_BUILD_COMPOUND Construire un maillage assemblé + + STB_COPY_MESH + Copie le maillage + STB_CLIP Pan de coupe @@ -2823,6 +2987,22 @@ Vérifiez la limite dans les préférences du module Mesh. TOP_FACES Faces + + TOP_BARE_BORDER_VOLUME + Volumes avec frontière libre + + + TOP_BARE_BORDER_FACE + Faces avec frontière libre + + + TOP_OVER_CONSTRAINED_VOLUME + Volumes sur-contraints + + + TOP_OVER_CONSTRAINED_FACE + Faces sur-contraintes + TOP_FREE_BORDER Frontières libres @@ -2871,6 +3051,14 @@ Vérifiez la limite dans les préférences du module Mesh. TOP_MAP Projection de motif + + TOP_MAX_ELEMENT_LENGTH_2D + Diamètre des éléments 2D + + + TOP_MAX_ELEMENT_LENGTH_3D + Diamètre des éléments 3D + TOP_MED Importer un fichier MED @@ -2991,6 +3179,14 @@ Vérifiez la limite dans les préférences du module Mesh. TOP_RESET Restaurer + + TOP_SAVE_DISTRIBUTION + Exporter la distribution + + + TOP_SHOW_DISTRIBUTION + Afficher la distribution + TOP_REVOLUTION Révolution @@ -3123,6 +3319,10 @@ Vérifiez la limite dans les préférences du module Mesh. TOP_WIRE Contours + + UNKNOWN_CONTROL + Inconnu + VOLUME_3D_ELEMENTS Aire @@ -3225,10 +3425,14 @@ avec le paramètre '%1' des préférences du module Mesh.NB_NODES_REMOVED %1 nœud(s) supprimés. + + SMESH_SAVE_DISTRIBUTION + Exporter la distribution + SMESH_PLUGINS_OTHER Extensions SMESH - + SMESHGUI @@ -3317,6 +3521,30 @@ Ouvrez une fenêtre VTK et essayez de nouveau PREF_NOTIFY_MODE Montrer la notification sur le résultat de calcul + + PREF_NOTIFY_NEVER + Jamais + + + PREF_NOTIFY_ERROR + Erreurs uniquement + + + PREF_NOTIFY_ALWAYS + Toujours + + + PREF_ELEM_INFO + Information des éléments du maillage + + + PREF_ELEM_INFO_SIMPLE + Simple + + + PREF_ELEM_INFO_TREE + Arbre + SMESH_PREF_GROUP_PRECISION Précision des champs d'entrée @@ -3365,6 +3593,10 @@ Ouvrez une fenêtre VTK et essayez de nouveau PREF_GROUP_SELECTION Sélection + + PREF_GROUP_INFO + Information du maillage + PREF_HIGHLIGHT_COLOR Couleur de sélection @@ -4121,6 +4353,22 @@ Vérifiez la validité des informations données BAD_ORIENTED_VOLUME Volume mal orienté + + BARE_BORDER_VOLUME + Volumes avec frontière libre + + + BARE_BORDER_FACE + Faces avec frontière libre + + + OVER_CONSTRAINED_VOLUME + Volumes sur-contraints + + + OVER_CONSTRAINED_FACE + Faces sur-contraintes + BELONG_TO_CYLINDER Appartient au cylindre @@ -5173,6 +5421,14 @@ Il y a trop peu de points dans le fichier CLIP_PLANES Plans de découpe + + MESHES_SUBMESHES_GROUPS + Maillages, sous-maillages et groupes + + + SELECT_ALL + Tout sélectionner + ROTATION_AROUND_X_Y2Z Rotation autour de X (Y à Z): @@ -5343,4 +5599,361 @@ Il y a trop peu de points dans le fichier Le nom du groupe n'est pas indiqué + + SMESHGUI_MeshInfo + + NAME_LAB + Nom: + + + OBJECT_LAB + Objet: + + + NODES_LAB + Nœuds: + + + ELEMENTS_LAB + Eléments: + + + TOTAL_LAB + Total + + + LINEAR_LAB + Linéaire + + + QUADRATIC_LAB + Quadratique + + + 0D_LAB + 0D: + + + 1D_LAB + 1D (arêtes): + + + 2D_LAB + 2D (faces): + + + TRIANGLES_LAB + Triangles: + + + QUADRANGLES_LAB + Quadrangles: + + + POLYGONS_LAB + Polygones: + + + 3D_LAB + 3D (volumes): + + + TETRAHEDRONS_LAB + Tétrahédrons: + + + HEXAHEDONRS_LAB + Hexahédrons: + + + PYRAMIDS_LAB + Pyramides: + + + PRISMS_LAB + Prismes: + + + POLYHEDRONS_LAB + Polyhédrons: + + + OBJECT_MESH + Maillage + + + OBJECT_SUBMESH + Sous-maillage + + + OBJECT_GROUP + Groupe + + + OBJECT_GROUP_NODES + Groupe de nœuds + + + OBJECT_GROUP_EDGES + Groupe d'arêtes + + + OBJECT_GROUP_FACES + Groupe de faces + + + OBJECT_GROUP_VOLUMES + Groupe de volumes + + + OBJECT_GROUP_0DELEMS + Groupe d'éléments 0D + + + + SMESHGUI_MeshInfoDlg + + MESH_INFO + Infiormations de maillage + + + BASE_INFO + Informations de base + + + ELEM_INFO + Informations des éléments + + + NODE_MODE + Nœud + + + ELEM_MODE + Elément + + + + SMESHGUI_ElemInfo + + COORDINATES + COORDONNÉES + + + CONNECTIVITY + CONNECTIVITÉ + + + GRAVITY_CENTER + CENTRE DE GRAVITÉ + + + NODE + Nœud + + + 0D_ELEMENT + ELÉMENTS 0D + + + 0D_ELEMENTS + ELÉMENTS 0D + + + EDGE + ARÊTE + + + EDGES + ARÊTES + + + FACE + FACE + + + FACES + FACES + + + VOLUME + VOLUME + + + VOLUMES + VOLUMES + + + FREE_NODE + Nœud libre (pas de connectivité) + + + TYPE + TYPE + + + TRIANGLE + Triangle + + + QUADRANGLE + Quadrangle + + + POLYGON + Polygône + + + TETRAHEDRON + Tétrahédron + + + HEXAHEDRON + Hexahédron + + + PYRAMID + Pyramide + + + PRISM + Prisme + + + POLYHEDRON + Polyhédron + + + QUADRATIC + QUADRATIQUE + + + YES + Oui + + + NO + Non + + + PROPERTY + Propriété + + + VALUE + Valeur + + + X_FROM_Y_ITEMS_SHOWN + %1-%2 sur %3 éléments affichés + + + + SMESHGUI_MinDistance + + FIRST_TARGET + Premier élément + + + SECOND_TARGET + Deuxième élément + + + NODE + Nœud + + + ELEMENT + Elément + + + OBJECT + Objet + + + ORIGIN + Origine + + + COMPUTE + Calculer + + + RESULT + Distance entre les éléments + + + DISTANCE + Distance + + + + SMESHGUI_CopyMeshDlg + + OBJECT_NAME + Objet source + + + ELEM_IDS + IDs des éléments sources + + + NEW_NAME + Nom du nouveau maillage + + + + SMESHGUI_MeasureDlg + + MEASUREMENTS + Outils de mesure + + + MIN_DIST + Distance minimale + + + BND_BOX + Boîte englobante + + + + SMESHGUI_BoundingBox + + SOURCE + Source + + + OBJECTS + Objets + + + NODES + Nœuds + + + ELEMENTS + Eléments + + + COMPUTE + Calculer + + + RESULT + Boîte englobante + + + SELECTED_NB_OBJ + %1 %2 sélectionnés + + + NB_NODES + nœuds + + + NB_ELEMENTS + éléments + + diff --git a/src/SMESH_I/SMESH_2smeshpy.cxx b/src/SMESH_I/SMESH_2smeshpy.cxx index dfb378f24..26a480a4e 100644 --- a/src/SMESH_I/SMESH_2smeshpy.cxx +++ b/src/SMESH_I/SMESH_2smeshpy.cxx @@ -247,7 +247,8 @@ 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 ( id_mesh != myMeshes.end() ) + { // check for mesh editor object if ( aCommand->GetMethod() == "GetMeshEditor" ) { // MeshEditor creation _pyID editorID = aCommand->GetResultValue(); @@ -268,7 +269,8 @@ Handle(_pyCommand) _pyGen::AddCommand( const TCollection_AsciiString& theCommand // SMESH_MeshEditor method? map< _pyID, Handle(_pyMeshEditor) >::iterator id_editor = myMeshEditors.find( objID ); - if ( id_editor != myMeshEditors.end() ) { + if ( id_editor != myMeshEditors.end() ) + { id_editor->second->Process( aCommand ); TCollection_AsciiString processedCommand = aCommand->GetString(); // some commands of SMESH_MeshEditor create meshes @@ -277,6 +279,15 @@ Handle(_pyCommand) _pyGen::AddCommand( const TCollection_AsciiString& theCommand aCommand->GetString() = processedCommand; // discard changes made by _pyMesh myMeshes.insert( make_pair( mesh->GetID(), mesh )); } + if ( aCommand->GetMethod() == "MakeBoundaryMesh") { + _pyID meshID = aCommand->GetResultValue(0); + if ( !myMeshes.count( meshID ) ) + { + Handle(_pyMesh) mesh = new _pyMesh( aCommand, meshID ); + aCommand->GetString() = processedCommand; // discard changes made by _pyMesh + myMeshes.insert( make_pair( meshID, mesh )); + } + } return aCommand; } // SMESH_Hypothesis method? @@ -352,7 +363,7 @@ void _pyGen::Process( const Handle(_pyCommand)& theCommand ) myMeshes.insert( make_pair( mesh->GetID(), mesh )); return; } - if ( method == "CreateMeshesFromUNV" || method == "CreateMeshesFromSTL") + if ( method == "CreateMeshesFromUNV" || method == "CreateMeshesFromSTL" || method == "CopyMesh" ) { Handle(_pyMesh) mesh = new _pyMesh( theCommand, theCommand->GetResultValue() ); myMeshes.insert( make_pair( mesh->GetID(), mesh )); @@ -1118,14 +1129,15 @@ void _pyMeshEditor::Process( const Handle(_pyCommand)& theCommand) "ConvertToQuadratic","ConvertFromQuadratic","RenumberNodes","RenumberElements", "RotationSweep","RotationSweepObject","RotationSweepObject1D","RotationSweepObject2D", "ExtrusionSweep","AdvancedExtrusion","ExtrusionSweepObject","ExtrusionSweepObject1D","ExtrusionSweepObject2D", - "ExtrusionAlongPath","ExtrusionAlongPathObject","ExtrusionAlongPathObject1D","ExtrusionAlongPathObject2D", + "ExtrusionAlongPath","ExtrusionAlongPathObject","ExtrusionAlongPathX", + "ExtrusionAlongPathObject1D","ExtrusionAlongPathObject2D", "Mirror","MirrorObject","Translate","TranslateObject","Rotate","RotateObject", "FindCoincidentNodes",/*"FindCoincidentNodesOnPart",*/"MergeNodes","FindEqualElements", "MergeElements","MergeEqualElements","SewFreeBorders","SewConformFreeBorders", "SewBorderToSide","SewSideElements","ChangeElemNodes","GetLastCreatedNodes", "GetLastCreatedElems", "MirrorMakeMesh","MirrorObjectMakeMesh","TranslateMakeMesh", - "TranslateObjectMakeMesh","RotateMakeMesh","RotateObjectMakeMesh" + "TranslateObjectMakeMesh","RotateMakeMesh","RotateObjectMakeMesh","MakeBoundaryMesh" ,"" }; // <- mark of the end sameMethods.Insert( names ); } @@ -1166,6 +1178,13 @@ void _pyMeshEditor::Process( const Handle(_pyCommand)& theCommand) } } + // set "ExtrusionAlongPathX()" instead of "ExtrusionAlongPathObjX()" + if ( !isPyMeshMethod && method == "ExtrusionAlongPathObjX") + { + isPyMeshMethod=true; + theCommand->SetMethod("ExtrusionAlongPathX"); + } + // set "FindCoincidentNodesOnPart()" instead of "FindCoincidentNodesOnPartBut()" if ( !isPyMeshMethod && method == "FindCoincidentNodesOnPartBut") { diff --git a/src/SMESH_I/SMESH_DumpPython.cxx b/src/SMESH_I/SMESH_DumpPython.cxx index 3fd8ff22f..a8e4205b2 100644 --- a/src/SMESH_I/SMESH_DumpPython.cxx +++ b/src/SMESH_I/SMESH_DumpPython.cxx @@ -232,7 +232,10 @@ namespace SMESH if(!aSObject->_is_nil() || CORBA::is_nil( theArg )) return *this << aSObject; SMESH::long_array_var anElementsId = theArg->GetIDs(); - return *this << anElementsId; + SMESH::SMESH_Mesh_var mesh = theArg->GetMesh(); + SMESH::array_of_ElementType_var types = theArg->GetTypes(); + SMESH::ElementType type = types->length() ? types[0] : SMESH::ALL; + return *this << mesh << ".GetIDSource(" << anElementsId << ", " << type << ")"; } TPythonDump& @@ -266,43 +269,47 @@ namespace SMESH if ( theArg ) { FunctorType aFunctorType = theArg->GetFunctorType(); switch(aFunctorType){ - case FT_AspectRatio: myStream<< "anAspectRatio"; break; - case FT_AspectRatio3D: myStream<< "anAspectRatio3D"; break; - case FT_Warping: myStream<< "aWarping"; break; - case FT_MinimumAngle: myStream<< "aMinimumAngle"; break; - case FT_Taper: myStream<< "aTaper"; break; - case FT_Skew: myStream<< "aSkew"; break; - case FT_Area: myStream<< "aArea"; break; - case FT_Volume3D: myStream<< "aVolume3D"; break; - case FT_MaxElementLength2D:myStream<< "aMaxElementLength2D";break; - case FT_MaxElementLength3D:myStream<< "aMaxElementLength3D";break; - case FT_FreeBorders: myStream<< "aFreeBorders"; break; - case FT_FreeEdges: myStream<< "aFreeEdges"; break; - case FT_FreeNodes: myStream<< "aFreeNodes"; break; - case FT_FreeFaces: myStream<< "aFreeFaces"; break; - case FT_MultiConnection: myStream<< "aMultiConnection"; break; - case FT_MultiConnection2D:myStream<< "aMultiConnection2D";break; - case FT_Length: myStream<< "aLength"; break; - case FT_Length2D: myStream<< "aLength"; break; - case FT_BelongToGeom: myStream<< "aBelongToGeom"; break; - case FT_BelongToPlane: myStream<< "aBelongToPlane"; break; - case FT_BelongToCylinder: myStream<< "aBelongToCylinder"; break; - case FT_BelongToGenSurface:myStream<<"aBelongToGenSurface";break; - case FT_LyingOnGeom: myStream<< "aLyingOnGeom"; break; - case FT_CoplanarFaces: myStream<< "aCoplanarFaces"; break; - case FT_RangeOfIds: myStream<< "aRangeOfIds"; break; - case FT_BadOrientedVolume:myStream<< "aBadOrientedVolume";break; - case FT_LinearOrQuadratic:myStream<< "aLinearOrQuadratic";break; - case FT_GroupColor: myStream<< "aGroupColor"; break; - case FT_ElemGeomType: myStream<< "anElemGeomType"; break; - case FT_LessThan: myStream<< "aLessThan"; break; - case FT_MoreThan: myStream<< "aMoreThan"; break; - case FT_EqualTo: myStream<< "anEqualTo"; break; - case FT_LogicalNOT: myStream<< "aLogicalNOT"; break; - case FT_LogicalAND: myStream<< "aLogicalAND"; break; - case FT_LogicalOR: myStream<< "aLogicalOR"; break; + case FT_AspectRatio: myStream<< "anAspectRatio"; break; + case FT_AspectRatio3D: myStream<< "anAspectRatio3D"; break; + case FT_Warping: myStream<< "aWarping"; break; + case FT_MinimumAngle: myStream<< "aMinimumAngle"; break; + case FT_Taper: myStream<< "aTaper"; break; + case FT_Skew: myStream<< "aSkew"; break; + case FT_Area: myStream<< "aArea"; break; + case FT_Volume3D: myStream<< "aVolume3D"; break; + case FT_MaxElementLength2D: myStream<< "aMaxElementLength2D"; break; + case FT_MaxElementLength3D: myStream<< "aMaxElementLength3D"; break; + case FT_FreeBorders: myStream<< "aFreeBorders"; break; + case FT_FreeEdges: myStream<< "aFreeEdges"; break; + case FT_FreeNodes: myStream<< "aFreeNodes"; break; + case FT_FreeFaces: myStream<< "aFreeFaces"; break; + case FT_MultiConnection: myStream<< "aMultiConnection"; break; + case FT_MultiConnection2D: myStream<< "aMultiConnection2D"; break; + case FT_Length: myStream<< "aLength"; break; + case FT_Length2D: myStream<< "aLength2D"; break; + case FT_BelongToGeom: myStream<< "aBelongToGeom"; break; + case FT_BelongToPlane: myStream<< "aBelongToPlane"; break; + case FT_BelongToCylinder: myStream<< "aBelongToCylinder"; break; + case FT_BelongToGenSurface: myStream<< "aBelongToGenSurface"; break; + case FT_LyingOnGeom: myStream<< "aLyingOnGeom"; break; + case FT_CoplanarFaces: myStream<< "aCoplanarFaces"; break; + case FT_RangeOfIds: myStream<< "aRangeOfIds"; break; + case FT_BadOrientedVolume: myStream<< "aBadOrientedVolume"; break; + case FT_BareBorderVolume: myStream<< "aBareBorderVolume"; break; + case FT_BareBorderFace: myStream<< "aBareBorderFace"; break; + case FT_OverConstrainedVolume: myStream<< "aOverConstrainedVolume"; break; + case FT_OverConstrainedFace: myStream<< "aOverConstrainedFace"; break; + case FT_LinearOrQuadratic: myStream<< "aLinearOrQuadratic"; break; + case FT_GroupColor: myStream<< "aGroupColor"; break; + case FT_ElemGeomType: myStream<< "anElemGeomType"; break; + case FT_LessThan: myStream<< "aLessThan"; break; + case FT_MoreThan: myStream<< "aMoreThan"; break; + case FT_EqualTo: myStream<< "anEqualTo"; break; + case FT_LogicalNOT: myStream<< "aLogicalNOT"; break; + case FT_LogicalAND: myStream<< "aLogicalAND"; break; + case FT_LogicalOR: myStream<< "aLogicalOR"; break; case FT_Undefined: - default: myStream<< "anUndefined"; break; + default: myStream<< "anUndefined"; break; } myStream< nbEvents; std::vector funValues; - myNumericalFunctorPtr->GetHistogram(nbIntervals,nbEvents,funValues); + std::vector elements; + myNumericalFunctorPtr->GetHistogram(nbIntervals,nbEvents,funValues,elements); nbIntervals = CORBA::Short( std::min( nbEvents.size(), funValues.size() - 1)); SMESH::Histogram_var histogram = new SMESH::Histogram; @@ -937,6 +939,66 @@ FunctorType BadOrientedVolume_i::GetFunctorType() return SMESH::FT_BadOrientedVolume; } +/* + Class : BareBorderVolume_i + Description : Verify whether a mesh volume has a free facet without a face on it +*/ +BareBorderVolume_i::BareBorderVolume_i() +{ + Controls::PredicatePtr control( new Controls::BareBorderVolume() ); + myFunctorPtr = myPredicatePtr = control; +}; + +FunctorType BareBorderVolume_i::GetFunctorType() +{ + return SMESH::FT_BareBorderVolume; +} + +/* + Class : BareBorderFace_i + Description : Verify whether a mesh face has a free border without an edge on it +*/ +BareBorderFace_i::BareBorderFace_i() +{ + Controls::PredicatePtr control( new Controls::BareBorderFace() ); + myFunctorPtr = myPredicatePtr = control; +}; + +FunctorType BareBorderFace_i::GetFunctorType() +{ + return SMESH::FT_BareBorderFace; +} + +/* + Class : OverConstrainedVolume_i + Description : Verify whether a mesh volume has only one facet shared with other volumes +*/ +OverConstrainedVolume_i::OverConstrainedVolume_i() +{ + Controls::PredicatePtr control( new Controls::OverConstrainedVolume() ); + myFunctorPtr = myPredicatePtr = control; +}; + +FunctorType OverConstrainedVolume_i::GetFunctorType() +{ + return SMESH::FT_OverConstrainedVolume; +} + +/* + Class : OverConstrainedFace_i + Description : Verify whether a mesh face has only one border shared with other faces +*/ +OverConstrainedFace_i::OverConstrainedFace_i() +{ + Controls::PredicatePtr control( new Controls::OverConstrainedFace() ); + myFunctorPtr = myPredicatePtr = control; +}; + +FunctorType OverConstrainedFace_i::GetFunctorType() +{ + return SMESH::FT_OverConstrainedFace; +} + /* Class : BelongToGeom_i Description : Predicate for selection on geometrical support @@ -2036,6 +2098,38 @@ BadOrientedVolume_ptr FilterManager_i::CreateBadOrientedVolume() return anObj._retn(); } +BareBorderVolume_ptr FilterManager_i::CreateBareBorderVolume() +{ + SMESH::BareBorderVolume_i* aServant = new SMESH::BareBorderVolume_i(); + SMESH::BareBorderVolume_var anObj = aServant->_this(); + TPythonDump()<_this(); + TPythonDump()<_this(); + TPythonDump()<_this(); + TPythonDump()<GetElementType(); + return true; + } + case FT_BareBorderVolume: + { + BareBorderVolume_i* aPred = dynamic_cast( thePred ); + + CORBA::ULong i = theCriteria->length(); + theCriteria->length( i + 1 ); + + theCriteria[ i ] = createCriterion(); + + theCriteria[ i ].Type = FT_BareBorderVolume; + theCriteria[ i ].TypeOfElement = aPred->GetElementType(); + + return true; + } + case FT_BareBorderFace: + { + BareBorderFace_i* aPred = dynamic_cast( thePred ); + + CORBA::ULong i = theCriteria->length(); + theCriteria->length( i + 1 ); + + theCriteria[ i ] = createCriterion(); + + theCriteria[ i ].Type = FT_BareBorderFace; + theCriteria[ i ].TypeOfElement = aPred->GetElementType(); + + return true; + } + case FT_OverConstrainedVolume: + { + OverConstrainedVolume_i* aPred = dynamic_cast( thePred ); + + CORBA::ULong i = theCriteria->length(); + theCriteria->length( i + 1 ); + + theCriteria[ i ] = createCriterion(); + + theCriteria[ i ].Type = FT_OverConstrainedVolume; + theCriteria[ i ].TypeOfElement = aPred->GetElementType(); + + return true; + } + case FT_OverConstrainedFace: + { + OverConstrainedFace_i* aPred = dynamic_cast( thePred ); + + CORBA::ULong i = theCriteria->length(); + theCriteria->length( i + 1 ); + + theCriteria[ i ] = createCriterion(); + + theCriteria[ i ].Type = FT_OverConstrainedFace; + theCriteria[ i ].TypeOfElement = aPred->GetElementType(); + return true; } case FT_LessThan: @@ -2723,6 +2873,26 @@ CORBA::Boolean Filter_i::SetCriteria( const SMESH::Filter::Criteria& theCriteria aPredicate = aFilterMgr->CreateBadOrientedVolume(); } break; + case SMESH::FT_BareBorderVolume: + { + aPredicate = aFilterMgr->CreateBareBorderVolume(); + } + break; + case SMESH::FT_BareBorderFace: + { + aPredicate = aFilterMgr->CreateBareBorderFace(); + } + break; + case SMESH::FT_OverConstrainedVolume: + { + aPredicate = aFilterMgr->CreateOverConstrainedVolume(); + } + break; + case SMESH::FT_OverConstrainedFace: + { + aPredicate = aFilterMgr->CreateOverConstrainedFace(); + } + break; case SMESH::FT_LinearOrQuadratic: { SMESH::LinearOrQuadratic_ptr tmpPred = aFilterMgr->CreateLinearOrQuadratic(); @@ -2963,7 +3133,11 @@ static inline LDOMString toString( CORBA::Long theType ) case FT_BelongToCylinder: return "Belong to Cylinder"; case FT_BelongToGenSurface: return "Belong to Generic Surface"; case FT_LyingOnGeom : return "Lying on Geom"; - case FT_BadOrientedVolume: return "Bad Oriented Volume"; + case FT_BadOrientedVolume:return "Bad Oriented Volume"; + case FT_BareBorderVolume: return "Volumes with bare border"; + case FT_BareBorderFace : return "Faces with bare border"; + case FT_OverConstrainedVolume: return "Over-constrained Volumes"; + case FT_OverConstrainedFace : return "Over-constrained Faces"; case FT_RangeOfIds : return "Range of IDs"; case FT_FreeBorders : return "Free borders"; case FT_FreeEdges : return "Free edges"; @@ -3017,6 +3191,10 @@ static inline SMESH::FunctorType toFunctorType( const LDOMString& theStr ) // else if ( theStr.equals( "Length2D" ) ) return FT_Length2D; else if ( theStr.equals( "Range of IDs" ) ) return FT_RangeOfIds; else if ( theStr.equals( "Bad Oriented Volume" ) ) return FT_BadOrientedVolume; + else if ( theStr.equals( "Volumes with bare border" ) ) return FT_BareBorderVolume; + else if ( theStr.equals( "Faces with bare border" ) ) return FT_BareBorderFace; + else if ( theStr.equals( "Over-constrained Volumes" ) ) return FT_OverConstrainedVolume; + else if ( theStr.equals( "Over-constrained Faces" ) ) return FT_OverConstrainedFace; else if ( theStr.equals( "Less than" ) ) return FT_LessThan; else if ( theStr.equals( "More than" ) ) return FT_MoreThan; else if ( theStr.equals( "Equal to" ) ) return FT_EqualTo; diff --git a/src/SMESH_I/SMESH_Filter_i.hxx b/src/SMESH_I/SMESH_Filter_i.hxx index bef8c2252..9ca20ddb4 100644 --- a/src/SMESH_I/SMESH_Filter_i.hxx +++ b/src/SMESH_I/SMESH_Filter_i.hxx @@ -44,6 +44,7 @@ class SMESHDS_Mesh; namespace SMESH { + // ================================================================================ namespace Controls { @@ -123,8 +124,10 @@ namespace SMESH Controls::ElementsOnShapePtr myElementsOnShapePtr; // only if myIsSubshape == false }; typedef boost::shared_ptr LyingOnGeomPtr; - } - + + } // namespace Controls + + // ================================================================================ /* FUNCTORS */ @@ -387,6 +390,54 @@ namespace SMESH FunctorType GetFunctorType(); }; + /* + Class : BareBorderVolume_i + Description : Verify whether a mesh volume has a free facet without a face on it + */ + class SMESH_I_EXPORT BareBorderVolume_i: public virtual POA_SMESH::BareBorderVolume, + public virtual Predicate_i + { + public: + BareBorderVolume_i(); + FunctorType GetFunctorType(); + }; + + /* + Class : BareBorderFace_i + Description : Verify whether a mesh face has a free border without an edge on it + */ + class SMESH_I_EXPORT BareBorderFace_i: public virtual POA_SMESH::BareBorderFace, + public virtual Predicate_i + { + public: + BareBorderFace_i(); + FunctorType GetFunctorType(); + }; + + /* + Class : OverConstrainedVolume_i + Description : Verify whether a mesh volume has only one facet shared with other volumes + */ + class SMESH_I_EXPORT OverConstrainedVolume_i: public virtual POA_SMESH::OverConstrainedVolume, + public virtual Predicate_i + { + public: + OverConstrainedVolume_i(); + FunctorType GetFunctorType(); + }; + + /* + Class : OverConstrainedFace_i + Description : Verify whether a mesh face has only one border shared with other faces + */ + class SMESH_I_EXPORT OverConstrainedFace_i: public virtual POA_SMESH::OverConstrainedFace, + public virtual Predicate_i + { + public: + OverConstrainedFace_i(); + FunctorType GetFunctorType(); + }; + /* Class : BelongToGeom_i Description : Predicate for selection on geometrical support @@ -954,6 +1005,10 @@ namespace SMESH RangeOfIds_ptr CreateRangeOfIds(); BadOrientedVolume_ptr CreateBadOrientedVolume(); + BareBorderFace_ptr CreateBareBorderFace(); + BareBorderVolume_ptr CreateBareBorderVolume(); + OverConstrainedFace_ptr CreateOverConstrainedFace(); + OverConstrainedVolume_ptr CreateOverConstrainedVolume(); LinearOrQuadratic_ptr CreateLinearOrQuadratic(); GroupColor_ptr CreateGroupColor(); ElemGeomType_ptr CreateElemGeomType(); diff --git a/src/SMESH_I/SMESH_Gen_i.cxx b/src/SMESH_I/SMESH_Gen_i.cxx index 47e0fad99..6b4fac320 100644 --- a/src/SMESH_I/SMESH_Gen_i.cxx +++ b/src/SMESH_I/SMESH_Gen_i.cxx @@ -91,9 +91,10 @@ #include "SMDS_EdgePosition.hxx" #include "SMDS_FacePosition.hxx" -#include "SMDS_VertexPosition.hxx" -#include "SMDS_SpacePosition.hxx" #include "SMDS_PolyhedralVolumeOfNodes.hxx" +#include "SMDS_SetIterator.hxx" +#include "SMDS_SpacePosition.hxx" +#include "SMDS_VertexPosition.hxx" #include CORBA_SERVER_HEADER(SMESH_Group) #include CORBA_SERVER_HEADER(SMESH_Filter) @@ -901,7 +902,7 @@ SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CreateMeshesFromUNV( const char* theFileName aServant->ImportUNVFile( theFileName ); // Dump creation of groups - aServant->GetGroups(); + SMESH::ListOfGroups_var groups = aServant->GetGroups(); aServant->GetImpl().GetMeshDS()->Modified(); return aMesh._retn(); @@ -982,7 +983,7 @@ SMESH::mesh_array* SMESH_Gen_i::CreateMeshesFromMED( const char* theFileName, } // Dump creation of groups for ( int i = 0; i < aResult->length(); ++i ) - aResult[ i ]->GetGroups(); + SMESH::ListOfGroups_var groups = aResult[ i ]->GetGroups(); return aResult._retn(); } @@ -2025,7 +2026,23 @@ SMESH_Gen_i::ConcatenateCommon(const SMESH::mesh_array& theMeshesArray, } } }//elems loop - + + // copy orphan nodes + SMDS_NodeIteratorPtr itNodes = anInitMeshDS->nodesIterator(); + while ( itNodes->more() ) + { + const SMDS_MeshNode* aNode = itNodes->next(); + if ( aNode->NbInverseElements() == 0 ) + { + const SMDS_MeshNode* aNewNode = + aNewMeshDS->AddNode(aNode->X(), aNode->Y(), aNode->Z()); + nodesMap.insert( make_pair(aNode->GetID(), aNewNode->GetID()) ); + if( theCommonGroups ) + anIDsNodes[anNbNodes++] = aNewNode->GetID(); + } + } + + aListOfGroups = anInitImpl->GetGroups(); SMESH::SMESH_GroupBase_ptr aGroup; @@ -2211,6 +2228,212 @@ SMESH_Gen_i::ConcatenateCommon(const SMESH::mesh_array& theMeshesArray, return aNewMesh._retn(); } +//================================================================================ +/*! + * \brief Create a mesh by copying a part of another mesh + * \param meshPart - a part of mesh to copy + * \param toCopyGroups - to create in the new mesh groups + * the copied elements belongs to + * \param toKeepIDs - to preserve IDs of the copied elements or not + * \retval SMESH::SMESH_Mesh_ptr - the new mesh + */ +//================================================================================ + +SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CopyMesh(SMESH::SMESH_IDSource_ptr meshPart, + const char* meshName, + CORBA::Boolean toCopyGroups, + CORBA::Boolean toKeepIDs) +{ + Unexpect aCatch(SALOME_SalomeException); + + TPythonDump* pyDump = new TPythonDump; // prevent dump from CreateMesh() + + // 1. Get source mesh + + if ( CORBA::is_nil( meshPart )) + THROW_SALOME_CORBA_EXCEPTION( "bad IDSource", SALOME::BAD_PARAM ); + + SMESH::SMESH_Mesh_var srcMesh = meshPart->GetMesh(); + SMESH_Mesh_i* srcMesh_i = SMESH::DownCast( srcMesh ); + if ( !srcMesh_i ) + THROW_SALOME_CORBA_EXCEPTION( "bad mesh of IDSource", SALOME::BAD_PARAM ); + + SMESHDS_Mesh* srcMeshDS = srcMesh_i->GetImpl().GetMeshDS(); + + // 2. Make a new mesh + + SMESH::SMESH_Mesh_var newMesh = CreateMesh(GEOM::GEOM_Object::_nil()); + SMESH_Mesh_i* newMesh_i = SMESH::DownCast( newMesh ); + if ( !newMesh_i ) + THROW_SALOME_CORBA_EXCEPTION( "can't create a mesh", SALOME::INTERNAL_ERROR ); + SALOMEDS::SObject_var meshSO = ObjectToSObject(myCurrentStudy, newMesh ); + if ( !meshSO->_is_nil() ) + { + SetName( meshSO, meshName, "Mesh" ); + SetPixMap( meshSO, "ICON_SMESH_TREE_MESH_IMPORTED"); + } + SMESHDS_Mesh* newMeshDS = newMesh_i->GetImpl().GetMeshDS(); + ::SMESH_MeshEditor editor( &newMesh_i->GetImpl() ); + + // 3. Get elements to copy + + SMDS_ElemIteratorPtr srcElemIt; + TIDSortedElemSet srcElems; + SMESH::array_of_ElementType_var srcElemTypes = meshPart->GetTypes(); + if ( SMESH::DownCast( meshPart )) + { + srcElemIt = srcMeshDS->elementsIterator(); + } + else + { + SMESH::long_array_var ids = meshPart->GetIDs(); + if ( srcElemTypes->length() == 1 && srcElemTypes[0] == SMESH::NODE ) // group of nodes + { + for (int i=0; i < ids->length(); i++) + if ( const SMDS_MeshElement * elem = srcMeshDS->FindNode( ids[i] )) + srcElems.insert( elem ); + } + else + { + for (int i=0; i < ids->length(); i++) + if ( const SMDS_MeshElement * elem = srcMeshDS->FindElement( ids[i] )) + srcElems.insert( elem ); + } + if ( srcElems.empty() ) + return newMesh._retn(); + + typedef SMDS_SetIterator< SMDS_pElement, TIDSortedElemSet::const_iterator > ElIter; + srcElemIt = SMDS_ElemIteratorPtr( new ElIter( srcElems.begin(), srcElems.end() )); + } + + // 4. Copy elements + + typedef map TE2EMap; + TE2EMap e2eMapByType[ SMDSAbs_NbElementTypes ]; + TE2EMap& n2nMap = e2eMapByType[ SMDSAbs_Node ]; + int iN; + const SMDS_MeshNode *nSrc, *nTgt; + vector< const SMDS_MeshNode* > nodes; + while ( srcElemIt->more() ) + { + const SMDS_MeshElement * elem = srcElemIt->next(); + nodes.resize( elem->NbNodes()); + SMDS_ElemIteratorPtr nIt = elem->nodesIterator(); + if ( toKeepIDs ) { + for ( iN = 0; nIt->more(); ++iN ) + { + nSrc = static_cast( nIt->next() ); + nTgt = newMeshDS->FindNode( nSrc->GetID()); + if ( !nTgt ) + nTgt = newMeshDS->AddNodeWithID( nSrc->X(), nSrc->Y(), nSrc->Z(), nSrc->GetID()); + nodes[ iN ] = nTgt; + } + } + else { + for ( iN = 0; nIt->more(); ++iN ) + { + nSrc = static_cast( nIt->next() ); + TE2EMap::iterator n2n = n2nMap.insert( make_pair( nSrc, SMDS_pNode(0) )).first; + if ( !n2n->second ) + n2n->second = newMeshDS->AddNode( nSrc->X(), nSrc->Y(), nSrc->Z() ); + nodes[ iN ] = (const SMDS_MeshNode*) n2n->second; + } + } + if ( elem->GetType() != SMDSAbs_Node ) + { + int ID = toKeepIDs ? elem->GetID() : 0; + const SMDS_MeshElement * newElem = editor.AddElement( nodes, + elem->GetType(), + elem->IsPoly(), + ID); + if ( toCopyGroups && !toKeepIDs ) + e2eMapByType[ elem->GetType() ].insert( make_pair( elem, newElem )); + } + } + + // 5. Copy groups + + int nbNewGroups = 0; + if ( toCopyGroups ) + { + SMESH_Mesh::GroupIteratorPtr gIt = srcMesh_i->GetImpl().GetGroups(); + while ( gIt->more() ) + { + SMESH_Group* group = gIt->next(); + const SMESHDS_GroupBase* groupDS = group->GetGroupDS(); + + // Check group type. We copy nodal groups containing nodes of copied element + SMDSAbs_ElementType groupType = groupDS->GetType(); + if ( groupType != SMDSAbs_Node && + newMeshDS->GetMeshInfo().NbElements( groupType ) == 0 ) + continue; // group type differs from types of meshPart + + // Find copied elements in the group + vector< const SMDS_MeshElement* > groupElems; + SMDS_ElemIteratorPtr eIt = groupDS->GetElements(); + if ( toKeepIDs ) + { + const SMDS_MeshElement* foundElem; + if ( groupType == SMDSAbs_Node ) + { + while ( eIt->more() ) + if (( foundElem = newMeshDS->FindNode( eIt->next()->GetID() ))) + groupElems.push_back( foundElem ); + } + else + { + while ( eIt->more() ) + if (( foundElem = newMeshDS->FindElement( eIt->next()->GetID() ))) + groupElems.push_back( foundElem ); + } + } + else + { + TE2EMap & e2eMap = e2eMapByType[ groupDS->GetType() ]; + if ( e2eMap.empty() ) continue; + int minID = e2eMap.begin()->first->GetID(); + int maxID = e2eMap.rbegin()->first->GetID(); + TE2EMap::iterator e2e; + while ( eIt->more() && groupElems.size() < e2eMap.size()) + { + const SMDS_MeshElement* e = eIt->next(); + if ( e->GetID() < minID || e->GetID() > maxID ) continue; + if ((e2e = e2eMap.find( e )) != e2eMap.end()) + groupElems.push_back( e2e->second ); + } + } + // Make a new group + if ( !groupElems.empty() ) + { + SMESH::SMESH_Group_var newGroupObj = + newMesh->CreateGroup( SMESH::ElementType(groupType), group->GetName() ); + if ( SMESH_GroupBase_i* newGroup_i = SMESH::DownCast( newGroupObj)) + { + SMESHDS_GroupBase * newGroupDS = newGroup_i->GetGroupDS(); + SMDS_MeshGroup& smdsGroup = ((SMESHDS_Group*)newGroupDS)->SMDSGroup(); + for ( unsigned i = 0; i < groupElems.size(); ++i ) + smdsGroup.Add( groupElems[i] ); + + nbNewGroups++; + } + } + } + } + + *pyDump << newMesh << " = " << this + << ".CopyMesh( " << meshPart << ", " + << "'" << meshName << "', " + << toCopyGroups << ", " + << toKeepIDs << ")"; + + delete pyDump; pyDump = 0; // allow dump in GetGroups() + + if ( nbNewGroups > 0 ) // dump created groups + SMESH::ListOfGroups_var groups = newMesh->GetGroups(); + + return newMesh._retn(); +} + //================================================================================ /*! * SMESH_Gen_i::GetMEDVersion diff --git a/src/SMESH_I/SMESH_Gen_i.hxx b/src/SMESH_I/SMESH_Gen_i.hxx index b2c90805c..b4003818d 100644 --- a/src/SMESH_I/SMESH_Gen_i.hxx +++ b/src/SMESH_I/SMESH_Gen_i.hxx @@ -236,6 +236,12 @@ public: SMESH::SMESH_Mesh_ptr CreateMeshesFromSTL( const char* theFileName ) throw ( SALOME::SALOME_Exception ); + // Copy a part of mesh + SMESH::SMESH_Mesh_ptr CopyMesh(SMESH::SMESH_IDSource_ptr meshPart, + const char* meshName, + CORBA::Boolean toCopyGroups, + CORBA::Boolean toKeepIDs); + // Compute mesh on a shape CORBA::Boolean Compute( SMESH::SMESH_Mesh_ptr theMesh, GEOM::GEOM_Object_ptr theShapeObject ) diff --git a/src/SMESH_I/SMESH_MeshEditor_i.cxx b/src/SMESH_I/SMESH_MeshEditor_i.cxx index d6185e107..5144d33a9 100644 --- a/src/SMESH_I/SMESH_MeshEditor_i.cxx +++ b/src/SMESH_I/SMESH_MeshEditor_i.cxx @@ -2685,6 +2685,8 @@ ExtrusionAlongPathObjX(SMESH::SMESH_IDSource_ptr Object, SMESH::ElementType ElemType, SMESH::SMESH_MeshEditor::Extrusion_Error& Error) { + TPythonDump aPythonDump; // it is here to prevent dump of GetGroups() + SMESH::long_array_var anElementsId = Object->GetIDs(); SMESH::ListOfGroups * aGroups = extrusionAlongPathX(anElementsId, Path, @@ -2698,16 +2700,12 @@ ExtrusionAlongPathObjX(SMESH::SMESH_IDSource_ptr Object, (SMDSAbs_ElementType)ElemType, Error); - if ( !myPreviewMode ) { + if (!myPreviewMode) { bool isDumpGroups = aGroups && aGroups->length() > 0; - TPythonDump aPythonDump; - if(isDumpGroups) { - aPythonDump << "("<length() > 0; - TPythonDump aPythonDump; - if(isDumpGroups) { - aPythonDump << "("<CreateGroup( SMESH::ElementType(elemType),groupName); + group_var = mesh_i->CreateGroup( SMESH::ElementType(int(elemType)-1),groupName); if ( SMESH_GroupBase_i* group_i = SMESH::DownCast( group_var )) smesh_group = group_i->GetSmeshGroup(); } @@ -5369,6 +5366,8 @@ SMESH_MeshEditor_i::MakeBoundaryMesh(SMESH::SMESH_IDSource_ptr idSource, storeResult( aMeshEditor ); } + const char* dimName[] = { "BND_2DFROM3D", "BND_1DFROM3D", "BND_1DFROM2D" }; + // result of MakeBoundaryMesh() is a tuple (mesh, group) if ( mesh_var->_is_nil() ) pyDump << myMesh_i->_this() << ", "; @@ -5380,9 +5379,9 @@ SMESH_MeshEditor_i::MakeBoundaryMesh(SMESH::SMESH_IDSource_ptr idSource, pyDump << group_var << " = "; pyDump << this << ".MakeBoundaryMesh( " << idSource << ", " - << dim << ", " - << groupName << ", " - << meshName<< ", " + << "SMESH." << dimName[int(dim)] << ", " + << "'" << groupName << "', " + << "'" << meshName<< "', " << toCopyElements << ", " << toCopyExistingBondary << ")"; diff --git a/src/SMESH_SWIG/ex19_sphereINcube.py b/src/SMESH_SWIG/ex19_sphereINcube.py index 043a2e312..f50a0c8e4 100644 --- a/src/SMESH_SWIG/ex19_sphereINcube.py +++ b/src/SMESH_SWIG/ex19_sphereINcube.py @@ -76,17 +76,13 @@ f4 = MakePlane(sphere_centre, MakeVectorDXDYDZ( 1, 0, -1), plan_trim) #sphere_decoupee = MakePartition(solids, sphere_outils, [], [], ShapeType["SOLID"]) -solids = geompy.SubShapeAll(sphere_troue,geompy.ShapeType["SOLID"]) -sphere_decoupee = MakePartition(solids, [f1], [], [], ShapeType["SOLID"]) -solids = geompy.SubShapeAll(sphere_decoupee,geompy.ShapeType["SOLID"]) -sphere_decoupee = MakePartition(solids, [f2], [], [], ShapeType["SOLID"]) -solids = geompy.SubShapeAll(sphere_decoupee,geompy.ShapeType["SOLID"]) -sphere_decoupee = MakePartition(solids, [f3], [], [], ShapeType["SOLID"]) -solids = geompy.SubShapeAll(sphere_decoupee,geompy.ShapeType["SOLID"]) -sphere_decoupee = MakePartition(solids, [f4], [], [], ShapeType["SOLID"]) -solids = geompy.SubShapeAll(sphere_decoupee,geompy.ShapeType["SOLID"]) - -sphere_partie = geompy.MakeCompound(solids) + +sphere_decoupee = MakePartition([sphere_troue], [f1], [], [], ShapeType["SOLID"]) +sphere_decoupee = MakePartition([sphere_decoupee], [f2], [], [], ShapeType["SOLID"]) +sphere_decoupee = MakePartition([sphere_decoupee], [f3], [], [], ShapeType["SOLID"]) +sphere_decoupee = MakePartition([sphere_decoupee], [f4], [], [], ShapeType["SOLID"]) + +sphere_partie = geompy.MakeCompound([sphere_decoupee]) sphere_partie = GetBlockNearPoint(sphere_decoupee, MakeVertex(-sphere_rayon, 0, 0)) sphere_bloc = RemoveExtraEdges(sphere_partie) @@ -113,17 +109,12 @@ cube_plein = MakeBox(-cube_cote, -cube_cote, -cube_cote, +cube_cote, +cube_co cube_trou = MakeCut(cube_plein, sphere_pleine) #cube_decoupe = MakePartition([cube_trou], sphere_outils, [], [], ShapeType["SOLID"]) -solids = geompy.SubShapeAll(cube_trou,geompy.ShapeType["SOLID"]) -cube_decoupe = MakePartition(solids, [f1], [], [], ShapeType["SOLID"]) -solids = geompy.SubShapeAll(cube_decoupe,geompy.ShapeType["SOLID"]) -cube_decoupe = MakePartition(solids, [f2], [], [], ShapeType["SOLID"]) -solids = geompy.SubShapeAll(cube_decoupe,geompy.ShapeType["SOLID"]) -cube_decoupe = MakePartition(solids, [f3], [], [], ShapeType["SOLID"]) -solids = geompy.SubShapeAll(cube_decoupe,geompy.ShapeType["SOLID"]) -cube_decoupe = MakePartition(solids, [f4], [], [], ShapeType["SOLID"]) -solids = geompy.SubShapeAll(cube_decoupe,geompy.ShapeType["SOLID"]) - -cube_decoupe = geompy.MakeCompound(solids) +cube_decoupe = MakePartition([cube_trou], [f1], [], [], ShapeType["SOLID"]) +cube_decoupe = MakePartition([cube_decoupe], [f2], [], [], ShapeType["SOLID"]) +cube_decoupe = MakePartition([cube_decoupe], [f3], [], [], ShapeType["SOLID"]) +cube_decoupe = MakePartition([cube_decoupe], [f4], [], [], ShapeType["SOLID"]) + +cube_decoupe = geompy.MakeCompound([cube_decoupe]) cube_partie = GetBlockNearPoint(cube_decoupe, MakeVertex(-cube_cote, 0, 0)) diff --git a/src/SMESH_SWIG/smeshDC.py b/src/SMESH_SWIG/smeshDC.py index f07cf3c23..3e52108c6 100644 --- a/src/SMESH_SWIG/smeshDC.py +++ b/src/SMESH_SWIG/smeshDC.py @@ -17,11 +17,10 @@ # # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com # - # File : smesh.py # Author : Francis KLOSS, OCC # Module : SMESH -# + """ \namespace smesh \brief Module smesh @@ -358,7 +357,7 @@ def ParseDirStruct(Dir): pntStr = Dir.pointStruct if isinstance(pntStr, PointStructStr6): Parameters = str(pntStr.x1Str) + var_separator + str(pntStr.x2Str) + var_separator - Parameters += str(pntStr.y1Str) + var_separator + str(pntStr.y2Str) + var_separator + Parameters += str(pntStr.y1Str) + var_separator + str(pntStr.y2Str) + var_separator Parameters += str(pntStr.z1Str) + var_separator + str(pntStr.z2Str) Point = PointStruct(pntStr.x2 - pntStr.x1, pntStr.y2 - pntStr.y1, pntStr.z2 - pntStr.z1) else: @@ -387,13 +386,13 @@ def ParseAngles(list): else: Result.append(parameter) pass - + Parameters = Parameters + str(parameter) Parameters = Parameters + var_separator pass Parameters = Parameters[:len(Parameters)-1] return Result, Parameters - + def IsEqual(val1, val2, tol=PrecisionConfusion): if abs(val1 - val2) < tol: return True @@ -491,7 +490,7 @@ def CheckPlugin(plugin): print "Warning: BLSURFPlugin module unavailable" return False return True - + # end of l1_auxiliary ## @} @@ -570,7 +569,7 @@ class smeshDC(SMESH._objref_SMESH_Gen): # @return SMESH.AxisStruct # @ingroup l1_auxiliary def GetAxisStruct(self,theObj): - edges = self.geompyD.SubShapeAll( theObj, geompyDC.ShapeType["EDGE"] ) + edges = self.geompyD.ExtractShapes( theObj, geompyDC.ShapeType["EDGE"] ) if len(edges) > 1: vertex1, vertex2 = self.geompyD.SubShapeAll( edges[0], geompyDC.ShapeType["VERTEX"] ) vertex3, vertex4 = self.geompyD.SubShapeAll( edges[1], geompyDC.ShapeType["VERTEX"] ) @@ -663,27 +662,6 @@ class smeshDC(SMESH._objref_SMESH_Gen): aMesh = Mesh(self, self.geompyD, aSmeshMesh) return aMesh - ## From SMESH_Gen interface - # @return the list of integer values - # @ingroup l1_auxiliary - def GetSubShapesId( self, theMainObject, theListOfSubObjects ): - return SMESH._objref_SMESH_Gen.GetSubShapesId(self,theMainObject, theListOfSubObjects) - - ## From SMESH_Gen interface. Creates a pattern - # @return an instance of SMESH_Pattern - # - # Example of Patterns usage - # @ingroup l2_modif_patterns - def GetPattern(self): - return SMESH._objref_SMESH_Gen.GetPattern(self) - - ## Sets number of segments per diagonal of boundary box of geometry by which - # default segment length of appropriate 1D hypotheses is defined. - # Default value is 10 - # @ingroup l1_auxiliary - def SetBoundaryBoxSegmentation(self, nbSegments): - SMESH._objref_SMESH_Gen.SetBoundaryBoxSegmentation(self,nbSegments) - ## Concatenate the given meshes into one mesh. # @return an instance of Mesh class # @param meshes the meshes to combine into one mesh @@ -707,6 +685,41 @@ class smeshDC(SMESH._objref_SMESH_Gen): aMesh = Mesh(self, self.geompyD, aSmeshMesh) return aMesh + ## Create a mesh by copying a part of another mesh. + # @param meshPart a part of mesh to copy, either a Mesh, a sub-mesh or a group; + # to copy nodes or elements not contained in any mesh object, + # pass result of Mesh.GetIDSource( list_of_ids, type ) as meshPart + # @param meshName a name of the new mesh + # @param toCopyGroups to create in the new mesh groups the copied elements belongs to + # @param toKeepIDs to preserve IDs of the copied elements or not + # @return an instance of Mesh class + def CopyMesh( self, meshPart, meshName, toCopyGroups=False, toKeepIDs=False): + if (isinstance( meshPart, Mesh )): + meshPart = meshPart.GetMesh() + mesh = SMESH._objref_SMESH_Gen.CopyMesh( self,meshPart,meshName,toCopyGroups,toKeepIDs ) + return Mesh(self, self.geompyD, mesh) + + ## From SMESH_Gen interface + # @return the list of integer values + # @ingroup l1_auxiliary + def GetSubShapesId( self, theMainObject, theListOfSubObjects ): + return SMESH._objref_SMESH_Gen.GetSubShapesId(self,theMainObject, theListOfSubObjects) + + ## From SMESH_Gen interface. Creates a pattern + # @return an instance of SMESH_Pattern + # + # Example of Patterns usage + # @ingroup l2_modif_patterns + def GetPattern(self): + return SMESH._objref_SMESH_Gen.GetPattern(self) + + ## Sets number of segments per diagonal of boundary box of geometry by which + # default segment length of appropriate 1D hypotheses is defined. + # Default value is 10 + # @ingroup l1_auxiliary + def SetBoundaryBoxSegmentation(self, nbSegments): + SMESH._objref_SMESH_Gen.SetBoundaryBoxSegmentation(self,nbSegments) + # Filtering. Auxiliary functions: # ------------------------------ @@ -735,6 +748,8 @@ class smeshDC(SMESH._objref_SMESH_Gen): # @param UnaryOp FT_LogicalNOT or FT_Undefined # @param BinaryOp a binary logical operation FT_LogicalAND, FT_LogicalOR or # FT_Undefined (must be for the last criterion of all criteria) + # @param Tolerance the tolerance used by FT_BelongToGeom, FT_BelongToSurface, + # FT_LyingOnGeom, FT_CoplanarFaces criteria # @return SMESH.Filter.Criterion # @ingroup l1_controls def GetCriterion(self,elementType, @@ -742,10 +757,12 @@ class smeshDC(SMESH._objref_SMESH_Gen): Compare = FT_EqualTo, Treshold="", UnaryOp=FT_Undefined, - BinaryOp=FT_Undefined): + BinaryOp=FT_Undefined, + Tolerance=1e-07): aCriterion = self.GetEmptyCriterion() aCriterion.TypeOfElement = elementType aCriterion.Type = self.EnumToLong(CritType) + aCriterion.Tolerance = Tolerance aTreshold = Treshold @@ -810,7 +827,9 @@ class smeshDC(SMESH._objref_SMESH_Gen): return None pass elif CritType in [FT_FreeBorders, FT_FreeEdges, FT_BadOrientedVolume, FT_FreeNodes, - FT_FreeFaces, FT_LinearOrQuadratic]: + FT_FreeFaces, FT_LinearOrQuadratic, + FT_BareBorderFace, FT_BareBorderVolume, + FT_OverConstrainedFace, FT_OverConstrainedVolume]: # At this point the treshold is unnecessary if aTreshold == FT_LogicalNOT: aCriterion.UnaryOp = self.EnumToLong(FT_LogicalNOT) @@ -845,14 +864,17 @@ class smeshDC(SMESH._objref_SMESH_Gen): # @param Compare belongs to {FT_LessThan, FT_MoreThan, FT_EqualTo} # @param Treshold the threshold value (range of id ids as string, shape, numeric) # @param UnaryOp FT_LogicalNOT or FT_Undefined + # @param Tolerance the tolerance used by FT_BelongToGeom, FT_BelongToSurface, + # FT_LyingOnGeom, FT_CoplanarFaces criteria # @return SMESH_Filter # @ingroup l1_controls def GetFilter(self,elementType, CritType=FT_Undefined, Compare=FT_EqualTo, Treshold="", - UnaryOp=FT_Undefined): - aCriterion = self.GetCriterion(elementType, CritType, Compare, Treshold, UnaryOp, FT_Undefined) + UnaryOp=FT_Undefined, + Tolerance=1e-07): + aCriterion = self.GetCriterion(elementType, CritType, Compare, Treshold, UnaryOp, FT_Undefined,Tolerance) aFilterMgr = self.CreateFilterManager() aFilter = aFilterMgr.CreateFilter() aCriteria = [] @@ -913,7 +935,7 @@ class smeshDC(SMESH._objref_SMESH_Gen): obj = obj.GetMesh() d = {} if hasattr(obj, "_narrow") and obj._narrow(SMESH.SMESH_IDSource): - values = obj.GetMeshInfo() + values = obj.GetMeshInfo() for i in range(SMESH.Entity_Last._v): if i < len(values): d[SMESH.EntityType._item(i)]=values[i] pass @@ -924,7 +946,7 @@ class smeshDC(SMESH._objref_SMESH_Gen): # If @a src2 is None, and @a id2 = 0, distance from @a src1 / @a id1 to the origin is computed. # If @a src2 is None, and @a id2 != 0, it is assumed that both @a id1 and @a id2 belong to @a src1. # - # @param src1 first source object + # @param src1 first source object # @param src2 second source object # @param id1 node/element id from the first source # @param id2 node/element id from the second (or first) source @@ -940,13 +962,13 @@ class smeshDC(SMESH._objref_SMESH_Gen): else: result = result.value return result - + ## Get measure structure specifying minimum distance data between two objects # # If @a src2 is None, and @a id2 = 0, distance from @a src1 / @a id1 to the origin is computed. # If @a src2 is None, and @a id2 != 0, it is assumed that both @a id1 and @a id2 belong to @a src1. # - # @param src1 first source object + # @param src1 first source object # @param src2 second source object # @param id1 node/element id from the first source # @param id2 node/element id from the second (or first) source @@ -985,7 +1007,7 @@ class smeshDC(SMESH._objref_SMESH_Gen): result = aMeasurements.MinDistance(src1, src2) aMeasurements.Destroy() return result - + ## Get bounding box of the specified object(s) # @param objects single source object or list of source objects # @return tuple of six values (minX, minY, minZ, maxX, maxY, maxZ) @@ -1330,8 +1352,8 @@ class Mesh: shape = geom if shape==0: shape = self.geom - nbSolids = len( self.geompyD.SubShapeAll( shape, geompyDC.ShapeType["SOLID"] )) - nbShells = len( self.geompyD.SubShapeAll( shape, geompyDC.ShapeType["SHELL"] )) + nbSolids = len( self.geompyD.ExtractShapes( shape, geompyDC.ShapeType["SOLID"] )) + nbShells = len( self.geompyD.ExtractShapes( shape, geompyDC.ShapeType["SHELL"] )) if nbSolids == 0 or nbSolids == nbShells: return Mesh_Prism3D(self, geom) return Mesh_RadialPrism3D(self, geom) @@ -1412,14 +1434,14 @@ class Mesh: except: shapeText = " on subshape #%s" % (err.subShapeID) errText = "" - stdErrors = ["OK", #COMPERR_OK + stdErrors = ["OK", #COMPERR_OK "Invalid input mesh", #COMPERR_BAD_INPUT_MESH - "std::exception", #COMPERR_STD_EXCEPTION - "OCC exception", #COMPERR_OCC_EXCEPTION - "SALOME exception", #COMPERR_SLM_EXCEPTION - "Unknown exception", #COMPERR_EXCEPTION - "Memory allocation problem", #COMPERR_MEMORY_PB - "Algorithm failed", #COMPERR_ALGO_FAILED + "std::exception", #COMPERR_STD_EXCEPTION + "OCC exception", #COMPERR_OCC_EXCEPTION + "SALOME exception", #COMPERR_SLM_EXCEPTION + "Unknown exception", #COMPERR_EXCEPTION + "Memory allocation problem", #COMPERR_MEMORY_PB + "Algorithm failed", #COMPERR_ALGO_FAILED "Unexpected geometry"]#COMPERR_BAD_SHAPE if err.code > 0: if err.code < len(stdErrors): errText = stdErrors[err.code] @@ -1744,6 +1766,8 @@ class Mesh: # @param Compare belongs to {FT_LessThan, FT_MoreThan, FT_EqualTo} # @param Treshold the threshold value (range of id ids as string, shape, numeric) # @param UnaryOp FT_LogicalNOT or FT_Undefined + # @param Tolerance the tolerance used by FT_BelongToGeom, FT_BelongToSurface, + # FT_LyingOnGeom, FT_CoplanarFaces criteria # @return SMESH_Group # @ingroup l2_grps_create def MakeGroup(self, @@ -1752,8 +1776,9 @@ class Mesh: CritType=FT_Undefined, Compare=FT_EqualTo, Treshold="", - UnaryOp=FT_Undefined): - aCriterion = self.smeshpyD.GetCriterion(elementType, CritType, Compare, Treshold, UnaryOp, FT_Undefined) + UnaryOp=FT_Undefined, + Tolerance=1e-07): + aCriterion = self.smeshpyD.GetCriterion(elementType, CritType, Compare, Treshold, UnaryOp, FT_Undefined,Tolerance) group = self.MakeGroupByCriterion(groupName, aCriterion) return group @@ -1855,15 +1880,15 @@ class Mesh: # @ingroup l2_grps_operon def UnionGroups(self, group1, group2, name): return self.mesh.UnionGroups(group1, group2, name) - + ## Produces a union list of groups - # New group is created. All mesh elements that are present in + # New group is created. All mesh elements that are present in # initial groups are added to the new one # @return an instance of SMESH_Group # @ingroup l2_grps_operon def UnionListOfGroups(self, groups, name): return self.mesh.UnionListOfGroups(groups, name) - + ## Prodices an intersection of two groups # A new group is created. All mesh elements that are common # for the two initial groups are added to the new one. @@ -1871,9 +1896,9 @@ class Mesh: # @ingroup l2_grps_operon def IntersectGroups(self, group1, group2, name): return self.mesh.IntersectGroups(group1, group2, name) - + ## Produces an intersection of groups - # New group is created. All mesh elements that are present in all + # New group is created. All mesh elements that are present in all # initial groups simultaneously are added to the new one # @return an instance of SMESH_Group # @ingroup l2_grps_operon @@ -1887,17 +1912,17 @@ class Mesh: # @ingroup l2_grps_operon def CutGroups(self, main_group, tool_group, name): return self.mesh.CutGroups(main_group, tool_group, name) - + ## Produces a cut of groups - # A new group is created. All mesh elements that are present in main groups + # A new group is created. All mesh elements that are present in main groups # but do not present in tool groups are added to the new one # @return an instance of SMESH_Group # @ingroup l2_grps_operon def CutListOfGroups(self, main_groups, tool_groups, name): return self.mesh.CutListOfGroups(main_groups, tool_groups, name) - + ## Produces a group of elements with specified element type using list of existing groups - # A new group is created. System + # A new group is created. System # 1) extract all nodes on which groups elements are built # 2) combine all elements of specified dimension laying on these nodes # @return an instance of SMESH_Group @@ -1969,6 +1994,13 @@ class Mesh: def GetMeshEditor(self): return self.mesh.GetMeshEditor() + ## Wrap a list of IDs of elements or nodes into SMESH_IDSource which + # can be passed as argument to accepting mesh, group or sub-mesh + # @return an instance of SMESH_IDSource + # @ingroup l1_auxiliary + def GetIDSource(self, ids, elemType): + return self.GetMeshEditor().MakeIDSource(ids, elemType) + ## Gets MED Mesh # @return an instance of SALOME_MED::MESH # @ingroup l1_auxiliary @@ -2346,7 +2378,7 @@ class Mesh: def MinDistance(self, id1, id2=0, isElem1=False, isElem2=False): aMeasure = self.GetMinDistance(id1, id2, isElem1, isElem2) return aMeasure.value - + ## Get measure structure specifying minimum distance data between two objects # @param id1 first node/element id # @param id2 second node/element id (if 0, distance from @a id1 to the origin is computed) @@ -2367,12 +2399,12 @@ class Mesh: pass else: id2 = None - + aMeasurements = self.smeshpyD.CreateMeasurements() aMeasure = aMeasurements.MinDistance(id1, id2) aMeasurements.Destroy() return aMeasure - + ## Get bounding box of the specified object(s) # @param objects single source object or list of source objects or list of nodes/elements IDs # @param isElem if @a objects is a list of IDs, @c True value in this parameters specifies that @a objects are elements, @@ -2421,7 +2453,7 @@ class Mesh: aMeasure = aMeasurements.BoundingBox(srclist) aMeasurements.Destroy() return aMeasure - + # Mesh edition (SMESH_MeshEditor functionality): # --------------------------------------------- @@ -2651,10 +2683,10 @@ class Mesh: # @ingroup l2_modif_throughp def FindElementsByPoint(self, x, y, z, elementType = SMESH.ALL): return self.editor.FindElementsByPoint(x, y, z, elementType) - + # Return point state in a closed 2D mesh in terms of TopAbs_State enumeration. # TopAbs_UNKNOWN state means that either mesh is wrong or the analysis fails. - + def GetPointState(self, x, y, z): return self.editor.GetPointState(x, y, z) @@ -2722,7 +2754,7 @@ class Mesh: IDsOfElements = self.GetElementsId() self.mesh.SetParameters(Parameters) Functor = 0 - if ( isinstance( theCriterion, SMESH._objref_NumericalFunctor ) ): + if ( isinstance( theCriterion, SMESH._objref_NumericalFunctor ) ): Functor = theCriterion else: Functor = self.smeshpyD.GetFunctor(theCriterion) @@ -3044,7 +3076,7 @@ class Mesh: # @param meshName - a name of new mesh to store created boundary elements in, # "" means not to create the new mesh # @param toCopyElements - if true, the checked elements will be copied into the new mesh - # @param toCopyExistingBondary - if true, not only new but also pre-existing + # @param toCopyExistingBondary - if true, not only new but also pre-existing # boundary elements will be copied into the new mesh # @return tuple (mesh, group) where bondary elements were added to # @ingroup l2_modif_edit @@ -3213,7 +3245,7 @@ class Mesh: ## Generates new elements by extrusion of the elements with given ids # @param IDsOfElements the list of elements ids for extrusion - # @param StepVector vector, defining the direction and value of extrusion + # @param StepVector vector or DirStruct, defining the direction and value of extrusion # @param NbOfSteps the number of steps # @param MakeGroups forces the generation of new groups from existing ones # @return the list of created groups (SMESH_GroupBase) if MakeGroups=True, empty list otherwise @@ -3347,7 +3379,10 @@ class Mesh: Parameters = AnglesParameters + var_separator + RefPointParameters self.mesh.SetParameters(Parameters) - if isinstance(Base,list): + if (isinstance(Path, Mesh)): + Path = Path.GetMesh() + + if isinstance(Base, list): IDsOfElements = [] if Base == []: IDsOfElements = self.GetElementsId() else: IDsOfElements = Base @@ -3355,7 +3390,8 @@ class Mesh: HasAngles, Angles, LinearVariation, HasRefPoint, RefPoint, MakeGroups, ElemType) else: - if isinstance(Base,Mesh): + if isinstance(Base, Mesh): Base = Base.GetMesh() + if isinstance(Base, SMESH._objref_SMESH_Mesh) or isinstance(Base, SMESH._objref_SMESH_Group) or isinstance(Base, SMESH._objref_SMESH_subMesh): return self.editor.ExtrusionAlongPathObjX(Base, Path, NodeStart, HasAngles, Angles, LinearVariation, HasRefPoint, RefPoint, MakeGroups, ElemType) @@ -3700,7 +3736,7 @@ class Mesh: if ( isinstance( theObject, Mesh )): theObject = theObject.GetMesh() if ( isinstance( theObject, list )): - theObject = self.editor.MakeIDSource(theObject, SMESH.ALL) + theObject = self.GetIDSource(theObject, SMESH.ALL) thePoint, Parameters = ParsePointStruct(thePoint) self.mesh.SetParameters(Parameters) @@ -3721,7 +3757,7 @@ class Mesh: if (isinstance(theObject, Mesh)): theObject = theObject.GetMesh() if ( isinstance( theObject, list )): - theObject = self.editor.MakeIDSource(theObject,SMESH.ALL) + theObject = self.GetIDSource(theObject,SMESH.ALL) mesh = self.editor.ScaleMakeMesh(theObject, thePoint, theScaleFact, MakeGroups, NewMeshName) @@ -3855,7 +3891,7 @@ class Mesh: if not isinstance( exceptNodes, list): exceptNodes = [ exceptNodes ] if exceptNodes and isinstance( exceptNodes[0], int): - exceptNodes = [ self.editor.MakeIDSource( exceptNodes, SMESH.NODE)] + exceptNodes = [ self.GetIDSource( exceptNodes, SMESH.NODE)] return self.editor.FindCoincidentNodesOnPartBut(SubMeshOrGroup, Tolerance,exceptNodes) ## Merges nodes @@ -3951,14 +3987,14 @@ class Mesh: ## Creates a hole in a mesh by doubling the nodes of some particular elements # @param theNodes identifiers of nodes to be doubled - # @param theModifiedElems identifiers of elements to be updated by the new (doubled) - # nodes. If list of element identifiers is empty then nodes are doubled but + # @param theModifiedElems identifiers of elements to be updated by the new (doubled) + # nodes. If list of element identifiers is empty then nodes are doubled but # they not assigned to elements # @return TRUE if operation has been completed successfully, FALSE otherwise # @ingroup l2_modif_edit def DoubleNodes(self, theNodes, theModifiedElems): return self.editor.DoubleNodes(theNodes, theModifiedElems) - + ## Creates a hole in a mesh by doubling the nodes of some particular elements # This method provided for convenience works as DoubleNodes() described above. # @param theNodeId identifiers of node to be doubled @@ -3967,7 +4003,7 @@ class Mesh: # @ingroup l2_modif_edit def DoubleNode(self, theNodeId, theModifiedElems): return self.editor.DoubleNode(theNodeId, theModifiedElems) - + ## Creates a hole in a mesh by doubling the nodes of some particular elements # This method provided for convenience works as DoubleNodes() described above. # @param theNodes group of nodes to be doubled @@ -3989,18 +4025,18 @@ class Mesh: # @ingroup l2_modif_edit def DoubleNodeGroups(self, theNodes, theModifiedElems): return self.editor.DoubleNodeGroups(theNodes, theModifiedElems) - + ## Creates a hole in a mesh by doubling the nodes of some particular elements # @param theElems - the list of elements (edges or faces) to be replicated # The nodes for duplication could be found from these elements # @param theNodesNot - list of nodes to NOT replicate - # @param theAffectedElems - the list of elements (cells and edges) to which the + # @param theAffectedElems - the list of elements (cells and edges) to which the # replicated nodes should be associated to. # @return TRUE if operation has been completed successfully, FALSE otherwise # @ingroup l2_modif_edit def DoubleNodeElem(self, theElems, theNodesNot, theAffectedElems): return self.editor.DoubleNodeElem(theElems, theNodesNot, theAffectedElems) - + ## Creates a hole in a mesh by doubling the nodes of some particular elements # @param theElems - the list of elements (edges or faces) to be replicated # The nodes for duplication could be found from these elements @@ -4012,7 +4048,7 @@ class Mesh: # @ingroup l2_modif_edit def DoubleNodeElemInRegion(self, theElems, theNodesNot, theShape): return self.editor.DoubleNodeElemInRegion(theElems, theNodesNot, theShape) - + ## Creates a hole in a mesh by doubling the nodes of some particular elements # This method provided for convenience works as DoubleNodes() described above. # @param theElems - group of of elements (edges or faces) to be replicated @@ -4036,7 +4072,7 @@ class Mesh: # @ingroup l2_modif_edit def DoubleNodeElemGroupInRegion(self, theElems, theNodesNot, theShape): return self.editor.DoubleNodeElemGroupInRegion(theElems, theNodesNot, theShape) - + ## Creates a hole in a mesh by doubling the nodes of some particular elements # This method provided for convenience works as DoubleNodes() described above. # @param theElems - list of groups of elements (edges or faces) to be replicated @@ -4059,7 +4095,7 @@ class Mesh: # @ingroup l2_modif_edit def DoubleNodeElemGroupsInRegion(self, theElems, theNodesNot, theShape): return self.editor.DoubleNodeElemGroupsInRegion(theElems, theNodesNot, theShape) - + ## Double nodes on shared faces between groups of volumes and create flat elements on demand. # The list of groups must describe a partition of the mesh volumes. # The nodes of the internal faces at the boundaries of the groups are doubled. @@ -4079,27 +4115,27 @@ class Mesh: else: val = 0 return val - + ## Get length of 1D element. # @param elemId mesh element ID # @return element's length value # @ingroup l1_measurements def GetLength(self, elemId): - return self._valueFromFunctor(SMESH.FT_Length, elemId) + return self._valueFromFunctor(SMESH.FT_Length, elemId) ## Get area of 2D element. # @param elemId mesh element ID # @return element's area value # @ingroup l1_measurements def GetArea(self, elemId): - return self._valueFromFunctor(SMESH.FT_Area, elemId) + return self._valueFromFunctor(SMESH.FT_Area, elemId) ## Get volume of 3D element. # @param elemId mesh element ID # @return element's volume value # @ingroup l1_measurements def GetVolume(self, elemId): - return self._valueFromFunctor(SMESH.FT_Volume3D, elemId) + return self._valueFromFunctor(SMESH.FT_Volume3D, elemId) ## Get maximum element length. # @param elemId mesh element ID @@ -4110,7 +4146,7 @@ class Mesh: ftype = SMESH.FT_MaxElementLength3D else: ftype = SMESH.FT_MaxElementLength2D - return self._valueFromFunctor(ftype, elemId) + return self._valueFromFunctor(ftype, elemId) ## Get aspect ratio of 2D or 3D element. # @param elemId mesh element ID @@ -4121,7 +4157,7 @@ class Mesh: ftype = SMESH.FT_AspectRatio3D else: ftype = SMESH.FT_AspectRatio - return self._valueFromFunctor(ftype, elemId) + return self._valueFromFunctor(ftype, elemId) ## Get warping angle of 2D element. # @param elemId mesh element ID @@ -4340,8 +4376,11 @@ class Mesh_Algorithm: pass self.mesh.smeshpyD.SetName(hypo, hyp + a) pass + geomName="" + if self.geom: + geomName = GetName(self.geom) status = self.mesh.mesh.AddHypothesis(self.geom, hypo) - TreatHypoStatus( status, GetName(hypo), GetName(self.geom), 0 ) + TreatHypoStatus( status, GetName(hypo), geomName, 0 ) return hypo ## Returns entry of the shape to mesh in the study @@ -4424,7 +4463,7 @@ class Mesh_Segment(Mesh_Algorithm): pass hyp.SetUsePreestimatedLength( length == 0.0 ) return hyp - + ## Defines "NumberOfSegments" hypothesis to cut an edge in a fixed number of segments # @param n for the number of segments that cut an edge # @param s for the scale factor (optional) @@ -4625,7 +4664,7 @@ class Mesh_Segment(Mesh_Algorithm): store_geom = self.geom if type(vertex) is types.IntType: if vertex == 0 or vertex == 1: - vertex = self.mesh.geompyD.SubShapeAllSorted(self.geom, geompyDC.ShapeType["VERTEX"])[vertex] + vertex = self.mesh.geompyD.ExtractShapes(self.geom, geompyDC.ShapeType["VERTEX"],True)[vertex] self.geom = vertex pass pass @@ -4884,20 +4923,31 @@ class Mesh_Triangle(Mesh_Algorithm): self.Parameters().SetOptionValue(optionName,level) ## Sets QuadAllowed flag. - # Only for algoType == NETGEN || NETGEN_2D || BLSURF + # Only for algoType == NETGEN(NETGEN_1D2D) || NETGEN_2D || BLSURF # @ingroup l3_hypos_netgen l3_hypos_blsurf def SetQuadAllowed(self, toAllow=True): if self.algoType == NETGEN_2D: - if toAllow: # add QuadranglePreference - self.Hypothesis("QuadranglePreference", UseExisting=1, CompareMethod=self.CompareEqualHyp) - else: # remove QuadranglePreference + if not self.params: + # use simple hyps + hasSimpleHyps = False + simpleHyps = ["QuadranglePreference","LengthFromEdges","MaxElementArea"] for hyp in self.mesh.GetHypothesisList( self.geom ): - if hyp.GetName() == "QuadranglePreference": - self.mesh.RemoveHypothesis( self.geom, hyp ) + if hyp.GetName() in simpleHyps: + hasSimpleHyps = True + if hyp.GetName() == "QuadranglePreference": + if not toAllow: # remove QuadranglePreference + self.mesh.RemoveHypothesis( self.geom, hyp ) + pass + return pass pass + if hasSimpleHyps: + if toAllow: # add QuadranglePreference + self.Hypothesis("QuadranglePreference", UseExisting=1, CompareMethod=self.CompareEqualHyp) + pass + return pass - return + pass if self.Parameters(): self.params.SetQuadAllowed(toAllow) return @@ -4906,30 +4956,25 @@ class Mesh_Triangle(Mesh_Algorithm): # # @ingroup l3_hypos_netgen def Parameters(self, which=SOLE): - if self.params: - return self.params - if self.algoType == NETGEN: - if which == SIMPLE: - self.params = self.Hypothesis("NETGEN_SimpleParameters_2D", [], + if not self.params: + if self.algoType == NETGEN: + if which == SIMPLE: + self.params = self.Hypothesis("NETGEN_SimpleParameters_2D", [], + "libNETGENEngine.so", UseExisting=0) + else: + self.params = self.Hypothesis("NETGEN_Parameters_2D", [], + "libNETGENEngine.so", UseExisting=0) + elif self.algoType == MEFISTO: + print "Mefisto algo support no multi-parameter hypothesis" + elif self.algoType == NETGEN_2D: + self.params = self.Hypothesis("NETGEN_Parameters_2D_ONLY", [], "libNETGENEngine.so", UseExisting=0) + elif self.algoType == BLSURF: + self.params = self.Hypothesis("BLSURF_Parameters", [], + "libBLSURFEngine.so", UseExisting=0) else: - self.params = self.Hypothesis("NETGEN_Parameters_2D", [], - "libNETGENEngine.so", UseExisting=0) - return self.params - elif self.algoType == MEFISTO: - print "Mefisto algo support no multi-parameter hypothesis" - return None - elif self.algoType == NETGEN_2D: - print "NETGEN_2D_ONLY algo support no multi-parameter hypothesis" - print "NETGEN_2D_ONLY uses 'MaxElementArea' and 'LengthFromEdges' ones" - return None - elif self.algoType == BLSURF: - self.params = self.Hypothesis("BLSURF_Parameters", [], - "libBLSURFEngine.so", UseExisting=0) - return self.params - else: - print "Mesh_Triangle with algo type %s does not have such a parameter, check algo type"%self.algoType - return None + print "Mesh_Triangle with algo type %s does not have such a parameter, check algo type"%self.algoType + return self.params ## Sets MaxSize # @@ -5026,14 +5071,14 @@ class Mesh_Quadrangle(Mesh_Algorithm): # @param quadType defines the algorithm of transition between differently descretized # sides of a geometrical face: # - QUAD_STANDARD - both triangles and quadrangles are possible in the transition - # area along the finer meshed sides. + # area along the finer meshed sides. # - QUAD_TRIANGLE_PREF - only triangles are built in the transition area along the # finer meshed sides. # - QUAD_QUADRANGLE_PREF - only quadrangles are built in the transition area along # the finer meshed sides, iff the total quantity of segments on # all four sides of the face is even (divisible by 2). # - QUAD_QUADRANGLE_PREF_REVERSED - same as QUAD_QUADRANGLE_PREF but the transition - # area is located along the coarser meshed sides. + # area is located along the coarser meshed sides. # - QUAD_REDUCED - only quadrangles are built and the transition between the sides # is made gradually, layer by layer. This type has a limitation on # the number of segments: one pair of opposite sides must have the @@ -5166,33 +5211,34 @@ class Mesh_Tetrahedron(Mesh_Algorithm): # # @ingroup l3_hypos_netgen def Parameters(self, which=SOLE): - if self.params: - return self.params + if not self.params: - if self.algoType == FULL_NETGEN: - if which == SIMPLE: - self.params = self.Hypothesis("NETGEN_SimpleParameters_3D", [], - "libNETGENEngine.so", UseExisting=0) - else: - self.params = self.Hypothesis("NETGEN_Parameters", [], + if self.algoType == FULL_NETGEN: + if which == SIMPLE: + self.params = self.Hypothesis("NETGEN_SimpleParameters_3D", [], + "libNETGENEngine.so", UseExisting=0) + else: + self.params = self.Hypothesis("NETGEN_Parameters", [], + "libNETGENEngine.so", UseExisting=0) + + if self.algoType == NETGEN: + self.params = self.Hypothesis("NETGEN_Parameters_3D", [], "libNETGENEngine.so", UseExisting=0) - return self.params - if self.algoType == GHS3D: - self.params = self.Hypothesis("GHS3D_Parameters", [], - "libGHS3DEngine.so", UseExisting=0) - return self.params + elif self.algoType == GHS3D: + self.params = self.Hypothesis("GHS3D_Parameters", [], + "libGHS3DEngine.so", UseExisting=0) - if self.algoType == GHS3DPRL: - self.params = self.Hypothesis("GHS3DPRL_Parameters", [], - "libGHS3DPRLEngine.so", UseExisting=0) - return self.params + elif self.algoType == GHS3DPRL: + self.params = self.Hypothesis("GHS3DPRL_Parameters", [], + "libGHS3DPRLEngine.so", UseExisting=0) + else: + print "Algo supports no multi-parameter hypothesis" - print "Algo supports no multi-parameter hypothesis" - return None + return self.params ## Sets MaxSize - # Parameter of FULL_NETGEN + # Parameter of FULL_NETGEN and NETGEN # @ingroup l3_hypos_netgen def SetMaxSize(self, theSize): self.Parameters().SetMaxSize(theSize) @@ -5204,7 +5250,7 @@ class Mesh_Tetrahedron(Mesh_Algorithm): self.Parameters().SetSecondOrder(theVal) ## Sets Optimize flag - # Parameter of FULL_NETGEN + # Parameter of FULL_NETGEN and NETGEN # @ingroup l3_hypos_netgen def SetOptimize(self, theVal): self.Parameters().SetOptimize(theVal) @@ -5911,7 +5957,7 @@ omniORB.registerObjref(StdMeshers._objref_StdMeshers_LocalLength._NP_RepositoryI #Wrapper class for StdMeshers_LayerDistribution hypothesis class LayerDistribution(StdMeshers._objref_StdMeshers_LayerDistribution): - + def SetLayerDistribution(self, hypo): StdMeshers._objref_StdMeshers_LayerDistribution.SetParameters(self,hypo.GetParameters()) hypo.ClearParameters(); @@ -5922,9 +5968,9 @@ omniORB.registerObjref(StdMeshers._objref_StdMeshers_LayerDistribution._NP_Repos #Wrapper class for StdMeshers_SegmentLengthAroundVertex hypothesis class SegmentLengthAroundVertex(StdMeshers._objref_StdMeshers_SegmentLengthAroundVertex): - + ## Set Length parameter value - # @param length numerical value or name of variable from notebook + # @param length numerical value or name of variable from notebook def SetLength(self, length): length,parameters = ParseParameters(StdMeshers._objref_StdMeshers_SegmentLengthAroundVertex.GetLastParameters(self),1,1,length) StdMeshers._objref_StdMeshers_SegmentLengthAroundVertex.SetParameters(self,parameters) @@ -5936,7 +5982,7 @@ omniORB.registerObjref(StdMeshers._objref_StdMeshers_SegmentLengthAroundVertex._ #Wrapper class for StdMeshers_Arithmetic1D hypothesis class Arithmetic1D(StdMeshers._objref_StdMeshers_Arithmetic1D): - + ## Set Length parameter value # @param length numerical value or name of variable from notebook # @param isStart true is length is Start Length, otherwise false @@ -5947,15 +5993,15 @@ class Arithmetic1D(StdMeshers._objref_StdMeshers_Arithmetic1D): length,parameters = ParseParameters(StdMeshers._objref_StdMeshers_Arithmetic1D.GetLastParameters(self),2,nb,length) StdMeshers._objref_StdMeshers_Arithmetic1D.SetParameters(self,parameters) StdMeshers._objref_StdMeshers_Arithmetic1D.SetLength(self,length,isStart) - + #Registering the new proxy for Arithmetic1D omniORB.registerObjref(StdMeshers._objref_StdMeshers_Arithmetic1D._NP_RepositoryId, Arithmetic1D) #Wrapper class for StdMeshers_Deflection1D hypothesis class Deflection1D(StdMeshers._objref_StdMeshers_Deflection1D): - + ## Set Deflection parameter value - # @param deflection numerical value or name of variable from notebook + # @param deflection numerical value or name of variable from notebook def SetDeflection(self, deflection): deflection,parameters = ParseParameters(StdMeshers._objref_StdMeshers_Deflection1D.GetLastParameters(self),1,1,deflection) StdMeshers._objref_StdMeshers_Deflection1D.SetParameters(self,parameters) @@ -5966,7 +6012,7 @@ omniORB.registerObjref(StdMeshers._objref_StdMeshers_Deflection1D._NP_Repository #Wrapper class for StdMeshers_StartEndLength hypothesis class StartEndLength(StdMeshers._objref_StdMeshers_StartEndLength): - + ## Set Length parameter value # @param length numerical value or name of variable from notebook # @param isStart true is length is Start Length, otherwise false @@ -5977,54 +6023,54 @@ class StartEndLength(StdMeshers._objref_StdMeshers_StartEndLength): length,parameters = ParseParameters(StdMeshers._objref_StdMeshers_StartEndLength.GetLastParameters(self),2,nb,length) StdMeshers._objref_StdMeshers_StartEndLength.SetParameters(self,parameters) StdMeshers._objref_StdMeshers_StartEndLength.SetLength(self,length,isStart) - + #Registering the new proxy for StartEndLength omniORB.registerObjref(StdMeshers._objref_StdMeshers_StartEndLength._NP_RepositoryId, StartEndLength) #Wrapper class for StdMeshers_MaxElementArea hypothesis class MaxElementArea(StdMeshers._objref_StdMeshers_MaxElementArea): - + ## Set Max Element Area parameter value # @param area numerical value or name of variable from notebook def SetMaxElementArea(self, area): area ,parameters = ParseParameters(StdMeshers._objref_StdMeshers_MaxElementArea.GetLastParameters(self),1,1,area) StdMeshers._objref_StdMeshers_MaxElementArea.SetParameters(self,parameters) StdMeshers._objref_StdMeshers_MaxElementArea.SetMaxElementArea(self,area) - + #Registering the new proxy for MaxElementArea omniORB.registerObjref(StdMeshers._objref_StdMeshers_MaxElementArea._NP_RepositoryId, MaxElementArea) #Wrapper class for StdMeshers_MaxElementVolume hypothesis class MaxElementVolume(StdMeshers._objref_StdMeshers_MaxElementVolume): - + ## Set Max Element Volume parameter value # @param volume numerical value or name of variable from notebook def SetMaxElementVolume(self, volume): volume ,parameters = ParseParameters(StdMeshers._objref_StdMeshers_MaxElementVolume.GetLastParameters(self),1,1,volume) StdMeshers._objref_StdMeshers_MaxElementVolume.SetParameters(self,parameters) StdMeshers._objref_StdMeshers_MaxElementVolume.SetMaxElementVolume(self,volume) - + #Registering the new proxy for MaxElementVolume omniORB.registerObjref(StdMeshers._objref_StdMeshers_MaxElementVolume._NP_RepositoryId, MaxElementVolume) #Wrapper class for StdMeshers_NumberOfLayers hypothesis class NumberOfLayers(StdMeshers._objref_StdMeshers_NumberOfLayers): - + ## Set Number Of Layers parameter value # @param nbLayers numerical value or name of variable from notebook def SetNumberOfLayers(self, nbLayers): nbLayers ,parameters = ParseParameters(StdMeshers._objref_StdMeshers_NumberOfLayers.GetLastParameters(self),1,1,nbLayers) StdMeshers._objref_StdMeshers_NumberOfLayers.SetParameters(self,parameters) StdMeshers._objref_StdMeshers_NumberOfLayers.SetNumberOfLayers(self,nbLayers) - + #Registering the new proxy for NumberOfLayers omniORB.registerObjref(StdMeshers._objref_StdMeshers_NumberOfLayers._NP_RepositoryId, NumberOfLayers) #Wrapper class for StdMeshers_NumberOfSegments hypothesis class NumberOfSegments(StdMeshers._objref_StdMeshers_NumberOfSegments): - + ## Set Number Of Segments parameter value # @param nbSeg numerical value or name of variable from notebook def SetNumberOfSegments(self, nbSeg): @@ -6032,14 +6078,14 @@ class NumberOfSegments(StdMeshers._objref_StdMeshers_NumberOfSegments): nbSeg , parameters = ParseParameters(lastParameters,1,1,nbSeg) StdMeshers._objref_StdMeshers_NumberOfSegments.SetParameters(self,parameters) StdMeshers._objref_StdMeshers_NumberOfSegments.SetNumberOfSegments(self,nbSeg) - + ## Set Scale Factor parameter value # @param factor numerical value or name of variable from notebook def SetScaleFactor(self, factor): factor, parameters = ParseParameters(StdMeshers._objref_StdMeshers_NumberOfSegments.GetLastParameters(self),2,2,factor) StdMeshers._objref_StdMeshers_NumberOfSegments.SetParameters(self,parameters) StdMeshers._objref_StdMeshers_NumberOfSegments.SetScaleFactor(self,factor) - + #Registering the new proxy for NumberOfSegments omniORB.registerObjref(StdMeshers._objref_StdMeshers_NumberOfSegments._NP_RepositoryId, NumberOfSegments) @@ -6110,7 +6156,7 @@ if not noNETGENPlugin: NETGENPlugin._objref_NETGENPlugin_SimpleHypothesis_2D.SetLocalLength(self, length) ## Set Max Element Area parameter value - # @param area numerical value or name of variable from notebook + # @param area numerical value or name of variable from notebook def SetMaxElementArea(self, area): lastParameters = NETGENPlugin._objref_NETGENPlugin_SimpleHypothesis_2D.GetLastParameters(self) area, parameters = ParseParameters(lastParameters,2,2,area) @@ -6131,7 +6177,7 @@ if not noNETGENPlugin: #Wrapper class for NETGENPlugin_SimpleHypothesis_3D hypothesis class NETGEN_SimpleParameters_3D(NETGEN_SimpleParameters_2D,NETGENPlugin._objref_NETGENPlugin_SimpleHypothesis_3D): ## Set Max Element Volume parameter value - # @param volume numerical value or name of variable from notebook + # @param volume numerical value or name of variable from notebook def SetMaxElementVolume(self, volume): lastParameters = NETGENPlugin._objref_NETGENPlugin_SimpleHypothesis_3D.GetLastParameters(self) volume, parameters = ParseParameters(lastParameters,3,3,volume) diff --git a/src/StdMeshers/StdMeshers_Import_1D.cxx b/src/StdMeshers/StdMeshers_Import_1D.cxx index b3dac25ab..9f4759a59 100644 --- a/src/StdMeshers/StdMeshers_Import_1D.cxx +++ b/src/StdMeshers/StdMeshers_Import_1D.cxx @@ -120,6 +120,7 @@ namespace // INTERNAL STUFF enum _ListenerDataType { WAIT_HYP_MODIF=1, // data indicating awaiting for valid parameters of src hyp + LISTEN_SRC_MESH, // data storing submesh depending on source mesh state SRC_HYP // data storing ImportSource hyp }; //================================================================================ @@ -130,10 +131,29 @@ namespace // INTERNAL STUFF struct _ListenerData : public SMESH_subMeshEventListenerData { const StdMeshers_ImportSource1D* _srcHyp; - _ListenerData(const StdMeshers_ImportSource1D* h): + _ListenerData(const StdMeshers_ImportSource1D* h, _ListenerDataType type=SRC_HYP): SMESH_subMeshEventListenerData(/*isDeletable=*/true), _srcHyp(h) { - myType = SRC_HYP; + myType = type; + } + }; + //================================================================================ + /*! + * \brief Comparator of sub-meshes + */ + struct _SubLess + { + bool operator()(const SMESH_subMesh* sm1, const SMESH_subMesh* sm2 ) const + { + if ( sm1 == sm2 ) return false; + if ( !sm1 || !sm2 ) return sm1 < sm2; + const TopoDS_Shape& s1 = sm1->GetSubShape(); + const TopoDS_Shape& s2 = sm2->GetSubShape(); + TopAbs_ShapeEnum t1 = s1.IsNull() ? TopAbs_SHAPE : s1.ShapeType(); + TopAbs_ShapeEnum t2 = s2.IsNull() ? TopAbs_SHAPE : s2.ShapeType(); + if ( t1 == t2) + return (sm1 < sm2); + return t1 < t2; // to have: face < edge } }; //================================================================================ @@ -146,10 +166,10 @@ namespace // INTERNAL STUFF StdMeshers_Import_1D::TNodeNodeMap _n2n; StdMeshers_Import_1D::TElemElemMap _e2e; - set< SMESH_subMesh*> _subM; // submeshes relating to this srcMesh - set< SMESH_subMesh*> _copyMeshSubM; // submeshes requesting mesh copying - set< SMESH_subMesh*> _copyGroupSubM; // submeshes requesting mesh copying - set< SMESH_subMesh*> _computedSubM; + set< SMESH_subMesh*, _SubLess > _subM; // submeshes relating to this srcMesh + set< SMESH_subMesh*, _SubLess > _copyMeshSubM; // submeshes requesting mesh copying + set< SMESH_subMesh*, _SubLess > _copyGroupSubM; // submeshes requesting mesh copying + set< SMESH_subMesh*, _SubLess > _computedSubM; SMESHDS_SubMesh* _importMeshSubDS; // submesh storing a copy of _srcMesh int _importMeshSubID; // id of _importMeshSubDS @@ -196,10 +216,30 @@ namespace // INTERNAL STUFF if ( toCopyGroups ) _copyGroupSubM.insert( sm ); else _copyGroupSubM.erase( sm ); } + void addComputed( SMESH_subMesh* sm ) + { + SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator(/*includeSelf=*/true, + /*complexShapeFirst=*/true); + while ( smIt->more() ) + { + sm = smIt->next(); + switch ( sm->GetSubShape().ShapeType() ) + { + case TopAbs_EDGE: + case TopAbs_FACE: + _subM.insert( sm ); + if ( !sm->IsEmpty() ) + _computedSubM.insert( sm ); + case TopAbs_VERTEX: + break; + default:; + } + } + } }; //================================================================================ /*! - * Listener notified on events of an imported submesh + * Listener notified on events relating to imported submesh */ class _Listener : public SMESH_subMeshEventListener { @@ -212,198 +252,248 @@ namespace // INTERNAL STUFF // return poiter to a static listener static _Listener* get() { static _Listener theListener; return &theListener; } - //-------------------------------------------------------------------------------- - /*! - * \brief Find or create ImportData for given meshes - */ - static _ImportData* getImportData(const SMESH_Mesh* srcMesh, - SMESH_Mesh* tgtMesh) - { - list< _ImportData >& dList = get()->_tgtMesh2ImportData[tgtMesh]; - list< _ImportData >::iterator d = dList.begin(); - for ( ; d != dList.end(); ++d ) - if ( d->_srcMesh == srcMesh ) - return &*d; - dList.push_back(_ImportData(srcMesh)); - return &dList.back(); - } + static _ImportData* getImportData(const SMESH_Mesh* srcMesh, SMESH_Mesh* tgtMesh); - //-------------------------------------------------------------------------------- - /*! - * \brief Remember an imported mesh and groups - * \param smDS - submesh DS holding the imported mesh - * \param sm - submesh computed by Import algo - * \param srcMeshDS - source mesh - * \param srcHyp - ImportSource hypothesis - */ - static _ImportData* storeImportSubmesh(SMESH_subMesh* importSub, - const SMESH_Mesh* srcMesh, - const StdMeshers_ImportSource1D* srcHyp) - { - // set listener to hear events of the submesh computed by "Import" algo - importSub->SetEventListener( get(), new _ListenerData(srcHyp), importSub ); - - // set a listener to hear events of the source mesh - SMESH_subMesh* smToNotify = importSub; - SMESH_subMesh* smToListen = srcMesh->GetSubMeshContaining(1); - importSub->SetEventListener - ( new SMESH_subMeshEventListener(/*isDeletable=*/true), - SMESH_subMeshEventListenerData::MakeData( smToNotify ), - smToListen ); - - // remeber the submesh - _ImportData* iData = _Listener::getImportData( srcMesh, importSub->GetFather()); - iData->_subM.insert( importSub ); - iData->trackHypParams( importSub, srcHyp ); - if ( !importSub->IsEmpty() ) - iData->_computedSubM.insert( importSub ); - if ( !iData->_copyMeshSubM.empty() && iData->_importMeshSubID < 1 ) - { - SMESH_Mesh* tgtMesh = importSub->GetFather(); - iData->_importMeshSubID = getSubmeshIDForCopiedMesh( srcMesh->GetMeshDS(),tgtMesh); - iData->_importMeshSubDS = tgtMesh->GetMeshDS()->NewSubMesh( iData->_importMeshSubID ); - } - if ( !importSub->IsEmpty() ) - iData->_computedSubM.insert( importSub ); + static void storeImportSubmesh(SMESH_subMesh* importSub, + const SMESH_Mesh* srcMesh, + const StdMeshers_ImportSource1D* srcHyp); - return iData; - } - //-------------------------------------------------------------------------------- - /*! - * \brief mark sm as missing src hyp with valid groups - */ + virtual void ProcessEvent(const int event, + const int eventType, + SMESH_subMesh* subMesh, + SMESH_subMeshEventListenerData* data, + const SMESH_Hypothesis* hyp); + void removeSubmesh( SMESH_subMesh* sm, _ListenerData* data ); + void clearSubmesh ( SMESH_subMesh* sm, _ListenerData* data, bool clearAllSub ); + + // mark sm as missing src hyp with valid groups static void waitHypModification(SMESH_subMesh* sm) { sm->SetEventListener (get(), SMESH_subMeshEventListenerData::MakeData( sm, WAIT_HYP_MODIF ), sm); } + }; + //-------------------------------------------------------------------------------- + /*! + * \brief Find or create ImportData for given meshes + */ + _ImportData* _Listener::getImportData(const SMESH_Mesh* srcMesh, + SMESH_Mesh* tgtMesh) + { + list< _ImportData >& dList = get()->_tgtMesh2ImportData[tgtMesh]; + list< _ImportData >::iterator d = dList.begin(); + for ( ; d != dList.end(); ++d ) + if ( d->_srcMesh == srcMesh ) + return &*d; + dList.push_back(_ImportData(srcMesh)); + return &dList.back(); + } - //-------------------------------------------------------------------------------- - /*! - * \brief Remove imported mesh and/or groups as soon as no more imported submeshes - * remain computed - * \param sm - submesh loosing Import algo - * \param data - data holding imported groups - */ - void removeSubmesh( SMESH_subMesh* sm, _ListenerData* data ) + //-------------------------------------------------------------------------------- + /*! + * \brief Remember an imported sub-mesh and set needed even listeners + * \param importSub - submesh computed by Import algo + * \param srcMesh - source mesh + * \param srcHyp - ImportSource hypothesis + */ + void _Listener::storeImportSubmesh(SMESH_subMesh* importSub, + const SMESH_Mesh* srcMesh, + const StdMeshers_ImportSource1D* srcHyp) + { + // set listener to hear events of the submesh computed by "Import" algo + importSub->SetEventListener( get(), new _ListenerData(srcHyp), importSub ); + + // set a listener to hear events of the source mesh + SMESH_subMesh* smToNotify = importSub; + SMESH_subMesh* smToListen = srcMesh->GetSubMeshContaining(1); + SMESH_subMeshEventListenerData* data = new _ListenerData(srcHyp, LISTEN_SRC_MESH); + data->mySubMeshes.push_back( smToNotify ); + importSub->SetEventListener( get(), data, smToListen ); + + // remeber the submesh importSub and its sub-submeshes + _ImportData* iData = _Listener::getImportData( srcMesh, importSub->GetFather()); + iData->trackHypParams( importSub, srcHyp ); + iData->addComputed( importSub ); + if ( !iData->_copyMeshSubM.empty() && iData->_importMeshSubID < 1 ) { - list< _ImportData > & dList = _tgtMesh2ImportData[ sm->GetFather() ]; - list< _ImportData >::iterator d = dList.begin(); - for ( ; d != dList.end(); ++d ) - if ( (*d)._subM.erase( sm )) + SMESH_Mesh* tgtMesh = importSub->GetFather(); + iData->_importMeshSubID = getSubmeshIDForCopiedMesh( srcMesh->GetMeshDS(),tgtMesh); + iData->_importMeshSubDS = tgtMesh->GetMeshDS()->NewSubMesh( iData->_importMeshSubID ); + } + } + //-------------------------------------------------------------------------------- + /*! + * \brief Remove imported mesh and/or groups if needed + * \param sm - submesh loosing Import algo + * \param data - data holding imported groups + */ + void _Listener::removeSubmesh( SMESH_subMesh* sm, _ListenerData* data ) + { + list< _ImportData > & dList = _tgtMesh2ImportData[ sm->GetFather() ]; + list< _ImportData >::iterator d = dList.begin(); + for ( ; d != dList.end(); ++d ) + if ( (*d)._subM.erase( sm )) + { + d->_computedSubM.erase( sm ); + bool rmMesh = d->_copyMeshSubM.erase( sm ) && d->_copyMeshSubM.empty(); + bool rmGroups = (d->_copyGroupSubM.erase( sm ) && d->_copyGroupSubM.empty()) || rmMesh; + if ( rmMesh ) + d->removeImportedMesh( sm->GetFather()->GetMeshDS() ); + if ( rmGroups && data ) + d->removeGroups( sm, data->_srcHyp ); + } + } + //-------------------------------------------------------------------------------- + /*! + * \brief Clear submeshes and remove imported mesh and/or groups if necessary + * \param sm - cleared submesh + * \param data - data holding imported groups + */ + void _Listener::clearSubmesh(SMESH_subMesh* sm, _ListenerData* data, bool clearAllSub) + { + list< _ImportData > & dList = _tgtMesh2ImportData[ sm->GetFather() ]; + list< _ImportData >::iterator d = dList.begin(); + for ( ; d != dList.end(); ++d ) + { + if ( !d->_subM.count( sm )) continue; + if ( (*d)._computedSubM.erase( sm ) ) + { + bool copyMesh = !d->_copyMeshSubM.empty(); + if ( copyMesh || clearAllSub ) { - d->_computedSubM.erase( sm ); - bool rmMesh = d->_copyMeshSubM.erase( sm ) && d->_copyMeshSubM.empty(); - bool rmGroups = (d->_copyGroupSubM.erase( sm ) && d->_copyGroupSubM.empty()) || rmMesh; - if ( rmMesh ) - d->removeImportedMesh( sm->GetFather()->GetMeshDS() ); - if ( rmGroups && data ) + // remove imported mesh and groups + d->removeImportedMesh( sm->GetFather()->GetMeshDS() ); + + if ( data ) d->removeGroups( sm, data->_srcHyp ); + + // clear the rest submeshes + if ( !d->_computedSubM.empty() ) + { + set< SMESH_subMesh*, _SubLess> subs; + subs.swap( d->_computedSubM ); // avoid recursion via events + while ( !subs.empty() ) + { + SMESH_subMesh* subM = *subs.begin(); subs.erase( subs.begin() ); + _ListenerData* hypData = (_ListenerData*) subM->GetEventListenerData( get() ); + if ( hypData ) + d->removeGroups( sm, hypData->_srcHyp ); + + subM->ComputeStateEngine( SMESH_subMesh::CLEAN ); + if ( subM->GetSubShape().ShapeType() == TopAbs_FACE ) + subM->ComputeSubMeshStateEngine( SMESH_subMesh::CLEAN ); + } + } } + sm->ComputeStateEngine( SMESH_subMesh::CLEAN ); + if ( sm->GetSubShape().ShapeType() == TopAbs_FACE ) + sm->ComputeSubMeshStateEngine( SMESH_subMesh::CLEAN ); + } + if ( data ) + d->trackHypParams( sm, data->_srcHyp ); + d->_n2n.clear(); + d->_e2e.clear(); } - //-------------------------------------------------------------------------------- - /*! - * \brief Remove imported mesh and/or groups and - * clear all submeshes with common source mesh - * \param sm - cleared submesh - * \param data - data holding imported groups - */ - void clearSubmesh( SMESH_subMesh* sm, _ListenerData* data ) + } + //-------------------------------------------------------------------------------- + /*! + * \brief Remove imported mesh and/or groups + */ + void _Listener::ProcessEvent(const int event, + const int eventType, + SMESH_subMesh* subMesh, + SMESH_subMeshEventListenerData* data, + const SMESH_Hypothesis* /*hyp*/) + { + if ( data && data->myType == WAIT_HYP_MODIF ) { - list< _ImportData > & dList = _tgtMesh2ImportData[ sm->GetFather() ]; - list< _ImportData >::iterator d = dList.begin(); - for ( ; d != dList.end(); ++d ) + // event of Import submesh + if ( SMESH_subMesh::MODIF_HYP == event && + SMESH_subMesh::ALGO_EVENT == eventType ) { - if ( !d->_subM.count( sm )) continue; - if ( (*d)._computedSubM.erase( sm ) ) - { - bool copyMesh = !d->_copyMeshSubM.empty(); - if ( copyMesh ) + // re-call SetEventListener() to take into account valid parameters + // of ImportSource hypothesis + SMESH_Gen* gen = subMesh->GetFather()->GetGen(); + if ( SMESH_Algo* algo = gen->GetAlgo(*subMesh->GetFather(), subMesh->GetSubShape())) + algo->SetEventListener( subMesh ); + } + } + else if ( data && data->myType == LISTEN_SRC_MESH ) + { + // event of source mesh + if ( SMESH_subMesh::COMPUTE_EVENT == eventType ) + { + switch ( event ) { + case SMESH_subMesh::CLEAN: + // source mesh cleaned -> clean target mesh + clearSubmesh( data->mySubMeshes.front(), (_ListenerData*) data, /*all=*/true ); + break; + case SMESH_subMesh::SUBMESH_COMPUTED: { + // source mesh computed -> reset FAILED state of Import submeshes to + // READY_TO_COMPUTE + SMESH_Mesh* srcMesh = subMesh->GetFather(); + if ( srcMesh->NbEdges() > 0 || srcMesh->NbFaces() > 0 ) { - // clear submeshes - if ( !d->_computedSubM.empty() ) + SMESH_Mesh* m = data->mySubMeshes.front()->GetFather(); + if ( SMESH_subMesh* sm1 = m->GetSubMeshContaining(1)) { - set< SMESH_subMesh*> subs; - subs.swap( d->_computedSubM ); // avoid recursion via events - while ( !subs.empty() ) - { - SMESH_subMesh* subM = *subs.begin(); subs.erase( subs.begin() ); - _ListenerData* hypData = (_ListenerData*) subM->GetEventListenerData( get() ); - if ( hypData ) - d->removeGroups( sm, hypData->_srcHyp ); - - subM->ComputeStateEngine( SMESH_subMesh::CLEAN ); - } + sm1->ComputeStateEngine(SMESH_subMesh::SUBMESH_COMPUTED ); + sm1->ComputeSubMeshStateEngine( SMESH_subMesh::SUBMESH_COMPUTED ); } - // remove imported mesh and groups - d->removeImportedMesh( sm->GetFather()->GetMeshDS() ); - - if ( data ) - d->removeGroups( sm, data->_srcHyp ); } + break; + } + default:; } - if ( data ) - d->trackHypParams( sm, data->_srcHyp ); - d->_n2n.clear(); - d->_e2e.clear(); } } - //-------------------------------------------------------------------------------- - /*! - * \brief Remove imported mesh and/or groups - */ - virtual void ProcessEvent(const int event, - const int eventType, - SMESH_subMesh* subMesh, - SMESH_subMeshEventListenerData* data, - const SMESH_Hypothesis* /*hyp*/) + else // event of Import submesh { - if ( data && data->myType == WAIT_HYP_MODIF ) + // find out what happens: import hyp modified or removed + bool removeImport = false, modifHyp = false; + if ( SMESH_subMesh::ALGO_EVENT == eventType ) + modifHyp = true; + if ( subMesh->GetAlgoState() != SMESH_subMesh::HYP_OK ) { - if ( SMESH_subMesh::MODIF_HYP == event && - SMESH_subMesh::ALGO_EVENT == eventType ) - { - SMESH_Gen* gen = subMesh->GetFather()->GetGen(); - if ( SMESH_Algo* algo = gen->GetAlgo(*subMesh->GetFather(), subMesh->GetSubShape())) - algo->SetEventListener( subMesh ); - } + removeImport = true; } - else + else if ( SMESH_subMesh::REMOVE_ALGO == event || + SMESH_subMesh::REMOVE_FATHER_ALGO == event ) { SMESH_Gen* gen = subMesh->GetFather()->GetGen(); SMESH_Algo* algo = gen->GetAlgo(*subMesh->GetFather(),subMesh->GetSubShape() ); + removeImport = ( strncmp( "Import", algo->GetName(), 6 ) != 0 ); + } - if ( subMesh->GetAlgoState() != SMESH_subMesh::HYP_OK || - strncmp( "Import", algo->GetName(), 6 ) != 0 ) - { - // treate removal of Import algo from subMesh - removeSubmesh( subMesh, (_ListenerData*) data ); - } - else if ( subMesh->IsEmpty() ) - { - // treate modification of ImportSource hypothesis - clearSubmesh( subMesh, (_ListenerData*) data ); - } - else if ( SMESH_subMesh::CHECK_COMPUTE_STATE == event && - SMESH_subMesh::COMPUTE_EVENT == eventType ) - { - // check compute state of all submeshes impoting from same src mesh; - // this is to take into account 1D computed submeshes hidden by 2D import algo; - // else source mesh is not copied as _subM.size != _computedSubM.size() - list< _ImportData > & dList = _tgtMesh2ImportData[ subMesh->GetFather() ]; - list< _ImportData >::iterator d = dList.begin(); - for ( ; d != dList.end(); ++d ) - if ( d->_subM.count( subMesh )) - { - set::iterator smIt = d->_subM.begin(); - for( ; smIt != d->_subM.end(); ++smIt ) - if ( (*smIt)->IsMeshComputed() ) - d->_computedSubM.insert( *smIt); - } - } + if ( removeImport ) + { + // treate removal of Import algo from subMesh + removeSubmesh( subMesh, (_ListenerData*) data ); + } + else if ( modifHyp ) + { + // treate modification of ImportSource hypothesis + clearSubmesh( subMesh, (_ListenerData*) data, /*all=*/false ); + } + else if ( SMESH_subMesh::CHECK_COMPUTE_STATE == event && + SMESH_subMesh::COMPUTE_EVENT == eventType ) + { + // check compute state of all submeshes impoting from same src mesh; + // this is to take into account 1D computed submeshes hidden by 2D import algo; + // else source mesh is not copied as _subM.size != _computedSubM.size() + list< _ImportData > & dList = _tgtMesh2ImportData[ subMesh->GetFather() ]; + list< _ImportData >::iterator d = dList.begin(); + for ( ; d != dList.end(); ++d ) + if ( d->_subM.count( subMesh )) + { + set::iterator smIt = d->_subM.begin(); + for( ; smIt != d->_subM.end(); ++smIt ) + if ( (*smIt)->IsMeshComputed() ) + d->_computedSubM.insert( *smIt); + } } } - }; // class _Listener + } //================================================================================ /*! @@ -495,7 +585,7 @@ namespace // INTERNAL STUFF _ImportData* iData = _Listener::getImportData(srcMesh,tgtMesh); SMESH_subMesh* importedSM = tgtMesh->GetSubMesh( tgtShape ); - iData->_computedSubM.insert( importedSM ); + iData->addComputed( importedSM ); if ( iData->_computedSubM.size() != iData->_subM.size() ) return 0; // not all submeshes computed yet @@ -543,8 +633,8 @@ bool StdMeshers_Import_1D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape & th subShapeIDs.insert( shapeID ); // get nodes on vertices - list < SMESH_MeshEditor::TNodeXYZ > vertexNodes; - list < SMESH_MeshEditor::TNodeXYZ >::iterator vNIt; + list < SMESH_MeshEditor::TNodeXYZ > vertexNodes; + list < SMESH_MeshEditor::TNodeXYZ >::iterator vNIt; TopExp_Explorer vExp( theShape, TopAbs_VERTEX ); for ( ; vExp.More(); vExp.Next() ) { diff --git a/src/StdMeshers/StdMeshers_Import_1D2D.cxx b/src/StdMeshers/StdMeshers_Import_1D2D.cxx index 5d89cd128..2d98c671f 100644 --- a/src/StdMeshers/StdMeshers_Import_1D2D.cxx +++ b/src/StdMeshers/StdMeshers_Import_1D2D.cxx @@ -153,8 +153,8 @@ bool StdMeshers_Import_1D2D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape & const bool toCheckOri = (helper.NbAncestors( geomFace, theMesh, TopAbs_SOLID ) == 1 ); Handle(Geom_Surface) surface = BRep_Tool::Surface( geomFace ); - if ( helper.GetSubShapeOri( tgtMesh->ShapeToMesh(), geomFace) == TopAbs_REVERSED ) - surface->UReverse(); + const bool reverse = + ( helper.GetSubShapeOri( tgtMesh->ShapeToMesh(), geomFace) == TopAbs_REVERSED ); gp_Pnt p; gp_Vec du, dv; set subShapeIDs; @@ -262,7 +262,7 @@ bool StdMeshers_Import_1D2D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape & { uv = helper.GetNodeUV( geomFace, newNodes[++iNode] ); surface->D1( uv.X(),uv.Y(), p, du,dv ); - geomNorm = du ^ dv; + geomNorm = reverse ? dv^du : du^dv; } while ( geomNorm.SquareMagnitude() < 1e-6 && iNode+1 < face->NbCornerNodes()); @@ -341,7 +341,7 @@ bool StdMeshers_Import_1D2D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape & int nbFaces = link2Nb->second; if ( nbFaces == 1 ) { - // check if the link lie on face boundary + // check if a not shared link lie on face boundary bool nodesOnBoundary = true; list< TopoDS_Shape > bndShapes; for ( int is1stN = 0; is1stN < 2 && nodesOnBoundary; ++is1stN ) @@ -356,6 +356,7 @@ bool StdMeshers_Import_1D2D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape & if ( Abs(u-f) < 2 * faceTol || Abs(u-l) < 2 * faceTol ) // duplicated node on vertex return error("Source elements overlap one another"); + tgtSM->RemoveNode( n, /*isNodeDeleted=*/false ); tgtMesh->SetNodeOnEdge( (SMDS_MeshNode*)n, edges[iE], u ); break; } @@ -371,10 +372,10 @@ bool StdMeshers_Import_1D2D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape & } } if ( !nodesOnBoundary ) - break; // free internal link + break; // error: free internal link if ( bndShapes.front().ShapeType() == TopAbs_EDGE && bndShapes.front() != bndShapes.back() ) - break; // link nodes on different geom edges + break; // error: link nodes on different geom edges // find geom edge the link is on if ( bndShapes.back().ShapeType() != TopAbs_EDGE ) @@ -389,7 +390,7 @@ bool StdMeshers_Import_1D2D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape & geomEdge.Nullify(); } if ( geomEdge.IsNull() ) - break; // vertices belong to different edges -> free internal link + break; // vertices belong to different edges -> error: free internal link bndShapes.push_back( geomEdge ); } @@ -407,15 +408,13 @@ bool StdMeshers_Import_1D2D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape & TopoDS_Edge geomEdge = TopoDS::Edge(bndShapes.back()); helper.CheckNodeU( geomEdge, link._medium, u, 10*faceTol, /*force=*/true ); + tgtSM->RemoveNode( link._medium, /*isNodeDeleted=*/false ); tgtMesh->SetNodeOnEdge( (SMDS_MeshNode*)link._medium, geomEdge, u ); } else { edge = tgtMesh->AddEdge( newNodes[0], newNodes[1]); } - // remove nodes from submesh of theShape - for ( unsigned i = 0; i < newNodes.size(); ++i ) - tgtSM->RemoveNode( newNodes[i], /*isNodeDeleted=*/false ); if ( !edge ) return false; diff --git a/src/StdMeshers/StdMeshers_ProjectionUtils.cxx b/src/StdMeshers/StdMeshers_ProjectionUtils.cxx index 86edbacfd..7749da81c 100644 --- a/src/StdMeshers/StdMeshers_ProjectionUtils.cxx +++ b/src/StdMeshers/StdMeshers_ProjectionUtils.cxx @@ -1082,6 +1082,7 @@ bool StdMeshers_ProjectionUtils::FindSubShapeAssociation(const TopoDS_Shape& the TopTools_IndexedMapOfShape vMap1, vMap2; TopExp::MapShapes( theShape1, TopAbs_VERTEX, vMap1 ); TopExp::MapShapes( theShape2, TopAbs_VERTEX, vMap2 ); + TopoDS_Vertex VV1[2], VV2[2]; if ( vMap1.Extent() != vMap2.Extent() ) RETURN_BAD_RESULT("Different nb of vertices"); @@ -1095,6 +1096,32 @@ bool StdMeshers_ProjectionUtils::FindSubShapeAssociation(const TopoDS_Shape& the return FindSubShapeAssociation( theShape1, theMesh1, theShape2, theMesh2, theMap); } + // Try to associate by common vertices of an edge + for ( int i = 1; i <= vMap1.Extent(); ++i ) + { + const TopoDS_Shape& v1 = vMap1(i); + if ( vMap2.Contains( v1 )) + { + // find an egde sharing v1 and sharing at the same time another common vertex + PShapeIteratorPtr edgeIt = SMESH_MesherHelper::GetAncestors( v1, *theMesh1, TopAbs_EDGE); + bool edgeFound = false; + while ( edgeIt->more() && !edgeFound ) + { + TopoDS_Edge edge = TopoDS::Edge( edgeIt->next()->Oriented(TopAbs_FORWARD)); + TopExp::Vertices(edge, VV1[0], VV1[1]); + if ( !VV1[0].IsSame( VV1[1] )) + edgeFound = ( vMap2.Contains( VV1[ v1.IsSame(VV1[0]) ? 1:0])); + } + if ( edgeFound ) + { + InsertAssociation( VV1[0], VV1[0], theMap, bidirect ); + InsertAssociation( VV1[1], VV1[1], theMap, bidirect ); + if (FindSubShapeAssociation( theShape1, theMesh1, theShape2, theMesh2, theMap )) + return true; + } + } + } + // Find transformation to make the shapes be of similar size at same location Bnd_Box box[2]; @@ -1116,7 +1143,6 @@ bool StdMeshers_ProjectionUtils::FindSubShapeAssociation(const TopoDS_Shape& the // Find 2 closest vertices - TopoDS_Vertex VV1[2], VV2[2]; // get 2 linked vertices of shape 1 not belonging to an inner wire of a face TopoDS_Shape edge = theShape1; TopExp_Explorer expF( theShape1, TopAbs_FACE ), expE; diff --git a/src/StdMeshers/StdMeshers_QuadToTriaAdaptor.cxx b/src/StdMeshers/StdMeshers_QuadToTriaAdaptor.cxx index 25b472c3e..4b9731812 100644 --- a/src/StdMeshers/StdMeshers_QuadToTriaAdaptor.cxx +++ b/src/StdMeshers/StdMeshers_QuadToTriaAdaptor.cxx @@ -82,10 +82,10 @@ namespace SMESH_MeshEditor::TNodeXYZ Pj( Nrem ); // an apex node to make common to all merged pyramids + if (PrmI->GetVtkType() != VTK_PYRAMID) throw SALOME_Exception(LOCALIZED("not a pyramid")); SMDS_MeshNode* CommonNode = const_cast(PrmI->GetNode(4)); if ( CommonNode == Nrem ) return; // already merged int nbI = CommonNode->NbInverseElements( SMDSAbs_Volume ); - //cerr << __LINE__ << " " << nbI << " " << nbJ << endl; SMESH_MeshEditor::TNodeXYZ Pi( CommonNode ); gp_XYZ Pnew = ( nbI*Pi + nbJ*Pj ) / (nbI+nbJ); CommonNode->setXYZ( Pnew.X(), Pnew.Y(), Pnew.Z() ); @@ -116,7 +116,6 @@ namespace } // set the common apex node to pyramids and triangles merged with J - //cerr << __LINE__ << " NbInverseElements " << Nrem->NbInverseElements() << endl; SMDS_ElemIteratorPtr itJ = Nrem->GetInverseElementIterator(); while ( itJ->more() ) { @@ -124,22 +123,15 @@ namespace if ( elem->GetType() == SMDSAbs_Volume ) // pyramid { vector< const SMDS_MeshNode* > nodes( elem->begin_nodes(), elem->end_nodes() ); - //cerr << __LINE__ << " volId " << elem->GetID() << " nbNodes " << nodes.size() << endl; nodes[4] = CommonNode; MESSAGE("ChangeElementNodes"); meshDS->ChangeElementNodes( elem, &nodes[0], nodes.size()); } else if ( tempTrias.count(elem) ) // tmp triangles { - //cerr << __LINE__ << " triaId " << elem->GetID() << endl; ((SMDS_VtkFace*) elem )->ChangeApex( CommonNode ); } -// else -// { -// cerr << __LINE__ << " other " << elem->GetVtkType() << endl; -// } } - //cerr << __LINE__ << " NbInverseElements " << Nrem->NbInverseElements() << endl; ASSERT( Nrem->NbInverseElements() == 0 ); meshDS->RemoveFreeNode( Nrem, meshDS->MeshElements( Nrem->getshapeId()), @@ -157,6 +149,8 @@ namespace const SMDS_MeshElement* PrmJ, const bool hasShape) { + if (PrmI->GetVtkType() != VTK_PYRAMID) throw SALOME_Exception(LOCALIZED("not a pyramid")); + if (PrmJ->GetVtkType() != VTK_PYRAMID) throw SALOME_Exception(LOCALIZED("not a pyramid")); const SMDS_MeshNode* nApexI = PrmI->GetNode(4); const SMDS_MeshNode* nApexJ = PrmJ->GetNode(4); if ( nApexI == nApexJ || @@ -264,6 +258,7 @@ namespace TRemTrias & tempTrias, set& nodesToMove) { + if (PrmI->GetVtkType() != VTK_PYRAMID) throw SALOME_Exception(LOCALIZED("not a pyramid")); TIDSortedElemSet adjacentPyrams, mergedPyrams; for(int k=0; k<4; k++) // loop on 4 base nodes of PrmI { @@ -302,6 +297,8 @@ namespace StdMeshers_QuadToTriaAdaptor::StdMeshers_QuadToTriaAdaptor(): myElemSearcher(0), myNbTriangles(0) { + myResMap.clear(); + myTempTriangles.clear(); } //================================================================================ @@ -1003,6 +1000,7 @@ bool StdMeshers_QuadToTriaAdaptor::Compute2ndPart(SMESH_Mesh& aMesh) return true; SMESHDS_Mesh * meshDS = aMesh.GetMeshDS(); + if (myPyramids[0]->GetVtkType() != VTK_PYRAMID) throw SALOME_Exception(LOCALIZED("not a pyramid")); int i, j, k, myShapeID = myPyramids[0]->GetNode(4)->getshapeId(); if ( !myElemSearcher ) @@ -1016,6 +1014,7 @@ bool StdMeshers_QuadToTriaAdaptor::Compute2ndPart(SMESH_Mesh& aMesh) for ( i = 0; i < myPyramids.size(); ++i ) { const SMDS_MeshElement* PrmI = myPyramids[i]; + if (PrmI->GetVtkType() != VTK_PYRAMID) throw SALOME_Exception(LOCALIZED("not a pyramid")); MergeAdjacent( PrmI, aMesh, myTempTriangles, nodesToMove ); } @@ -1023,6 +1022,7 @@ bool StdMeshers_QuadToTriaAdaptor::Compute2ndPart(SMESH_Mesh& aMesh) for ( i = 0; i < myPyramids.size(); ++i ) { const SMDS_MeshElement* PrmI = myPyramids[i]; + if (PrmI->GetVtkType() != VTK_PYRAMID) throw SALOME_Exception(LOCALIZED("not a pyramid")); // compare PrmI with all the rest pyramids @@ -1051,6 +1051,7 @@ bool StdMeshers_QuadToTriaAdaptor::Compute2ndPart(SMESH_Mesh& aMesh) for ( j = 0; j < suspectPyrams.size(); ++j ) { const SMDS_MeshElement* PrmJ = suspectPyrams[j]; + //if (PrmJ->GetVtkType() != VTK_PYRAMID) throw SALOME_Exception(LOCALIZED("not a pyramid")); if ( PrmJ == PrmI || PrmJ->NbCornerNodes() != 5 ) continue; if ( myShapeID != PrmJ->GetNode(4)->getshapeId()) @@ -1135,12 +1136,12 @@ bool StdMeshers_QuadToTriaAdaptor::Compute2ndPart(SMESH_Mesh& aMesh) } // loop on all pyramids - if( !nodesToMove.empty() && !meshDS->IsEmbeddedMode() ) - { - set::iterator n = nodesToMove.begin(); - for ( ; n != nodesToMove.end(); ++n ) - meshDS->MoveNode( *n, (*n)->X(), (*n)->Y(), (*n)->Z() ); - } +// if( !nodesToMove.empty() && !meshDS->IsEmbeddedMode() ) +// { +// set::iterator n = nodesToMove.begin(); +// for ( ; n != nodesToMove.end(); ++n ) +// meshDS->MoveNode( *n, (*n)->X(), (*n)->Y(), (*n)->Z() ); +// } // rebind triangles of pyramids sharing the same base quadrangle to the first // entrance of the base quadrangle @@ -1148,31 +1149,30 @@ bool StdMeshers_QuadToTriaAdaptor::Compute2ndPart(SMESH_Mesh& aMesh) for ( ++q2t; q2t != myResMap.end(); ++q2t, ++q2tPrev ) { if ( q2t->first == q2tPrev->first ) - { - //cerr << __LINE__ << " splice" << endl; - q2tPrev->second.splice( q2tPrev->second.end(), q2t->second ); - } + q2tPrev->second.splice( q2tPrev->second.end(), q2t->second ); } // delete removed triangles and count resulting nb of triangles for (q2t = myResMap.begin(); q2t != myResMap.end(); ++q2t) { TTriaList & trias = q2t->second; - vector faceToErase; + set faceToErase; faceToErase.clear(); - //cerr << __LINE__ << " " << trias.size() << endl; for (TTriaList::iterator tri = trias.begin(); tri != trias.end(); ++tri) { - //cerr << " " << __LINE__ << endl; const SMDS_MeshFace* face = *tri; if (myTempTriangles.count(face) && (myTempTriangles[face] == false)) - faceToErase.push_back(face); + faceToErase.insert(face); else myNbTriangles++; } - for (vector::iterator it = faceToErase.begin(); it != faceToErase.end(); ++it) + for (set::iterator it = faceToErase.begin(); it != faceToErase.end(); ++it) { const SMDS_MeshFace *face = dynamic_cast(*it); - if (face) trias.remove(face); + if (face) + { + trias.remove(face); + myTempTriangles.erase(face); + } meshDS->RemoveFreeElement(face, 0, false); } } -- 2.30.2