From ff53fa3701555ca921fd568e921709528e26c5dc Mon Sep 17 00:00:00 2001 From: eap Date: Wed, 15 Dec 2021 18:36:27 +0300 Subject: [PATCH] bos #26454 [EDF] (2021) SMESH: interactive mesh modification --- .../modifying_meshes_cut_triangles.py | 36 + doc/salome/examples/modifying_meshes_ex11.py | 10 +- .../gui/SMESH/images/add_node_on_face-dlg.png | Bin 0 -> 15758 bytes .../gui/SMESH/images/add_node_on_face.png | Bin 0 -> 6335 bytes .../SMESH/images/add_node_on_segment-dlg.png | Bin 0 -> 16823 bytes .../gui/SMESH/images/add_node_on_segment.png | Bin 0 -> 22980 bytes .../images/mesh_split_diag_interactive.png | Bin 0 -> 3272 bytes .../images/mesh_split_face_interactive.png | Bin 0 -> 3335 bytes doc/salome/gui/SMESH/images/meshtopass1.png | Bin 19502 -> 22561 bytes doc/salome/gui/SMESH/images/meshtopass2.png | Bin 12804 -> 14652 bytes doc/salome/gui/SMESH/images/meshtopass3.png | Bin 0 -> 21569 bytes .../SMESH/images/remove_node_reconnection.png | Bin 0 -> 35130 bytes .../images/remove_node_reconnection_dlg.png | Bin 0 -> 9901 bytes .../images/remove_node_reconnection_icon.png | Bin 0 -> 3898 bytes .../gui/SMESH/input/add_node_on_face.rst | 37 + .../gui/SMESH/input/add_node_on_segment.rst | 37 + .../SMESH/input/adding_quadratic_elements.rst | 6 +- .../gui/SMESH/input/mesh_through_point.rst | 6 + .../gui/SMESH/input/modifying_meshes.rst | 4 + doc/salome/gui/SMESH/input/modules.rst | 3 + .../input/removing_nodes_and_elements.rst | 35 +- .../gui/SMESH/input/tui_modifying_meshes.rst | 10 + idl/SMESH_MeshEditor.idl | 41 +- resources/CMakeLists.txt | 4 + resources/mesh_move_node_interactive.png | Bin 0 -> 3281 bytes resources/mesh_rem_node_recon.png | Bin 0 -> 3892 bytes resources/mesh_split_diag_interactive.png | Bin 0 -> 3272 bytes resources/mesh_split_face_interactive.png | Bin 0 -> 3335 bytes src/SMDS/SMDS_ElementFactory.cxx | 7 + src/SMESH/SMESH_MeshEditor.cxx | 299 ++++++- src/SMESH/SMESH_MeshEditor.hxx | 18 + src/SMESHGUI/CMakeLists.txt | 8 + src/SMESHGUI/SMESHGUI.cxx | 71 +- src/SMESHGUI/SMESHGUI_AddNodeOnFaceDlg.cxx | 786 ++++++++++++++++++ src/SMESHGUI/SMESHGUI_AddNodeOnFaceDlg.h | 140 ++++ src/SMESHGUI/SMESHGUI_AddNodeOnSegmentDlg.cxx | 701 ++++++++++++++++ src/SMESHGUI/SMESHGUI_AddNodeOnSegmentDlg.h | 125 +++ src/SMESHGUI/SMESHGUI_InteractiveOp.cxx | 181 ++++ src/SMESHGUI/SMESHGUI_InteractiveOp.h | 88 ++ src/SMESHGUI/SMESHGUI_MakeNodeAtPointDlg.cxx | 134 ++- src/SMESHGUI/SMESHGUI_MakeNodeAtPointDlg.h | 25 +- src/SMESHGUI/SMESHGUI_Operations.h | 4 + .../SMESHGUI_RemoveNodeReconnectionDlg.cxx | 485 +++++++++++ .../SMESHGUI_RemoveNodeReconnectionDlg.h | 110 +++ src/SMESHGUI/SMESH_images.ts | 16 + src/SMESHGUI/SMESH_msg_en.ts | 170 ++++ src/SMESHUtils/SMESH_MeshAlgos.cxx | 50 ++ src/SMESHUtils/SMESH_MeshAlgos.hxx | 7 + src/SMESH_I/SMESH_2smeshpy.cxx | 6 +- src/SMESH_I/SMESH_MeshEditor_i.cxx | 174 +++- src/SMESH_I/SMESH_MeshEditor_i.hxx | 40 +- src/SMESH_SWIG/smeshBuilder.py | 34 + 52 files changed, 3854 insertions(+), 54 deletions(-) create mode 100644 doc/salome/examples/modifying_meshes_cut_triangles.py create mode 100644 doc/salome/gui/SMESH/images/add_node_on_face-dlg.png create mode 100644 doc/salome/gui/SMESH/images/add_node_on_face.png create mode 100644 doc/salome/gui/SMESH/images/add_node_on_segment-dlg.png create mode 100644 doc/salome/gui/SMESH/images/add_node_on_segment.png create mode 100644 doc/salome/gui/SMESH/images/mesh_split_diag_interactive.png create mode 100644 doc/salome/gui/SMESH/images/mesh_split_face_interactive.png create mode 100644 doc/salome/gui/SMESH/images/meshtopass3.png create mode 100644 doc/salome/gui/SMESH/images/remove_node_reconnection.png create mode 100644 doc/salome/gui/SMESH/images/remove_node_reconnection_dlg.png create mode 100644 doc/salome/gui/SMESH/images/remove_node_reconnection_icon.png create mode 100644 doc/salome/gui/SMESH/input/add_node_on_face.rst create mode 100644 doc/salome/gui/SMESH/input/add_node_on_segment.rst create mode 100644 resources/mesh_move_node_interactive.png create mode 100644 resources/mesh_rem_node_recon.png create mode 100644 resources/mesh_split_diag_interactive.png create mode 100644 resources/mesh_split_face_interactive.png create mode 100644 src/SMESHGUI/SMESHGUI_AddNodeOnFaceDlg.cxx create mode 100644 src/SMESHGUI/SMESHGUI_AddNodeOnFaceDlg.h create mode 100644 src/SMESHGUI/SMESHGUI_AddNodeOnSegmentDlg.cxx create mode 100644 src/SMESHGUI/SMESHGUI_AddNodeOnSegmentDlg.h create mode 100644 src/SMESHGUI/SMESHGUI_InteractiveOp.cxx create mode 100644 src/SMESHGUI/SMESHGUI_InteractiveOp.h create mode 100644 src/SMESHGUI/SMESHGUI_RemoveNodeReconnectionDlg.cxx create mode 100644 src/SMESHGUI/SMESHGUI_RemoveNodeReconnectionDlg.h diff --git a/doc/salome/examples/modifying_meshes_cut_triangles.py b/doc/salome/examples/modifying_meshes_cut_triangles.py new file mode 100644 index 000000000..250b55952 --- /dev/null +++ b/doc/salome/examples/modifying_meshes_cut_triangles.py @@ -0,0 +1,36 @@ +# Cutting Triangles + +import salome +salome.salome_init_without_session() +from salome.smesh import smeshBuilder +smesh = smeshBuilder.New() + +# create 3 triangles and 1 segment all sharing edge 1-2 +mesh = smesh.Mesh() +n1 = mesh.AddNode( 0, 0, 0) +n2 = mesh.AddNode( 0, 0, -10) +n3 = mesh.AddNode( 10, 0, 0) +n4 = mesh.AddNode( 0, 10, 0) +n5 = mesh.AddNode( 0, -10, 0) +mesh.AddFace([ n1, n2, n3]) +mesh.AddFace([ n1, n2, n4]) +mesh.AddFace([ n1, n2, n5]) +mesh.AddEdge([ n1, n2] ) + +# =========================================================================== +# cut all the triangles and the segment by setting a new node on the segment +# =========================================================================== + +mesh.AddNodeOnSegment( n1, n2, 0.6 ) +assert mesh.NbNodes() == 6 # one new node created +assert mesh.NbTriangles() == 6 # each of the 3 triangles is split into two +assert mesh.NbEdges() == 2 # a segment is split into two + +# =============================================================== +# cut a triangle into three by adding a new node on the triangle +# =============================================================== + +triangleID = 1 +mesh.AddNodeOnFace( triangleID, 2, 0, -6 ) +assert mesh.NbNodes() == 7 # one new node created +assert mesh.NbTriangles() == 8 # the triangles is split into three diff --git a/doc/salome/examples/modifying_meshes_ex11.py b/doc/salome/examples/modifying_meshes_ex11.py index 28b544bc0..16ffe8777 100644 --- a/doc/salome/examples/modifying_meshes_ex11.py +++ b/doc/salome/examples/modifying_meshes_ex11.py @@ -1,10 +1,18 @@ # Removing Nodes import SMESH_mechanic - mesh = SMESH_mechanic.mesh # remove nodes #246 and #255 + res = mesh.RemoveNodes([246, 255]) if res == 1: print("Nodes removing is OK!") else: print("KO nodes removing.") + + +# Removing a Node with Reconnection +# ================================== + +print("Before RemoveNodeWithReconnection(): %s nodes, %s faces" % ( mesh.NbNodes(), mesh.NbFaces())) +mesh.RemoveNodeWithReconnection( 600 ) +print("After RemoveNodeWithReconnection(): %s nodes, %s faces" % ( mesh.NbNodes(), mesh.NbFaces())) diff --git a/doc/salome/gui/SMESH/images/add_node_on_face-dlg.png b/doc/salome/gui/SMESH/images/add_node_on_face-dlg.png new file mode 100644 index 0000000000000000000000000000000000000000..64dc2257ef2878c55f2b14f0e95ea6d5533bfd06 GIT binary patch literal 15758 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 Ap8x;= literal 0 HcmV?d00001 diff --git a/doc/salome/gui/SMESH/images/add_node_on_face.png b/doc/salome/gui/SMESH/images/add_node_on_face.png new file mode 100644 index 0000000000000000000000000000000000000000..84434939f0c72bdce4fe37957f22773697292dbe GIT binary patch literal 6335 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 literal 0 HcmV?d00001 diff --git a/doc/salome/gui/SMESH/images/add_node_on_segment-dlg.png b/doc/salome/gui/SMESH/images/add_node_on_segment-dlg.png new file mode 100644 index 0000000000000000000000000000000000000000..25cbb08ca33b7e357acf65df6d1ded8da204016c GIT binary patch literal 16823 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 literal 0 HcmV?d00001 diff --git a/doc/salome/gui/SMESH/images/mesh_split_diag_interactive.png b/doc/salome/gui/SMESH/images/mesh_split_diag_interactive.png new file mode 100644 index 0000000000000000000000000000000000000000..1342df96e13ce87e04077ad47b007cca3080120a GIT binary patch literal 3272 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 REbagR002ovPDHLkV1lkWK|}xm literal 0 HcmV?d00001 diff --git a/doc/salome/gui/SMESH/images/meshtopass1.png b/doc/salome/gui/SMESH/images/meshtopass1.png index 8ea8af79591ee7b5fae4554d79411e325b051565..1705f5e72b556ad6c6585d8e53b491368989a969 100644 GIT binary patch literal 22561 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®=mVDj07HoabNa6eQX`Y)eAS4cPQ7B+!dTz5f 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 R*zrp`>vaB1t3y!w{{dUSWn};W literal 19502 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 z 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 literal 12804 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 diff --git a/doc/salome/gui/SMESH/images/meshtopass3.png b/doc/salome/gui/SMESH/images/meshtopass3.png new file mode 100644 index 0000000000000000000000000000000000000000..bdbf86facddf3d501dff35e76ffad8ab747d5597 GIT binary patch literal 21569 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 M?8`{)OD_8SA0#BiY5)KL literal 0 HcmV?d00001 diff --git a/doc/salome/gui/SMESH/images/remove_node_reconnection.png b/doc/salome/gui/SMESH/images/remove_node_reconnection.png new file mode 100644 index 0000000000000000000000000000000000000000..02eef9c0d019aeef467ad2b28d92a3b8d9a5ce7e GIT binary patch literal 35130 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 z
Pgh!1q+!*BC`7UmmU&o7UnwalQGuz?iBb$xKsyzInGQr7(9;O)WjFCm9`50UP zqr2lTAUCxz%p2Q7{C!h|!_85KbR&bQfXfJdgsT^Zm|^$v%gQK2#J8xAErr{ovCu;# zn7bABGy?IptQ&vxDB*Zmy ztqd?^PfGS>XUF4aW)q!FEe>OB2=Mf#IN!2F)Zu}I9?R$aVMCVm+ZEwL6)yF z*$}RVI3vvoCKV*Pc#(%ER_~yw!NqD(5;wSctjRuv7H3L+gyA|r!3qliLxq%OW!ZGE(H(5})(@yEKLsF4q> ze(qc4WvqaxECwQZh&ANB3*F>86Wq5v%<)BG1uoj&P6qVSMH#jRtdWz7;ZNied~Ao>bn5Uxdm2o9DW{J z;m8`B?c>MPhn2x0`4P+we*U~(3<$G6T^b*1w3YF>W4jxblu2{K50i&}tfNALI5J=JeZ zhNDbPyjUCJnVK*Mo879N0|w|*{Cc4Tq>1p0d119*Y%OvMz+A8(#R^}Hi)Tj|)-2g{ zrvutx%2rJ6i;Wq^Si&4r(8LvU-8{KI$-7Mf@&azkd_IaA(>%YVn3(6uYW-y| zEzHotKz7z9X@~5|=h)+XTATO^z)0VZFb8;TTY$HAhB+!f${=H^Lyz;$>gf}lK0nG(UH{CD ztpUst7Aw!!h51``kVDKaRKP2-DKI$`Tsb$SVnzt#wjLPS1Afcs<-;8g{%^ZaWhQLv zxz_J>_FYL&n&#e=U}}+_3ko-J&zx#34H@!XA&OIBUapJrz{&(SElqNgsga3Bmr8sk zV4zlpZXAQR1ei}+0gN!#A*KK?YzgyDZH%dA*(Ua#!&+zbYI$G!J;~(c!3|#i?Tm74 zf#hnIla>CK@u+LWAJgw~3SGlK2FdD$9 z-z1)kDZ=v`0_4;NIHn-17^I`JT9@6I-({>Oo18pc<>gIBlyC3j03$H;+Lo9a15x;Q zM0eqlsTLO>IfFdAwxL%5rmeA5TNdF@vG3BSn2;ajqB%AEZLNbDO)1KpJ`7GP)0#Z| zeqDkq<_DN+v@%uzQ{Is+RWm^TU`BxVYePKvS%d@4afUW8l5&5zvd|4tY7cPz!iYMm zZ*Ok4)y}^DO~y)$|JnqYD=H(5(kD9H*9pK#ME*WcT4qi$SQlYzUV zwng1PO6<#l-QNHvlgV&SX;kS0JEP;?0+`nAl1Vklm}Hna#kjl#7gV^oe`PiQTHDA% zcZOMRAD>tqJX{sy%sClOpOs>~KETl2m;$ID&Gb>~4Rh-PCxdh2N@5xz@mv-KD04=* zydta66<}*!cYpfcA;630RZ_I{v2kEG1`(~N@0?pR@!;G%F3)pH<47F zx^RTow>!CGRgeRXaYp1s`2Ff2vm2aD&WkcYm*&QWL5iCdx`Ue)y8WFOrG1(N^J4QB z>0nI<)0Tp%^?>dzfN9+hHJHsJrhvvsvxG@-a7uxbs~0ADV!elteIBNJ11xbRm~W4B zPlc85mADy}8&v_B)fUVE749_CcBUAW6XcC;ex=YoIxoUNL;uvdw5G-W2r$RXF?AQh zjP@shX*n*!pE93hY{aHZGHr~|1v#=X%6DgHxO8!f4_sj?{C+kC5*WApcwojRmb-iu zHHCR`?j}BLimHqkgLK(Qbp0J%r2iVg9A#NjQf^FILTt?@Ej}u{j7$0ju`)} zPVvUh7{^$`YFpG5z-`@*z42X`c#6rvqZ_@v;fQi{{=Ti`Z7WzTBxO1h4cWr*oo$g?e>>#>AFael@3_f11@i490#z8uF zk1Bb)(uS@)Ba==^C`w5zx|R$V&T{aF1v^>nim@&j!Q}9uw|SV`=mg?y^ZGf{VrNip zv(~>wpy~d+dI+-}X!3FUXI`c`!<E-b9&dq@p-dNoKo!m^?n-*c#%gbt&#y5#xLLc8;|87_E;f{h_8T z7Jlz9priU`f*((}Qsnb;!+cv-J<-*Pdw?OxpSSq=wBE@vW)}l3{l}`cqdtf=@*urf z24|Q$GsPn-ZOo{%HJ_cv*bxly+735&Eemq$^dwVfq&d)(O_nD1KHC0T22zOFpO{$e zElw+Rk?ZjA;0ikfbYh>;wPWG__EdKy7#Z)ZZB~YGGRo!UO^h^!`psnPh#$3k0uIA- zBm8{6A9Jk_-G(|=hNJvtX&raWspY-x0VjM z-flli4=SSfDfwA|d1U3+6JP?#D3|SH0HY?OG0ioVAxfMPE}iM+?(*$e0%6W6Xi{;n zN9JW1TL9lF3G>^PPF`BEozL6>0?8!n0%1O=w)4!6AZM2b8IupA^U@49#MPTW)8h-m^~tjI>>K-U0`iBfPdXz>C{r{Hd~@ zMbQY4EweKz*TrdN5q`c1?pz#YTD_k_yOTw(09Af*D~R&wf?BSaW8(-3kC`hG|C+aB z%^u;sJ%DYMF936DK^9;h{u%*{jOR#Wn4c|hQI<^c!*UyA_7Mq27P}F~C|AyRpmX^7 zRi&4KpG3K9K^=L)Fp^YG=9(;s@;^itIDMRvx)6tzB>DFAG*>P4@R~h<$!241D2z3l zq^#b-?<+QNZDl=26gsm~jW`gSvj3tZ5xU8LTfDTVzo|L4y8xpaW=e8=X@F(1BzG@! zGG-qE7}a)jnnTP!p4t@T{rWIRnIrrpznc6|h%4vXl}&J^`LP|2er=pI6P?&Ryzla7WV=a6nprrJR%IpG0 znL-?_cXGVGhU=Hcc<}Qi&u#PZsXvIxI&&n!rsL9Lk*ZX+4&dc`% z-SufMYK{hX&3wDs{%C+8eNu|J=6(KvTo`Hcaqi4Ut}ENfyW8BX@~5fr_$hGO_{i<% z_v`HZYH5m}E|7RJP9|G?3^z5O0?1%CGl*74PtoBUfN_wwj{uDD)ks5#Ym;AUN&o-| z(Md!>R2F*p$R6U(MJ~n&xG2lu6t~Q4B;Oz8qUlWxHKjV7S6|^#eTD<`yqr;NU^ zUf7)Ay&Z8rYH(q4yZF@UP^K9F*pgPDc4mG(M;1za9Z9p(3_AH)5ZhfI)d1$wavQ}y zFIUaBW&y1$%q}mFFvU2d)P^aR;)ZgDDYPX4&Onu4YP8~jP;xxBnz-N4^#TwJ%< z$vJZ~oH#wkM7@X6&2ev}ZUH@E5~;JJdOI5%DeJTX7kcN{OUWxV%Std=fH|+9OEA*j zv4$X5E%fk-Bgpj?k{~{)79P1Lp$^W>Yh+qOfXAu=9AFN0n=h1KpYra`Mmrc}N^t?O z2T%B1nVZYzSh>HVnw*9N)0<*g93FIDA8*+F+_y5ojmy)VUFzbHoF)!1ei0zOC69K- zhjL%~A#>xbQU~wZyxjYlWOs;k?U-6#-q!$Ts97SI1$b_YmpAIdoLT5p@jrwZvTA%M z&&Ip;UY=U-VS**3JU=@kq|iVyL$mTs${%isGD;uhkm4lAOwVv}g^MRQIeC3kH5Hy9 zTY^bSZC?Jbs(}ZpJe)k;!?+?CWl1tf7h{k<#V|{z!_}&zHVMF-RN&@gyO+mTIT)z_ zdYmH3I7nE9%PL$HrZfCtdJ|*&sSZZkI@}oL=aoJ_b%wclu9cCxh+1T{i78gFN0^(G zC-Sqkp>Nv>c=JCxwUbaO!Hm{+30P~$vE9Q8L>z2Ay z_BL6C+w17w`dvCH$G4Nseg!VmYCN2p?^fD%xhL(C{p=wI2fthI;or^}Qwy97F?Y}R zNXnA_x7-^KHOCom3Ngjx6aI@hBf|+QAb`w{dwz0~7MX49yo;h*UOoi8-VE z{4`%bH6G0i@I;fF$2R+T#TMn;min#(%rJ9;<4b&)!YLkDW@k#Sv)@@yDuOD7u9rVm zd6eWL;3A}s*<$WnzbS@%Yh|+7UImqD#JExgy zxP4`u->pjW@7fsUB$yM6VXTXjTbJZ_iyfSAspbTWPo<#PrI6G7T-pJ1u?M+nS&H@k z7zdYRSSa>```}-907k|~ChvitI(cP_ja*-t!wo&_;lH~)An#@QD8o=goGa(qdCwN+ z)rk2UjhHTbGCVzd9eEdi+?N zF3PQO@|)s3v8;}(=QVKpOb0_H97Qva3!iIXBNEK-Hv4&_DZ-h$om~eQY4A8hfWNJ7 zz!->fs>QALnqWQz5QQ`j+jH?=3?eNGz3}0GO6_XrHC7 zT}orUgoMm+s42*~MOJQ|QG>oQsRnR{Gf0`=$0zn6Pka{T-p|uqILoh$8YjtK)*w2d ztb`)~CQKsCBEQ|TJjEJcj0r_h;n)Y!MN;}@psT(}LR+E1*jzvV+~y+J9pDIqL(y5I z``)^$F%c;=H_SB^E37tE7o3`EGR@J1p13{hLF) zwbQ|ii)yC>HDTvp5DE1i5=n?Y9}!r*pe z2nP9AwU@`&BzS14o7Xp5ndflxnb+GrfZ3C*h;4PGCw?1}mtmwS!I4D~o|TXb_00-h zL;H#C_cp+2{Z`D?EQyFg)nI*`5k}b?XE>rL$@PnZ{ArDy54PA?8%VO=AIDhd;gxDH zcdrUFwJ6TPMHzmxI?WcRhc~y_@n*gO7>&Mtd6lu0TujH9y}Y?I!2EEATj$ytEl1Jq zfQz(G1DK;MR$dfO3`gl*D74)ej^X5tC(~d(CVI6~PoA)cQCr&!vu&g(&S2 zt-k51ldY z_&m;GmN3Iiod-tlj{wsa1Ia+jzvz}kR28#t@u)o@$IJ1B0e)Hmzh2~FmCp+#fGCjO zCq!nULVGK50~ex;r|0JmGu8CXbPPG0000S4WZ;icML;G_b4?CDJ?a` zFd%(yo_DQt);a$#@0Y_`YzFo{d-i?BFD`b(YxNg*Zqwh!!^6AtQd!{*9v*%dc-=xo z0FDY;RKnoL4fkg+-x7f@eo0XN5yREaw z&h=I~JUkY>mkLkc`lN5qdi%e%n!4OW4nBOCD|m}9=mwF|^IP9O2vH@Qn`tH$u>|)< zW|tvOM{B>GHf%I<%jxh&vBn{YIThc&UN^@l=Hw)gSGT>j-W;DQ)heGdcvl$~|3GBn zG@yAnYB1d$gmx&L`0-0Mbny{t;t_L z;O358TwFYfRZ&pLHIAkgx<+YwgMgrjB{IDC5%LDD6&baFv0>cz@bGX$Ly38RcX&_0 zniDw#gWs=U3JQun_SF;8CkhIk@6si-ct>+y#6{7Cg@^YlR=cka-_Am*YJzixBdO-8 z3{L4jLW|_!Ee+Z{^W|>PT16qjhZVzDSAmnm(fW)t2w2IW$8F;MO0+}D5Or{HFcGn{ zdRSTVXbmLFpx(q$lXn=kMx&^Z8(?LVrsW?x#q zCa5Q=b3ecLKtUYG(S{7V#UPHzu>MXk1WWldHZ^!JgU{hrP4#{c<<CM7LRXw1uL#+CJW5oA?+M^HttDKGW+)b>J!eyp4x_ zzOCf&S=H$YY-bmX&C##U@2rVhjpd@em^8<+x~>iW%eE{3=3Z*0s zh4k_|wFlLhejedf`1lk#Q9wk-`=Fet4pUF@n{b;|^~OzF(K|t~lhev0A5zkub$Sz6 zZ5mgStc`H0?P!r09vlv#TBD)-Rdv&QDCHRvQ@OmnTD1`6tk-lvx#cB|msPIUnN&Lc ze&peo6fZ|fi0~(*ZaK%oMu5lm2x!$r$obImmb^=^XY{K`9J zmOJ%lIvQ>Yp+J$X^tE0J$UC43+NuKsqn&2?E%v{pF0ZcWG9cmo!>$*Xe2Xo9`R>z0 zOOWI7Kpo$UuU*!(1km!Wu2RaLk?+q*0&Hgg@J-KWOm@fK?>l&(=(GMcu<9bJTnIMQ zbeR=+m!7`8a~i|W!I3;UfY@zCUdAAGOV@DqtJvd6MMn9A!RS=7UGTE3E=eGbtZf>5 z(b2=BgKv80&I+@}V73v$mXukp-@d%H;4v(mDG?S zF`H@8F&pMo@G&dv^lZ&_E?@6Ta%zWmqyuZg&)BZ1RQpg>wl?Nx>P;k4@7_-}GIW&v z4NMs_)zDYNR0;^KF+b#`oqCZb`6cz)NYHf!1tnd-8G|9JwIOIkTicWN5;Z~CkPZL7 zCxh)s&8$u=TsR`gx(n zlkX&qR7e4YH|5>Cs&Sa)YFt5^6$~j6gGm(ziiBeUVFY%u4k=1AtpU3)G z(9fUbcqc~VVb0=#8tor0@cePx-YeE&K@WnOPFAH=Gems$}DH4#d$G8)&SWNZUSp=Rpfxnt))c zYLoPl6+xFt*XORRhC`{ZY28~i#yyt8uG;f*dZlVUi+yOk&ZE}PUXIyDJd z39R;H1$@^-&hkc}b7`ybRl5%TmuXuBa-|FZ#s${Nr zQj_f#adnk7t{XcgFTueyU0-}~p=T5w0!xQVZ0_0g4)*h-0<_Oh_IirBqb2f61k%xm-J4R4&T7~HFh=b)DQI06tS+G#g z4CbWlO^2YM!?C3Ln%Sg^APkREL0pVt+2om>`qP-Qa?nLRs*NFn_LRnfd-`eOcQ~Zw zliT8-Ow~nQ`+eaTh&(^Kn5#7jc=`jf{Y7?IfVb1manaZCwVv{%ejFPcTW|mH_s)xX z)JF~Wf}fR868sEYIC$-u7`idY{7tbt;-!o5iNrfBs zGfwV_d^NwbpEE|v4r8)6eefk9YCAb>Z}UQe$YFhIuHs(&UI*LqLul7})3Qh)*Q6j3 z=?5ih!W2fa#uhuMhR~zdl)!TvA(5TNj6TY4;nOY&NmrShACgUA1C2Nn?WtAtWsaQp zp(kc(Y)sUkHnwwq`Gv8uTtL889lw0lUnnB-P0U32ILVcyp@_NJ&&y^!O`sP!O!$wh z%v!hC;hy~8-xg(<`Q&+H`RLD|N5x|K#Kba4x2J#2OnnIni%my)Ihs!&3{hh;<-X$U z;&N09V*O9nAFJo(3wezx2OLc^xJWXV7-3f+QquL#Dp9YH2xon5^`ecOso0P&U$hin z)U!*nghxjYx@{H>K-3mX9nL>>>x{~kM7fj0zo6BVgBRK?gGa@$Uzeti3WAG%8i_8| z+j^9KZX_1kq4aXfOMQ*8-D@hS11}8UnleSOB6&&{NJl@X4hdMpMdJfQ5y>E&3A951 zLHSZm#pYx?(RM;6y=03qO~PKu&VYX2|MWTBiyPLQe)<>d$y#Hm0{d`)tdtIdUwM+ja6PeRx3m|jHBDc`vQrrHxV|EmBxD&T`oQ4y< zZL5F~|J5Y6V=}(l#Qy(O7VkyCm&dA9UueI4p_e3)&Ql~EjCn>B^@qs%(rp^1N`02* z(Vm_ds+krvln^)TwGv`d2CrGot&CtyN*FZm+n@TP{fLQPA~9=Q>{;jUie( zHaDjSU2UJWdAxYGNZ$oQHtgDiL>ybL*adix-f`+W9CR;t!T!}$O%)ANin)NbfprF5 z1QmAUG|>%Cw1lLLt7Cm{@#-9>f3)H2R$32rV-IB!&Ci4-fkzw^tF_~`fj2d-CY~0V-g4EW4 zCqE*}Z#h72;wOZ-NN!PCGUa_^iJM^!2_7Zr86kN^^gwjd;OGb#7zO@Nou`hHzJke2 zFJeEZufM>uli#&vZ43CY%$(UF=&+o3(Z7C|@X>lt#rZDxqpoAi{H+H(OH`>40(h4T z@Ax-Otn!rCMmXB=++^UNI?g0Dv8#)+Q{auy9+X6qd?aXY*QbpU*lms8o{D zukd<~XkycKlhf+Q(-SN^!MT*q{W&9$VKc0;88JNBhL-fq$ZH zfj;NKhH1Wj;xqbt)aF82=yt(23}?3Jk>IC-2O>z8M+2riu9J|?Z{K>GEp!a181}O+ zfeoCmut)I|kTUkJO-FKZR*u$-h&r0LBP~tEvkJAv5l>%oEhj%wy1ylBwm97!kk0-g z#su2^0slI;Lp^I6S7dlN$_`b=6h+Nv-bZ+8jjAi3bl;-Ncn1r&BQX2H&P&b7^=Z&h zGR@kBv+G-m%SqSK+QhWe+Wvrm_ofebBrEG;?XzdkXoW3_#NTo887Nf-?g%_A*k)UC zVW-ZabupDtO|O$^H@j7!U7%jGGZ__4WJHnG2{G^U2+XHRwe}J~v+^8jb#1dKdWM zKWSq2-IJ9|w9;ONwbK)Ip{d353JMC#Bj2()!Tsg_e>g5vD(;mBp7UtP9a}=f9 zt!4V9$Op<578c$sllS;T4h8}FYB2GGO;lW*+(~b()6QHo34?ev00rTIGoO)>k^XI1 zT3Ub2`_Vr?zh9U2J@`E&F@G@j9?T9Nby_G^g7HB#qts^_6aT#?PcK9UFh?WRHX3&+ zDItew8~9Gk>13q^Avn>O$RT3cOAb!Jx9g_$>Ksz-O*#ZqWFW$P1~sPBb&k9yE$PSD zwQ8?z1C0z&B!;YKGU&e@Wb%WcbQ&%%P6uQ!2LxJOHpaN_2cEf}ouAV^_TU5?uwEa@ z`;wIO`Rms%usXWSd?6p^WDah(3`$8!iLQ5MF4ie+HwX5Ex_dBHIQp4HZ*(nG%YmLkt`u!us2w9Mu`?Jy09(=-pBf921^2m!yP6of>s8SMVw|NeQ_I#iR@}V3!i9u2L_g^k#ZItp?Aul z2=5(r4-e5e`3uSS@84TmT2`3;xVAb3TU*xxlO+O7w!hD15aIoA4GojHN%P7I+h448 z&hzRH4!ocQINetVAMo>&Ms>9Z-z3(ncVe1t^jvB_nzNW`aJ{@U>0rIk{wX&vFCjku z2`IjIbq;0+e}2&{y#=s>FM_Xx4(W=bK^W&p$HtbGr+}W2+4#G+ga_8-%wXmA#GCZ zXy{0TtA#3iVhcn`L19Ayt?NfkLz9@4q=fL=-l&1bQ7OvH%Y)%mKeQfXNZCjzRh5dG zdIEyD4=?y9Srtr~MrAbZWe$}Xnk@nJXD$}f=Xhs z7|UzP=pJEa!B}zuvC~q#^BTM>Xb+xEL{3NdQe9pBKd=<7LEW{yY}wx4z9CIQLGj+y zzl;+zRU4I?`>?F#WaESsFd02<7FQ$yAs}fBR5Kob)yz?%prO&7e-II_e0>SGBbOoN z&Msmz{P5w!k7Y&(x1(8a_Z}wiF>gJv6+Ez&nVR=nU*o`)WcqB3l;%vlIY@5}U_ z;5Pe)hs$OA)N^LqY!gJ^Fy(a%bYo)gli3JU(JA^yi#U z4z``HE9FR|2BD#CJ_YyN`SObU|Epu+uzXXi_m1&C7CSq|@t+(_cmif)bt=SWr(|Uz zzv>#VPsqt%{IxK;;-W?IIR7EoxLv8+IjCvd(fm6L3k#W&SF}@Vc;FWa@c*3?{1Z@e zuU@?>nw682%iP^{Y47M*A1kEvo`Z1c>+5^o*F|Q^qJam@sOMp2ZCT2u>B>_{t^xq; z)Qr=)cI}#74RQwV-q+u6zSJGV_}C-7Ak(*Kcxeg{Otarn8P*H*w6{+aXXZI7VcSbu zLl#FB1ExX(fyYtPj;m&9Q*=W9+yDVm+ zltJ1X<8j&qqATrF!kPKlGxAr?3+!T)Kw~Bk?9rS%QWo@8!|W<3Aw9U;BY>#xvPbI$ zSyh&OcR}Tao6)Lf%A`{B8B{ntp_}#mA|6&k3zyqd(Pa7F|({g#?hZhT&=IPU?@JVnd_25oIKYrW=l(-8@9{{7* z)9OwHrZEacz6`!f4|@D>*5xrXsuAoiMci=;FFqxuw*`9Y1Bm+;F>wx{_Q7a3Eo-PZV(b;;{wk@-jC+*by8{w+WurY+(LI;CzJVo$m@!kfvctnesA|I zHK=tv_urZna&vP7_}?Z-f)WNx@w(%fkyTa$4J%3SfO?<krFYHEABl)KMnY5mo=9aNx_8#EZs{q0+-goK2x zxn{%+)=DXczRMy`wi{@bV-Pd_dZ$^)^jnnDvuD?eb<5egxFQJe``{Ii_kVt*GTG?K z11i@hBNKM@FPHn!Qlx`8wx6fG;Xdln*j&wXXD;K zibViqW15eQr)uqAB=Z~1II%r=5air)9J;t@Zcy)}2AGvW+<`?zBr#Lg&v$DE;t@%y(a$Ok^rojZ@%*+VbRPb~m+_y&OZ=(D%sQX>FsQ!+3RKk@MJD5XCGwMqNf z(A~U4D%Qo4s zoXTzJKkEM_*!=gf^gmbjA!nIL86}?>8{em+qst6`F*8=8F9M2y3EaI0!^$9n)28Kx z6joNOPhW9{I}&)_HcMe4pIy^>Qr65`&~2dol!2y0zAH$FaI6d-f%OGN>Dt|;$r{-G z{Xesa`sttu8{GP6*v!n#Z4{Ty+)Hq|{?wg9Zkw;J_W3CZ2|;GGPE1euWBZM(G>4m# z-B$g+h|Dix2GCCPT5lJjasT;4PP!P06OH2Q{pOfH%ObD;>)z1tnG5AmGg=zYD?9|K zx}+$NK@U79lkF_guWmYFY~r%P!F@V>;8gCbD(7YCMh0+C-3+L@>)+i404=ZIym_Om zcJc-2w{V~}?ov}L0YRNA>B@R~xLv$c(KL}KXY8NQ-Qc`2i;w`ui~DE>l<-w1Wfhla zH!SmgmU}7c9MI1|0qMittTJ>V&c|6wR-0=>u%2i-krX-TW4|NJNPa-lK0yr)l0f^ykLLWixVQ@UPJ{(o&xDtH;sj8K%$I*(-1p!8aoZv?E{;P` zkQ}reFaeW*8{if#XZr&Om{}NrOF_uKWn@&8(IyZnLtw#`P6l&zRxz>K5mEtOUdxFR zeVL;fchywkPhj~^P#aE->+Ht9>v>p$6%Z*}A@du6GgDcA}2H9emnbbfmF|_N>NO%rH=!^r7KG zx?cCK;)*vetLsZKC)n;TBhNQfH2j9Wzy#4rd+`EXS{f_VTDfM>=)uJdJ)oF}9x=VE zcUtM9G4Zf(20V}^8gYj~JU%ls){K^lhNc=Y1iN~=o|!7Z*Zhi#co0UnX~%jYuyY4- zSn<$!u`afcBWo9nlurckovj!pNOB!E)D1E;2vp{k`_U>;x7u6m`kHwPTpgH@n{7>2 zj+4FuiyB;)!lR-rE-%gpGi6~{+>jM`k?J^Iw+FbTD&X7~;PZ3f2+=j~DM`aZZc(!T ztg=!87EZs?{HAm3xi~OZ`{<}~hMuT;qY@kwOd{6RSFev8ap}0z+1dFMm_)h1zeC*cW%qm8YV1+5SC-R$f;Wj*e{sUML(q1v zN$Pnh$-?>3e2*ZBPMP6L1%(^UzPO^Q=hv=ZKR(|H1mm?e;MdB;K_E4=v$Mgl({j1@ z3d*$uW%g%gU3;xjV%NqA)u@xCV!xAIi#dgIWm2M!J5!J4BaV0 z7Cx8fM|)T-8w*Qm*d}1uBRTW)S{!-RzW#30TckRum2_ca!`q$0O z`bHW394O$?Eqlnq@*z5!1nkyuApXH~!=pcVV5Xq<=FQ!gFJH=Bo?%xoYGamAG?F^% z6PS|-TXd5EM`Q;G-)O-@N?x8hsw;ThuFJZ556Fo4FJIo8!Pew3aERuL@R!f`VjlV_Ji0Vo^7VspEn11W?4JAueC>OufW!OS8knV5!h;^bc0*>MA7adtX?X$|z4SU|+L z7L%6U!@V~qQ3A_@uzxZB^A*N#9B-UlZk-n+E}C3jbxV!q_@pO6-NJDb@Ai(41ZX;IKcU0#)nqO)FEpC-ko6N_GhY=2fK!}Is3b(O?m=!q>#-p;~Zp-$=t$X zeZEy*C7IuR@KJ_-ZSX8aG1DMupa3flN=*1C;;VMEQv z{(7sTTgQz8=W516Z@Fy4efG@3UEqhu#>zP_0r&2HjzcZENZR>-7|xKsg6M`RPw#WM z7iOjpK#`Qs?r(^|52K<%YY`wVt$~hOD=k(V-WbgjHl}|w%zv*x^%P|SE#|hdI#NZR z-wk3>{eu&;$UgUA>Hv!)DKyqNIv3X(3Z9 zgVV#+!nF~jIf_C&JjGLWhnU&T6F4{U6)RKNuepXKEpC+)T|Ty)OI^BdI+SxWNY6eR zcb!==Ld;4@J}Rqz*GH3tjI3wD#Z)+z{>*-@rQJasM1qKntlXv9Z50aCQBL}C=7yUN zU43NsxSbW4DHsMEuhgDMYri>SBqj7a-1=cxtJ7dCg_Q$JOLN#?!&9m_`rVG)ClTgo zKWX#N>W(<|Fd#ywg5=4E#MXT+7nN5(~s}}E9~xsXh0u6 z2dXsje_D2KXpWj%%PnB!Pj_3us4s7@#4il| z*=A0~LS0qWvNN0l#}oyeZZj}VY(hc_mt-RYd*s_ZBx2xsGrX6I>I!AgOoRUy;il+k literal 0 HcmV?d00001 diff --git a/doc/salome/gui/SMESH/images/remove_node_reconnection_icon.png b/doc/salome/gui/SMESH/images/remove_node_reconnection_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..5b35eab87fa40a52b638ec0defc6a218f18ce4fa GIT binary patch literal 3898 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: both :ref:`standalone groups `, :ref:`groups on filter `, and :ref:`groups on geometry `. If the user chooses a group on geometry or on filter, he is warned and proposed to convert this group to standalone. If the user rejects conversion operation, it is cancelled and a new node/element is not created! -To create any **Quadratic Element** specify the nodes which will form your element by selecting them in the 3D viewer with pressed Shift button and click *Selection* button to the right of **Corner Nodes** label. Their numbers will appear in the dialog box as **Corner Nodes** (alternatively you can just input numbers in this field without selection; note that to use this way the mesh should be selected before invoking this operation). The edges formed by the corner nodes will appear in the table. To define the middle nodes for each edge, double-click on the respective field and input the number of the node (or pick the node in the viewer). For bi-quadratic and tri-quadratic elements, your also need to specify central nodes. As soon as all needed nodes are specified, a preview of a new quadratic element will be displayed in the 3D viewer. Then you will be able to click **Apply** or **Apply and Close** button to add the element to the mesh. +#. To create any **Quadratic Element** specify the nodes which will form your element by selecting them in the 3D viewer with pressed Shift button and click *Selection* button to the right of **Corner Nodes** label. Their numbers will appear in the dialog box as **Corner Nodes** (alternatively you can just input numbers in this field without selection; note that to use this way the mesh should be selected before invoking this operation). The edges formed by the corner nodes will appear in the table. To define the middle nodes for each edge, double-click on the respective field and input the number of the node (or pick the node in the viewer). For bi-quadratic and tri-quadratic elements, your also need to specify central nodes. As soon as all needed nodes are specified, a preview of a new quadratic element will be displayed in the 3D viewer. + +#. Click **Apply** or **Apply and Close** button to add the element to the mesh. .. image:: ../images/aqt.png :align: center diff --git a/doc/salome/gui/SMESH/input/mesh_through_point.rst b/doc/salome/gui/SMESH/input/mesh_through_point.rst index 0065e2478..47bd8c472 100644 --- a/doc/salome/gui/SMESH/input/mesh_through_point.rst +++ b/doc/salome/gui/SMESH/input/mesh_through_point.rst @@ -8,6 +8,7 @@ In mesh you can define a node at a certain point either * by movement of the node closest to the point or * by movement of a selected node to the point. +* by movement of a selected node to the point specified by mouse click. *To displace a node:* @@ -34,6 +35,11 @@ In mesh you can define a node at a certain point either .. centered:: Automatic node selection + .. image:: ../images/meshtopass3.png + :align: center + + .. centered:: + Manual node selection with mouse location #. Specify the way of node selection: manually (the first radio button) or automatically (the second radio button). diff --git a/doc/salome/gui/SMESH/input/modifying_meshes.rst b/doc/salome/gui/SMESH/input/modifying_meshes.rst index 3c9b7d132..60e5f84a0 100644 --- a/doc/salome/gui/SMESH/input/modifying_meshes.rst +++ b/doc/salome/gui/SMESH/input/modifying_meshes.rst @@ -29,6 +29,8 @@ Salome provides a vast specter of mesh modification and transformation operation * :ref:`Unite two triangles `. * :ref:`Unite several adjacent triangles `. * :ref:`Cut a quadrangle ` into two triangles. +* :ref:`Cut triangles ` into two by adding a node on edge. +* :ref:`Cut a face ` into triangles by adding a node on it. * :ref:`Split ` volumic elements into tetrahedra or prisms. * :ref:`Split bi-quadratic ` elements into linear ones without creation of additional nodes. * :ref:`Smooth ` elements, reducung distortions in them by adjusting the locations of nodes. @@ -67,6 +69,8 @@ Salome provides a vast specter of mesh modification and transformation operation changing_orientation_of_elements.rst reorient_faces.rst cutting_quadrangles.rst + add_node_on_segment.rst + add_node_on_face.rst split_to_tetra.rst split_biquad_to_linear.rst smoothing.rst diff --git a/doc/salome/gui/SMESH/input/modules.rst b/doc/salome/gui/SMESH/input/modules.rst index 41915c4f1..6665aa100 100644 --- a/doc/salome/gui/SMESH/input/modules.rst +++ b/doc/salome/gui/SMESH/input/modules.rst @@ -365,6 +365,7 @@ Removing nodes and elements Mesh.RemoveElements Mesh.RemoveNodes + Mesh.RemoveNodeWithReconnection Mesh.RemoveOrphanNodes Modifying nodes and elements @@ -479,6 +480,8 @@ Cutting elements Mesh.SplitQuadsNearTriangularFacets Mesh.SplitHexaToTetras Mesh.SplitHexaToPrisms + Mesh.AddNodeOnSegment + Mesh.AddNodeOnFace Smoothing ========= diff --git a/doc/salome/gui/SMESH/input/removing_nodes_and_elements.rst b/doc/salome/gui/SMESH/input/removing_nodes_and_elements.rst index bfbb16d0c..6d7281cfc 100644 --- a/doc/salome/gui/SMESH/input/removing_nodes_and_elements.rst +++ b/doc/salome/gui/SMESH/input/removing_nodes_and_elements.rst @@ -7,6 +7,7 @@ Removing nodes and elements In MESH you can remove nodes and all types of cells of your mesh. * :ref:`removing_nodes_anchor` +* :ref:`removing_nodes_reconnect_anchor` * :ref:`removing_orphan_nodes_anchor` * :ref:`removing_elements_anchor` * :ref:`clear_mesh_anchor` @@ -33,7 +34,7 @@ Removing nodes In this dialog box you can specify one or several nodes: * choose mesh nodes with the mouse in the 3D Viewer. It is possible to select a whole area with a mouse frame; or - * input the node IDs directly in **ID Elements** field. The selected nodes will be highlighted in the viewer; or + * input the node IDs directly in **Node IDs** field. The selected nodes will be highlighted in the viewer; or * apply Filters. **Set filter** button allows to apply a filter to the selection of nodes. See more about filters in the :ref:`selection_filter_library_page` page. #. Click **Apply** or **Apply and Close** to confirm deletion of the specified nodes. @@ -42,6 +43,38 @@ Removing nodes Be careful while removing nodes because if you remove a definite node of your mesh all adjacent elements will be also deleted. +.. _removing_nodes_reconnect_anchor: + +Removing node with reconnection +############################### + +This operation removes a node and changes surrounding faces in order to cover a hole appearing in the mesh. This operation applies to 2D triangle mesh only. + + .. image:: ../images/remove_node_reconnection.png + :align: center + +**To remove a node:** + +.. |rmnr| image:: ../images/remove_node_reconnection_icon.png + +#. Select your mesh in the Object Browser or in the 3D viewer. +#. From the **Modification** menu choose **Remove** and from the associated submenu select the **Node with reconnection**, or just click *"Remove node with reconnection"* button |rmnr| in the toolbar. + The following dialog box will appear: + + .. image:: ../images/remove_node_reconnection_dlg.png + :align: center + + + In this dialog box you can specify one node to remove: + + * choose a mesh node with the mouse in the 3D Viewer or + * input the node ID directly in **ID** field. The selected node will be highlighted in the viewer. + + Activate **Preview** to see how faces will change. + +#. Click **Apply** or **Apply and Close** to confirm deletion of the specified node. + + .. _removing_orphan_nodes_anchor: Removing orphan nodes diff --git a/doc/salome/gui/SMESH/input/tui_modifying_meshes.rst b/doc/salome/gui/SMESH/input/tui_modifying_meshes.rst index 1509e8d9f..72e541c4d 100644 --- a/doc/salome/gui/SMESH/input/tui_modifying_meshes.rst +++ b/doc/salome/gui/SMESH/input/tui_modifying_meshes.rst @@ -207,6 +207,16 @@ Cutting Quadrangles :download:`Download this script <../../../examples/modifying_meshes_ex20.py>` +.. _tui_cutting_triangles: + +Cutting Triangles +================= + +.. literalinclude:: ../../../examples/modifying_meshes_cut_triangles.py + :language: python + +:download:`Download this script <../../../examples/modifying_meshes_cut_triangles.py>` + .. _modifying_meshes_split_vol: Split Volumes into Tetrahedra diff --git a/idl/SMESH_MeshEditor.idl b/idl/SMESH_MeshEditor.idl index 69f159dc2..18ebe2a36 100644 --- a/idl/SMESH_MeshEditor.idl +++ b/idl/SMESH_MeshEditor.idl @@ -159,6 +159,13 @@ module SMESH */ smIdType RemoveOrphanNodes() raises (SALOME::SALOME_Exception); + /*! + * \brief Remove a mesh node and change surrounding faces to close a hole + * \param nodeID node identifier + * \throw if mesh is not a triangle one + */ + void RemoveNodeWithReconnection(in smIdType nodeID) raises (SALOME::SALOME_Exception); + /*! * \brief Add a new node. * \param x X coordinate of new node @@ -291,18 +298,44 @@ module SMESH raises (SALOME::SALOME_Exception); + /*! + * \brief Change node location + */ boolean MoveNode(in smIdType NodeID, in double x, in double y, in double z) raises (SALOME::SALOME_Exception); + /*! + * \brief Swap a diagonal of a quadrangle formed by two adjacent triangles + */ boolean InverseDiag(in smIdType NodeID1, in smIdType NodeID2) raises (SALOME::SALOME_Exception); - + /*! + * \brief Delete a diagonal of a quadrangle formed by two adjacent triangles + * so that a new quadrangle appears in place of the triangles + */ boolean DeleteDiag(in smIdType NodeID1, in smIdType NodeID2) raises (SALOME::SALOME_Exception); + /*! + * \brief Replace each triangle bound by Node1-Node2 segment with + * two triangles by connecting a node made on the segment with a node opposite + * to the segment. + */ + void AddNodeOnSegment(in smIdType Node1, in smIdType Node2, in double position) + raises (SALOME::SALOME_Exception); + /*! + * \brief Split a face into triangles by adding a new node onto the face + * and connecting the new node with face nodes + */ + void AddNodeOnFace(in smIdType triangle, in double x, in double y, in double z); + /*! + * \brief Change orientation of cells + */ boolean Reorient(in smIdType_array IDsOfElements) raises (SALOME::SALOME_Exception); - + /*! + * \brief Change orientation of cells + */ boolean ReorientObject(in SMESH_IDSource theObject) raises (SALOME::SALOME_Exception); /*! @@ -408,8 +441,8 @@ module SMESH * \return 1 if 1-3 diagonal is better, 2 if 2-4 * diagonal is better, 0 if error occurs. */ - long BestSplit (in long IDOfQuad, - in NumericalFunctor Criterion) raises (SALOME::SALOME_Exception); + short BestSplit (in smIdType IDOfQuad, + in NumericalFunctor Criterion) raises (SALOME::SALOME_Exception); /*! * \brief Split volumic elements into tetrahedrons diff --git a/resources/CMakeLists.txt b/resources/CMakeLists.txt index d1436578a..076d1bdb9 100644 --- a/resources/CMakeLists.txt +++ b/resources/CMakeLists.txt @@ -122,6 +122,9 @@ SET(SMESH_RESOURCES_FILES mesh_minus.png mesh_move_node.png mesh_move_without_node.png + mesh_move_node_interactive.png + mesh_split_diag_interactive.png + mesh_split_face_interactive.png mesh_multi_edges.png mesh_multi_edges_2d.png mesh_node_to_point.png @@ -158,6 +161,7 @@ SET(SMESH_RESOURCES_FILES mesh_rem_element.png mesh_rem_node.png mesh_rem_orphan_nodes.png + mesh_rem_node_recon.png mesh_remove.png mesh_renumbering_elements.png mesh_renumbering_nodes.png diff --git a/resources/mesh_move_node_interactive.png b/resources/mesh_move_node_interactive.png new file mode 100644 index 0000000000000000000000000000000000000000..6e28f28229908db76a92d2e586d5be028bbafc4d GIT binary patch literal 3281 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 literal 0 HcmV?d00001 diff --git a/resources/mesh_rem_node_recon.png b/resources/mesh_rem_node_recon.png new file mode 100644 index 0000000000000000000000000000000000000000..df07f475ef19b591a9ef753a7c483654a750ea93 GIT binary patch literal 3892 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 REbagR002ovPDHLkV1lkWK|}xm literal 0 HcmV?d00001 diff --git a/src/SMDS/SMDS_ElementFactory.cxx b/src/SMDS/SMDS_ElementFactory.cxx index 611511916..dda4337c0 100644 --- a/src/SMDS/SMDS_ElementFactory.cxx +++ b/src/SMDS/SMDS_ElementFactory.cxx @@ -649,6 +649,13 @@ void SMDS_ElementChunk::SetVTKID( const SMDS_MeshElement* e, const vtkIdType vtk } myFactory->mySmdsIDs[ vtkID ] = e->GetID() - 1; } + else + { + if ((size_t) e->GetID() <= myFactory->myVtkIDs.size() ) + myFactory->myVtkIDs[ e->GetID() - 1 ] = vtkID; + if ((size_t) vtkID < myFactory->mySmdsIDs.size() ) + myFactory->mySmdsIDs[ vtkID ] = e->GetID() - 1; + } } //================================================================================ diff --git a/src/SMESH/SMESH_MeshEditor.cxx b/src/SMESH/SMESH_MeshEditor.cxx index 853d59b3e..0ef9f48c7 100644 --- a/src/SMESH/SMESH_MeshEditor.cxx +++ b/src/SMESH/SMESH_MeshEditor.cxx @@ -412,8 +412,8 @@ SMDS_MeshElement* SMESH_MeshEditor::AddElement(const vector & nodeIDs, // Modify a compute state of sub-meshes which become empty //======================================================================= -smIdType SMESH_MeshEditor::Remove (const list< smIdType >& theIDs, - const bool isNodes ) +smIdType SMESH_MeshEditor::Remove (const std::list< smIdType >& theIDs, + const bool isNodes ) { ClearLastCreated(); @@ -474,10 +474,87 @@ smIdType SMESH_MeshEditor::Remove (const list< smIdType >& theIDs, return removed; } +//================================================================================ +/*! + * \brief Remove a node and fill a hole appeared, by changing surrounding faces + */ +//================================================================================ + +void SMESH_MeshEditor::RemoveNodeWithReconnection( const SMDS_MeshNode* node ) +{ + if ( ! node ) + return; + + if ( node->NbInverseElements( SMDSAbs_Volume ) > 0 ) + throw SALOME_Exception( "RemoveNodeWithReconnection() applies to 2D mesh only" ); + + // check that only triangles surround the node + for ( SMDS_ElemIteratorPtr fIt = node->GetInverseElementIterator( SMDSAbs_Face ); fIt->more(); ) + { + const SMDS_MeshElement* face = fIt->next(); + if ( face->GetGeomType() != SMDSGeom_TRIANGLE ) + throw SALOME_Exception( "RemoveNodeWithReconnection() applies to triangle mesh only" ); + if ( face->IsQuadratic() ) + throw SALOME_Exception( "RemoveNodeWithReconnection() applies to linear mesh only" ); + } + + std::vector< const SMDS_MeshNode*> neighbours(2); + SMESH_MeshAlgos::IsOn2DBoundary( node, & neighbours ); + + bool toRemove = ( neighbours.size() > 2 ); // non-manifold ==> just remove + + // if ( neighbours.size() == 2 ) // on boundary + // { + // // check if theNode and neighbours are on a line + // gp_Pnt pN = SMESH_NodeXYZ( node ); + // gp_Pnt p0 = SMESH_NodeXYZ( neighbours[0] ); + // gp_Pnt p1 = SMESH_NodeXYZ( neighbours[1] ); + // double dist01 = p0.Distance( p1 ); + // double tol = 0.01 * dist01; + // double distN = ( gp_Vec( p0, p1 ) ^ gp_Vec( p0, pN )).Magnitude() / dist01; + // bool onLine = distN < tol; + // toRemove = !onLine; + // } + + if ( neighbours.empty() ) // not on boundary + { + TIDSortedElemSet linkedNodes; + GetLinkedNodes( node, linkedNodes, SMDSAbs_Face ); + for ( const SMDS_MeshElement* e : linkedNodes ) neighbours.push_back( cast2Node( e )); + if ( neighbours.empty() ) + toRemove = true; + } + + if ( toRemove ) + { + this->Remove( std::list< smIdType >( 1, node->GetID() ), /*isNode=*/true ); + return; + } + + // choose a node to replace by + const SMDS_MeshNode* nToReplace = nullptr; + SMESH_NodeXYZ nodeXYZ = node; + double minDist = Precision::Infinite(); + for ( const SMDS_MeshNode* n : neighbours ) + { + double dist = nodeXYZ.SquareDistance( n ); + if ( dist < minDist ) + { + minDist = dist; + nToReplace = n; + } + } + + // remove node + replace by nToReplace + std::list< const SMDS_MeshNode* > nodeGroup = { nToReplace, node }; + TListOfListOfNodes nodesToMerge( 1, nodeGroup ); + this->MergeNodes( nodesToMerge ); +} + //================================================================================ /*! * \brief Create 0D elements on all nodes of the given object. - * \param elements - Elements on whose nodes to create 0D elements; if empty, + * \param elements - Elements on whose nodes to create 0D elements; if empty, * the all mesh is treated * \param all0DElems - returns all 0D elements found or created on nodes of \a elements * \param duplicateElements - to add one more 0D element to a node or not @@ -947,24 +1024,24 @@ bool getQuadrangleNodes(const SMDS_MeshNode * theQuadNodes [], { if( tr1->NbNodes() != tr2->NbNodes() ) return false; + // find the 4-th node to insert into tr1 const SMDS_MeshNode* n4 = 0; SMDS_ElemIteratorPtr it = tr2->nodesIterator(); - int i=0; - while ( !n4 && i<3 ) { + for ( int i = 0; !n4 && i < 3; ++i ) + { const SMDS_MeshNode * n = cast2Node( it->next() ); - i++; bool isDiag = ( n == theNode1 || n == theNode2 ); if ( !isDiag ) n4 = n; } + // Make an array of nodes to be in a quadrangle int iNode = 0, iFirstDiag = -1; it = tr1->nodesIterator(); - i=0; - while ( i<3 ) { + for ( int i = 0; i < 3; ++i ) + { const SMDS_MeshNode * n = cast2Node( it->next() ); - i++; bool isDiag = ( n == theNode1 || n == theNode2 ); if ( isDiag ) { if ( iFirstDiag < 0 ) @@ -1079,6 +1156,210 @@ bool SMESH_MeshEditor::DeleteDiag (const SMDS_MeshNode * theNode1, return true; } +//======================================================================= +//function : SplitEdge +//purpose : Replace each triangle bound by theNode1-theNode2 segment with +// two triangles by connecting a node made on the link with a node opposite to the link. +//======================================================================= + +void SMESH_MeshEditor::SplitEdge (const SMDS_MeshNode * theNode1, + const SMDS_MeshNode * theNode2, + double thePosition) +{ + ClearLastCreated(); + + SMESHDS_Mesh * mesh = GetMeshDS(); + + // Get triangles and segments to divide + + std::vector diagNodes = { theNode1, theNode2 }; + std::vector foundElems; + if ( !mesh->GetElementsByNodes( diagNodes, foundElems ) || foundElems.empty() ) + throw SALOME_Exception( SMESH_Comment("No triangle is bound by the edge ") + << theNode1->GetID() << " - " << theNode2->GetID()); + + SMESH_MesherHelper helper( *GetMesh() ); + + for ( const SMDS_MeshElement * elem : foundElems ) + { + SMDSAbs_ElementType type = elem->GetType(); + switch ( type ) { + case SMDSAbs_Volume: + throw SALOME_Exception( "Can't split an edge of a volume"); + break; + + case SMDSAbs_Face: + if ( elem->GetGeomType() != SMDSGeom_TRIANGLE ) + throw SALOME_Exception( "Can't split an edge of a face of type other than triangle"); + if ( elem->IsQuadratic() ) + { + helper.SetIsQuadratic( true ); + helper.AddTLinks( static_cast< const SMDS_MeshFace*>( elem )); + helper.SetIsBiQuadratic( elem->GetEntityType() == SMDSEntity_BiQuad_Triangle ); + } + break; + + case SMDSAbs_Edge: + if ( elem->IsQuadratic() ) + { + helper.SetIsQuadratic( true ); + helper.AddTLinks( static_cast< const SMDS_MeshEdge*>( elem )); + } + break; + default:; + } + } + + // Make a new node + + const SMDS_MeshNode* nodeOnLink = helper.GetMediumNode( theNode1, theNode2,/*force3d=*/false ); + + gp_Pnt newNodeXYZ = ( SMESH_NodeXYZ( theNode1 ) * ( 1 - thePosition ) + + SMESH_NodeXYZ( theNode2 ) * thePosition ); + + const TopoDS_Shape& S = mesh->IndexToShape( nodeOnLink->GetShapeID() ); + if ( !S.IsNull() && S.ShapeType() == TopAbs_FACE ) // find newNodeXYZ by UV on FACE + { + Handle(ShapeAnalysis_Surface) surface = helper.GetSurface( TopoDS::Face( S )); + double tol = 100 * helper.MaxTolerance( S ); + gp_Pnt2d uv = surface->ValueOfUV( newNodeXYZ, tol ); + if ( surface->Gap() < SMESH_NodeXYZ( theNode1 ).Distance( theNode2 )) + { + newNodeXYZ = surface->Value( uv ); + if ( SMDS_FacePositionPtr nPos = nodeOnLink->GetPosition()) + nPos->SetParameters( uv.X(), uv.Y() ); + } + } + if ( !S.IsNull() && S.ShapeType() == TopAbs_EDGE ) // find newNodeXYZ by param on EDGE + { + mesh->MoveNode( nodeOnLink, newNodeXYZ.X(), newNodeXYZ.Y(), newNodeXYZ.Z() ); + double u = Precision::Infinite(), tol = 100 * helper.MaxTolerance( S ), distXYZ[4]; + helper.ToFixNodeParameters( true ); + if ( helper.CheckNodeU( TopoDS::Edge( S ), nodeOnLink, u, tol, /*force3D=*/false, distXYZ )) + newNodeXYZ.SetCoord( distXYZ[1], distXYZ[2], distXYZ[3] ); + } + mesh->MoveNode( nodeOnLink, newNodeXYZ.X(), newNodeXYZ.Y(), newNodeXYZ.Z() ); + + // Split triangles and segments + + std::vector nodes( 7 ); + for ( const SMDS_MeshElement * elem : foundElems ) + { + nodes.assign( elem->begin_nodes(), elem->end_nodes() ); + nodes.resize( elem->NbCornerNodes() + 1 ); + nodes.back() = nodes[0]; + + smIdType id = elem->GetID(); + int shapeID = elem->GetShapeID(); + + const SMDS_MeshNode* centralNode = nullptr; + if ( elem->GetEntityType() == SMDSEntity_BiQuad_Triangle ) + centralNode = elem->GetNode( 6 ); + + mesh->RemoveFreeElement( elem, /*sm=*/0, /*fromGroups=*/false ); + if ( centralNode ) + mesh->RemoveFreeNode( centralNode, /*sm=*/0, /*fromGroups=*/true ); + + for ( size_t i = 1; i < nodes.size(); ++i ) + { + const SMDS_MeshNode* n1 = nodes[i-1]; + const SMDS_MeshNode* n2 = nodes[i]; + const SMDS_MeshElement* newElem; + if ( nodes.size() == 4 ) // triangle + { + bool isDiag1 = ( n1 == theNode1 || n1 == theNode2 ); + bool isDiag2 = ( n2 == theNode1 || n2 == theNode2 ); + if ( isDiag1 && isDiag2 ) + continue; + + newElem = helper.AddFace( n1, n2, nodeOnLink, id ); + } + else // segment + { + newElem = helper.AddEdge( n1, nodeOnLink, id ); + } + myLastCreatedElems.push_back( newElem ); + AddToSameGroups( newElem, elem, mesh ); + if ( shapeID ) + mesh->SetMeshElementOnShape( newElem, shapeID ); + id = 0; + } + } + return; +} + +//======================================================================= +//function : SplitFace +//purpose : Split a face into triangles each formed by two nodes of the +// face and a new node added at the given coordinates. +//======================================================================= + +void SMESH_MeshEditor::SplitFace (const SMDS_MeshElement * theFace, + double theX, + double theY, + double theZ ) +{ + ClearLastCreated(); + + if ( !theFace ) + throw SALOME_Exception("Null face given"); + if ( theFace->GetType() != SMDSAbs_Face ) + throw SALOME_Exception("Not a face given"); + + SMESHDS_Mesh * mesh = GetMeshDS(); + + SMESH_MesherHelper helper( *GetMesh() ); + if ( theFace->IsQuadratic() ) + { + helper.SetIsQuadratic( true ); + helper.AddTLinks( static_cast< const SMDS_MeshFace*>( theFace )); + } + const TopoDS_Shape& shape = mesh->IndexToShape( theFace->GetShapeID() ); + helper.SetSubShape( shape ); + helper.SetElementsOnShape( true ); + + // Make a new node + + const SMDS_MeshNode* centralNode = nullptr; + if ( theFace->GetEntityType() == SMDSEntity_BiQuad_Triangle ) + centralNode = theFace->GetNode( 6 ); + else if ( theFace->GetEntityType() == SMDSEntity_BiQuad_Quadrangle ) + centralNode = theFace->GetNode( 8 ); + + if ( centralNode ) + { + helper.SetIsBiQuadratic( true ); + mesh->MoveNode( centralNode, theX, theY, theZ ); + } + else + centralNode = helper.AddNode( theX, theY, theZ ); + + + // Split theFace + + std::vector nodes( theFace->NbNodes() + 1 ); + nodes.assign( theFace->begin_nodes(), theFace->end_nodes() ); + nodes.resize( theFace->NbCornerNodes() + 1 ); + nodes.back() = nodes[0]; + + smIdType id = theFace->GetID(); + int shapeID = theFace->GetShapeID(); + + mesh->RemoveFreeElement( theFace, /*sm=*/0, /*fromGroups=*/false ); + + for ( size_t i = 1; i < nodes.size(); ++i ) + { + const SMDS_MeshElement* newElem = helper.AddFace( nodes[i-1], nodes[i], centralNode, id ); + + myLastCreatedElems.push_back( newElem ); + AddToSameGroups( newElem, theFace, mesh ); + if ( shapeID ) + mesh->SetMeshElementOnShape( newElem, shapeID ); + id = 0; + } + return; +} + //======================================================================= //function : Reorient //purpose : Reverse theElement orientation diff --git a/src/SMESH/SMESH_MeshEditor.hxx b/src/SMESH/SMESH_MeshEditor.hxx index 6962f2c2d..5bbc914ed 100644 --- a/src/SMESH/SMESH_MeshEditor.hxx +++ b/src/SMESH/SMESH_MeshEditor.hxx @@ -126,6 +126,10 @@ public: */ SMDS_MeshElement* AddElement(const std::vector & nodeIDs, const ElemFeatures& features); + /*! + * \brief Remove a node and fill a hole appeared by changing surrounding faces + */ + void RemoveNodeWithReconnection( const SMDS_MeshNode* node ); smIdType Remove (const std::list< smIdType >& theElemIDs, const bool isNodes); // Remove a node or an element. @@ -155,6 +159,20 @@ public: // with a quadrangle built on the same 4 nodes. // Return false if proper faces not found + void SplitEdge (const SMDS_MeshNode * theNode1, + const SMDS_MeshNode * theNode2, + double thePosition); + // Replace each triangle bound by theNode1-theNode2 link + // with two triangles by connecting a node made on the link with a node opposite to the link. + + void SplitFace (const SMDS_MeshElement * theFace, + double theX, + double theY, + double theZ ); + // Split a face into triangles each formed by two nodes of the face and a new node added + // at the given coordinates. + + bool Reorient (const SMDS_MeshElement * theElement); // Reverse theElement orientation diff --git a/src/SMESHGUI/CMakeLists.txt b/src/SMESHGUI/CMakeLists.txt index 30179b73a..bc4507366 100644 --- a/src/SMESHGUI/CMakeLists.txt +++ b/src/SMESHGUI/CMakeLists.txt @@ -153,6 +153,10 @@ SET(_moc_HEADERS SMESHGUI_HomardAdaptDlg.h SMESHGUI_HomardBoundaryDlg.h SMESHGUI_HomardListGroup.h + SMESHGUI_RemoveNodeReconnectionDlg.h + SMESHGUI_AddNodeOnSegmentDlg.h + SMESHGUI_AddNodeOnFaceDlg.h + SMESHGUI_InteractiveOp.h ) # header files / no moc processing @@ -275,6 +279,10 @@ SET(_other_SOURCES SMESHGUI_HomardAdaptDlg.cxx SMESHGUI_HomardBoundaryDlg.cxx SMESHGUI_HomardListGroup.cxx + SMESHGUI_RemoveNodeReconnectionDlg.cxx + SMESHGUI_AddNodeOnSegmentDlg.cxx + SMESHGUI_AddNodeOnFaceDlg.cxx + SMESHGUI_InteractiveOp.cxx ) # sources / to compile diff --git a/src/SMESHGUI/SMESHGUI.cxx b/src/SMESHGUI/SMESHGUI.cxx index 0c2778ad5..7023bf427 100644 --- a/src/SMESHGUI/SMESHGUI.cxx +++ b/src/SMESHGUI/SMESHGUI.cxx @@ -32,6 +32,8 @@ #include "SMESHGUI.h" #include "SMESHGUI_Add0DElemsOnAllNodesDlg.h" #include "SMESHGUI_AddMeshElementDlg.h" +#include "SMESHGUI_AddNodeOnSegmentDlg.h" +#include "SMESHGUI_AddNodeOnFaceDlg.h" #include "SMESHGUI_AddQuadraticElementDlg.h" #include "SMESHGUI_BuildCompoundDlg.h" #include "SMESHGUI_ClippingDlg.h" @@ -79,6 +81,7 @@ #include "SMESHGUI_Preferences_ScalarBarDlg.h" #include "SMESHGUI_PropertiesDlg.h" #include "SMESHGUI_RemoveElementsDlg.h" +#include "SMESHGUI_RemoveNodeReconnectionDlg.h" #include "SMESHGUI_RemoveNodesDlg.h" #include "SMESHGUI_RenumberingDlg.h" #include "SMESHGUI_ReorientFacesDlg.h" @@ -3549,6 +3552,14 @@ bool SMESHGUI::OnGUIEvent( int theCommandID ) } break; } + case SMESHOp::OpRemoveNodeWithReconn: + { + if(isStudyLocked()) break; + if ( warnOnGeomModif() ) + break; // action forbidden as geometry modified + startOperation( SMESHOp::OpRemoveNodeWithReconn ); + break; + } case SMESHOp::OpRemoveElements: // REMOVES ELEMENTS { if(isStudyLocked()) break; @@ -3807,6 +3818,24 @@ bool SMESHGUI::OnGUIEvent( int theCommandID ) startOperation( SMESHOp::OpMoveNode ); break; + case SMESHOp::OpMoveNodeInteractive: + if ( warnOnGeomModif() ) + break; // action forbidden as geometry modified + startOperation( SMESHOp::OpMoveNodeInteractive ); + break; + + case SMESHOp::OpSplitEdgeInteract: + if ( warnOnGeomModif() ) + break; // action forbidden as geometry modified + startOperation( SMESHOp::OpSplitEdgeInteract ); + break; + + case SMESHOp::OpSplitFaceInteract: + if ( warnOnGeomModif() ) + break; // action forbidden as geometry modified + startOperation( SMESHOp::OpSplitFaceInteract ); + break; + case SMESHOp::OpDuplicateNodes: { if(isStudyLocked()) break; @@ -4214,6 +4243,7 @@ void SMESHGUI::initialize( CAM_Application* app ) createSMESHAction( SMESHOp::OpRemoveNodes, "REMOVE_NODES", "ICON_DLG_REM_NODE" ); createSMESHAction( SMESHOp::OpRemoveElements, "REMOVE_ELEMENTS", "ICON_DLG_REM_ELEMENT" ); createSMESHAction( SMESHOp::OpRemoveOrphanNodes, "REMOVE_ORPHAN_NODES", "ICON_DLG_REM_ORPHAN_NODES" ); + createSMESHAction( SMESHOp::OpRemoveNodeWithReconn, "REMOVE_NODE_RECON", "ICON_REM_NODE_RECON" ); createSMESHAction( SMESHOp::OpClearMesh, "CLEAR_MESH", "ICON_CLEAR_MESH" ); //createSMESHAction( SMESHOp::OpRenumberingNodes, "RENUM_NODES", "ICON_DLG_RENUMBERING_NODES" ); @@ -4228,6 +4258,9 @@ void SMESHGUI::initialize( CAM_Application* app ) createSMESHAction( SMESHOp::OpMergeNodes, "MERGE", "ICON_SMESH_MERGE_NODES" ); createSMESHAction( SMESHOp::OpMergeElements, "MERGE_ELEMENTS", "ICON_DLG_MERGE_ELEMENTS" ); createSMESHAction( SMESHOp::OpMoveNode, "MESH_THROU_POINT","ICON_DLG_MOVE_NODE" ); + createSMESHAction( SMESHOp::OpMoveNodeInteractive, "MOVE_NODE_INTRCT","ICON_DLG_MOVE_NODE_INTERACTIVE" ); + createSMESHAction( SMESHOp::OpSplitEdgeInteract, "SPLIT_DIAG_INTRC","ICON_SPLIT_DIAG_INTERACTIVE" ); + createSMESHAction( SMESHOp::OpSplitFaceInteract, "SPLIT_FACE_INTRC","ICON_SPLIT_FACE_INTERACTIVE" ); createSMESHAction( SMESHOp::OpDuplicateNodes, "DUPLICATE_NODES", "ICON_SMESH_DUPLICATE_NODES" ); createSMESHAction( SMESHOp::OpDiagonalInversion, "INV", "ICON_DLG_MESH_DIAGONAL" ); createSMESHAction( SMESHOp::OpUnionOfTwoTriangle, "UNION2", "ICON_UNION2TRI" ); @@ -4464,14 +4497,18 @@ void SMESHGUI::initialize( CAM_Application* app ) createMenu( SMESHOp::OpBiQuadraticPentahedron, addId, -1 ); createMenu( SMESHOp::OpQuadraticHexahedron, addId, -1 ); createMenu( SMESHOp::OpTriQuadraticHexahedron, addId, -1 ); - - createMenu( SMESHOp::OpRemoveNodes, removeId, -1 ); - createMenu( SMESHOp::OpRemoveElements, removeId, -1 ); - createMenu( SMESHOp::OpRemoveOrphanNodes, removeId, -1 ); - createMenu( separator(), removeId, -1 ); - createMenu( SMESHOp::OpDeleteGroup, removeId, -1 ); - createMenu( separator(), removeId, -1 ); - createMenu( SMESHOp::OpClearMesh, removeId, -1 ); + createMenu( separator(), addId, -1 ); + createMenu( SMESHOp::OpSplitEdgeInteract, addId, -1 ); + createMenu( SMESHOp::OpSplitFaceInteract, addId, -1 ); + + createMenu( SMESHOp::OpRemoveNodes, removeId, -1 ); + createMenu( SMESHOp::OpRemoveElements, removeId, -1 ); + createMenu( SMESHOp::OpRemoveOrphanNodes, removeId, -1 ); + createMenu( SMESHOp::OpRemoveNodeWithReconn, removeId, -1 ); + createMenu( separator(), removeId, -1 ); + createMenu( SMESHOp::OpDeleteGroup, removeId, -1 ); + createMenu( separator(), removeId, -1 ); + createMenu( SMESHOp::OpClearMesh, removeId, -1 ); //createMenu( SMESHOp::OpRenumberingNodes, renumId, -1 ); //createMenu( SMESHOp::OpRenumberingElements, renumId, -1 ); @@ -4655,6 +4692,12 @@ void SMESHGUI::initialize( CAM_Application* app ) createTool( SMESHOp::OpSmoothing, modifyTb ); createTool( SMESHOp::OpPatternMapping, modifyTb ); + int interactTb = createTool( tr( "TB_INTERACT" ), QString( "SMESHInteractiveToolbar" ) ) ; + createTool( SMESHOp::OpMoveNodeInteractive, interactTb ); + createTool( SMESHOp::OpRemoveNodeWithReconn, interactTb ); + createTool( SMESHOp::OpSplitEdgeInteract, interactTb ); + createTool( SMESHOp::OpSplitFaceInteract, interactTb ); + // Adaptation - begin #if !defined(DISABLE_MG_ADAPT) || !defined(DISABLE_HOMARD_ADAPT) int adaptTb = createTool( tr( "TB_ADAPTATION" ), QString( "SMESHAdaptationToolbar" ) ) ; @@ -6022,6 +6065,18 @@ LightApp_Operation* SMESHGUI::createOperation( const int id ) const case SMESHOp::OpMoveNode: // Make mesh pass through point op = new SMESHGUI_MakeNodeAtPointOp(); break; + case SMESHOp::OpMoveNodeInteractive: // Make mesh pass through point / by mouse + op = new SMESHGUI_MakeNodeAtPointOp( 2 ); + break; + case SMESHOp::OpRemoveNodeWithReconn: + op = new SMESHGUI_RemoveNodeReconnectionOp(); + break; + case SMESHOp::OpSplitEdgeInteract: + op = new SMESHGUI_AddNodeOnSegmentOp(); + break; + case SMESHOp::OpSplitFaceInteract: + op = new SMESHGUI_AddNodeOnFaceOp(); + break; case SMESHOp::OpElem0DOnElemNodes: // Create 0D elements on all nodes op = new SMESHGUI_Add0DElemsOnAllNodesOp(); break; diff --git a/src/SMESHGUI/SMESHGUI_AddNodeOnFaceDlg.cxx b/src/SMESHGUI/SMESHGUI_AddNodeOnFaceDlg.cxx new file mode 100644 index 000000000..58f029612 --- /dev/null +++ b/src/SMESHGUI/SMESHGUI_AddNodeOnFaceDlg.cxx @@ -0,0 +1,786 @@ +// Copyright (C) 2007-2021 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, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +// File : SMESHGUI_AddNodeOnFaceDlg.cxx +// Author : Edward AGAPOV, Open CASCADE S.A.S. +// +#include "SMESHGUI_AddNodeOnFaceDlg.h" + +#include "SMESHGUI.h" +#include "SMESHGUI_Filter.h" +#include "SMESHGUI_IdValidator.h" +#include "SMESHGUI_MeshEditPreview.h" +#include "SMESHGUI_MeshUtils.h" +#include "SMESHGUI_SpinBox.h" +#include "SMESHGUI_VTKUtils.h" + +#include +#include +#include +#include +#include + +// SALOME GUI includes +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Qt includes +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// VTK includes +#include +#include +#include +#include +#include + + +// IDL includes +#include +#include CORBA_SERVER_HEADER(SMESH_Mesh) +#include CORBA_SERVER_HEADER(SMESH_MeshEditor) + +#define SPACING 6 +#define MARGIN 11 + +#define TOLERANCE 1e-3 + +//======================================================================= +/*! + * \brief Dialog to publish a sub-shape of the mesh main shape + * by selecting mesh elements + */ +//======================================================================= + +SMESHGUI_AddNodeOnFaceDlg::SMESHGUI_AddNodeOnFaceDlg() + : SMESHGUI_Dialog( 0, false, true ) +{ + setWindowTitle(tr("CAPTION")); + + QVBoxLayout* aDlgLay = new QVBoxLayout (mainFrame()); + aDlgLay->setMargin(0); + aDlgLay->setSpacing(SPACING); + myMainFrame = createMainFrame(mainFrame()); + + aDlgLay->addWidget(myMainFrame); + + aDlgLay->setStretchFactor(myMainFrame, 1); +} + +//======================================================================= +// function : createMainFrame() +// purpose : Create frame containing dialog's input fields +//======================================================================= + +QWidget* SMESHGUI_AddNodeOnFaceDlg::createMainFrame (QWidget* theParent) +{ + QWidget* aFrame = new QWidget(theParent); + + SUIT_ResourceMgr* rm = SMESH::GetResourceMgr( SMESHGUI::GetSMESHGUI() ); + QPixmap iconSelect( rm->loadPixmap("SMESH", tr("ICON_SELECT"))); + + // Face to split + + QGroupBox* faceGrp = new QGroupBox(tr("FACE_GROUP"), aFrame); + faceGrp->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) ); + QLabel* idLabel = new QLabel(tr("FACE_ID"), faceGrp); + myIdBtn = new QPushButton(faceGrp); + myIdBtn->setIcon(iconSelect); + myIdBtn->setCheckable(true); + myId = new QLineEdit(faceGrp); + myId->setValidator(new SMESHGUI_IdValidator(this, 1)); + + QGridLayout* faceGrpLayout = new QGridLayout(faceGrp); + faceGrpLayout->setSpacing(SPACING); + faceGrpLayout->setMargin(MARGIN); + + faceGrpLayout->addWidget( idLabel, 0, 0 ); + faceGrpLayout->addWidget( myIdBtn, 0, 1 ); + faceGrpLayout->addWidget( myId, 0, 2 ); + + // Node location + + QGroupBox* xyzGrp = new QGroupBox(tr("XYZ_GROUP"), aFrame); + xyzGrp->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) ); + + myDestBtn = new QPushButton(xyzGrp); + myDestBtn->setIcon(iconSelect); + myDestBtn->setCheckable(true); + + QLabel* locationXLabel = new QLabel(tr("SMESH_X"), xyzGrp); + myDestinationX = new SMESHGUI_SpinBox(xyzGrp); + QLabel* locationYLabel = new QLabel(tr("SMESH_Y"), xyzGrp); + myDestinationY = new SMESHGUI_SpinBox(xyzGrp); + QLabel* locationZLabel = new QLabel(tr("SMESH_Z"), xyzGrp); + myDestinationZ = new SMESHGUI_SpinBox(xyzGrp); + + myDestinationX->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, "length_precision"); + myDestinationY->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, "length_precision"); + myDestinationZ->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, "length_precision"); + + myPointOnFace = new QCheckBox(tr("XYZ_NODE_ON_FACE"), xyzGrp); + + QGridLayout* aDestLayout = new QGridLayout(xyzGrp); + aDestLayout->setMargin(MARGIN); + aDestLayout->setSpacing(SPACING); + aDestLayout->addWidget(myDestBtn, 0, 0); + aDestLayout->addWidget(locationXLabel, 0, 1); + aDestLayout->addWidget(myDestinationX, 0, 2); + aDestLayout->addWidget(locationYLabel, 0, 3); + aDestLayout->addWidget(myDestinationY, 0, 4); + aDestLayout->addWidget(locationZLabel, 0, 5); + aDestLayout->addWidget(myDestinationZ, 0, 6); + aDestLayout->setColumnStretch(2, 1); + aDestLayout->setColumnStretch(4, 1); + aDestLayout->setColumnStretch(6, 1); + aDestLayout->addWidget(myPointOnFace, 1, 0, 1, 6); + + // Preview + myPreviewChkBox = new QCheckBox( tr("PREVIEW"), aFrame); + myPreviewChkBox->setChecked( true ); + + QVBoxLayout* aLay = new QVBoxLayout(aFrame); + aLay->addWidget(faceGrp); + aLay->addWidget(xyzGrp); + aLay->addWidget(myPreviewChkBox); + + connect(myDestBtn, SIGNAL (toggled(bool)), this, SLOT(ButtonToggled(bool))); + connect(myIdBtn, SIGNAL (toggled(bool)), this, SLOT(ButtonToggled(bool))); + + myIdBtn->setChecked(true); + + return aFrame; +} + +//================================================================================ +/*! + * \brief SLOT called when any button is toggled + * \param bool - on or off + */ +//================================================================================ + +void SMESHGUI_AddNodeOnFaceDlg::ButtonToggled (bool on) +{ + const QObject* aSender = sender(); + if ( on ) { + if ( aSender == myDestBtn ) // button to set coord by node selection + { + if ( myIdBtn->isEnabled() ) + myIdBtn->setChecked( !on ); + } + else if ( aSender == myIdBtn ) // button to select a node to move + { + myDestBtn->setChecked( !on ); + } + } + emit selTypeChanged(); +} + +//================================================================================ +/*! + * \brief Constructor +*/ +//================================================================================ + +SMESHGUI_AddNodeOnFaceOp::SMESHGUI_AddNodeOnFaceOp() : + SMESHGUI_InteractiveOp() +{ + mySimulation = 0; + mySMESHGUI = 0; + myDlg = new SMESHGUI_AddNodeOnFaceDlg; + myHelpFileName = "add_node_on_face.html"; + + myNoPreview = false; + myUpdateDestination = false; + + // connect signals and slots + connect(myDlg->myDestinationX, SIGNAL (valueChanged(double)), this, SLOT(onDestCoordChanged())); + connect(myDlg->myDestinationY, SIGNAL (valueChanged(double)), this, SLOT(onDestCoordChanged())); + connect(myDlg->myDestinationZ, SIGNAL (valueChanged(double)), this, SLOT(onDestCoordChanged())); + connect(myDlg->myId, SIGNAL (textChanged(const QString&)),SLOT(redisplayPreview())); + connect(myDlg->myPreviewChkBox, SIGNAL (toggled(bool)), SLOT(redisplayPreview())); + connect(myDlg, SIGNAL (selTypeChanged() ), SLOT(onSelTypeChange())); + connect(myDlg->myId, SIGNAL (textChanged(const QString&)),SLOT(onTextChange(const QString&))); + connect(myDlg->myPointOnFace, SIGNAL(toggled(bool)), SLOT(pointLocationChanged(bool))); + + myFacePicker = vtkCellPicker::New(); + myFacePicker->SetTolerance(0.005); + myFacePicker->PickFromListOn(); + +} + +//================================================================================ +/*! + * \brief SLOT. Called upon change of selection type + */ +//================================================================================ + +void SMESHGUI_AddNodeOnFaceOp::onSelTypeChange() +{ + if ( myDlg->myIdBtn->isChecked() ) + { + setSelectionMode( FaceSelection ); + } + else if ( myDlg->myDestBtn->isChecked() ) + { + QString msg; + if (isValid(msg)) { + //Disconnect selectionChanged to keep selected element + disconnect(selectionMgr(), SIGNAL(selectionChanged()), this, SLOT(onSelectionDone())); + // Set selection mode to ActorSelection to avoid element's prehighlight during interactive selection + setSelectionMode(ActorSelection); + connect(selectionMgr(), SIGNAL(selectionChanged()), SLOT(onSelectionDone())); + } + } + else + { + setSelectionMode( ActorSelection ); + } +} + +//======================================================================= +// function : startOperation() +// purpose : Init dialog fields, connect signals and slots, show dialog +//======================================================================= + +void SMESHGUI_AddNodeOnFaceOp::startOperation() +{ + myNoPreview = false; + myMeshActor = 0; + + // init simulation with a current View + if ( mySimulation ) delete mySimulation; + mySMESHGUI = getSMESHGUI(); + mySimulation = new SMESHGUI_MeshEditPreview(SMESH::GetViewWindow( mySMESHGUI ) ); + connect(mySMESHGUI, SIGNAL (SignalActivatedViewManager()), this, SLOT(onOpenView())); + connect(mySMESHGUI, SIGNAL (SignalCloseView()), this, SLOT(onCloseView())); + vtkProperty* aProp = vtkProperty::New(); + aProp->SetRepresentationToWireframe(); + aProp->SetColor(250, 0, 250); + aProp->SetPointSize(5); + aProp->SetLineWidth( SMESH::GetFloat("SMESH:element_width",1) + 1); + mySimulation->GetActor()->SetProperty(aProp); + aProp->Delete(); + + SMESHGUI_SelectionOp::startOperation(); + SMESHGUI_InteractiveOp::startOperation(); + myDlg->myId->setText(""); + myUpdateDestination = true; + myDlg->myDestinationX->SetValue(0); + myDlg->myDestinationY->SetValue(0); + myDlg->myDestinationZ->SetValue(0); + myUpdateDestination = false; + + addObserver(); + + myDlg->show(); + + onSelectionDone(); // init myMeshActor +} + +//================================================================================ +/*! + * \brief Stops operation + */ +//================================================================================ + +void SMESHGUI_AddNodeOnFaceOp::stopOperation() +{ + myNoPreview = true; + if ( mySimulation ) + { + mySimulation->SetVisibility(false); + delete mySimulation; + mySimulation = 0; + } + if ( myMeshActor ) { + myMeshActor = 0; + } + // SMESH::SetPointRepresentation( false ); + // SMESH::RepaintCurrentView(); + + disconnect(mySMESHGUI, SIGNAL (SignalActivatedViewManager()), this, SLOT(onOpenView())); + disconnect(mySMESHGUI, SIGNAL (SignalCloseView()), this, SLOT(onCloseView())); + SMESHGUI_SelectionOp::stopOperation(); + removeObserver(); +} + +//================================================================================ +/*! + * \brief perform it's intention action: split a face + */ +//================================================================================ + +bool SMESHGUI_AddNodeOnFaceOp::onApply() +{ + if( SMESHGUI::isStudyLocked() ) + return false; + + if ( !myMeshActor ) { + SUIT_MessageBox::warning( dlg(), tr( "SMESH_WRN_WARNING" ), tr("INVALID_MESH") ); + dlg()->show(); + return false; + } + + QString msg; + if ( !isValid( msg ) ) { // node id is invalid + if( !msg.isEmpty() ) + SUIT_MessageBox::warning( dlg(), tr( "SMESH_WRN_WARNING" ), tr("INVALID_ID") ); + dlg()->show(); + return false; + } + + QStringList aParameters; + aParameters << myDlg->myDestinationX->text(); + aParameters << myDlg->myDestinationY->text(); + aParameters << myDlg->myDestinationZ->text(); + + try { + SMESH::SMESH_Mesh_var aMesh = SMESH::GetMeshByIO(myMeshActor->getIO()); + if (aMesh->_is_nil()) { + SUIT_MessageBox::information(SMESHGUI::desktop(), tr("SMESH_ERROR"), tr("SMESHG_NO_MESH") ); + return true; + } + SMESH::SMESH_MeshEditor_var aMeshEditor = aMesh->GetMeshEditor(); + if (aMeshEditor->_is_nil()) + return true; + + aMesh->SetParameters( aParameters.join(":").toUtf8().constData() ); + + bool ok; + SMESH::smIdType anId = myDlg->myId->text().toLong( &ok ); + + aMeshEditor->AddNodeOnFace( anId, + myDlg->myDestinationX->GetValue(), + myDlg->myDestinationY->GetValue(), + myDlg->myDestinationZ->GetValue() ); + SALOME_ListIO aList; + selectionMgr()->setSelectedObjects(aList,false); + aList.Append(myMeshActor->getIO()); + selectionMgr()->setSelectedObjects(aList,false); + onSelectionDone(); + SMESH::UpdateView(); + SMESHGUI::Modified(); + } + catch (const SALOME::SALOME_Exception& S_ex) { + SalomeApp_Tools::QtCatchCorbaException(S_ex); + } + catch (...) { + } + + return true; +} + +//================================================================================ +/*! + * \brief Check selected face id validity + */ +//================================================================================ + +bool SMESHGUI_AddNodeOnFaceOp::isValid( QString& msg ) +{ + bool ok = false; + if ( myMeshActor ) + { + SMESH::smIdType id = myDlg->myId->text().toLong(); + if ( id > 0 ) + if (SMDS_Mesh* aMesh = myMeshActor->GetObject()->GetMesh()) + if ( const SMDS_MeshElement* face = aMesh->FindElement( id )) + { + if ( face->GetType() == SMDSAbs_Face ) + ok = true; + else + msg += tr("NOT_FACE") + "\n"; + } + if ( !ok ) + msg += tr("INVALID_ID") + "\n"; + } + + ok = myDlg->myDestinationX->isValid( msg, !myNoPreview ) && ok; + ok = myDlg->myDestinationY->isValid( msg, !myNoPreview ) && ok; + ok = myDlg->myDestinationZ->isValid( msg, !myNoPreview ) && ok; + + return ok; +} + +//================================================================================ +/*! + * \brief SLOT called when selection changed + */ +//================================================================================ + +void SMESHGUI_AddNodeOnFaceOp::onSelectionDone() +{ + if ( !myDlg->isVisible() || !myDlg->isEnabled() ) + return; + + myNoPreview = true; + QString idStr; + try { + SALOME_ListIO aList; + selectionMgr()->selectedObjects(aList, SVTK_Viewer::Type()); + if (aList.Extent() != 1) + return; + Handle(SALOME_InteractiveObject) anIO = aList.First(); + myMeshActor = SMESH::FindActorByEntry(anIO->getEntry()); + myFacePicker->InitializePickList(); + myFacePicker->AddPickList(myMeshActor); + + QString aString; + int nbElems = SMESH::GetNameOfSelectedElements(selector(),anIO, aString); + if (nbElems == 1) + if ( SMDS_Mesh* aMesh = myMeshActor->GetObject()->GetMesh()) + if ( const SMDS_MeshElement* face = aMesh->FindElement( aString.toLong() )) + { + idStr = aString; + // set coordinates to face gravity center + gp_XYZ faceGC( 0,0,0 ); + for ( int i = 0; i < face->NbCornerNodes(); ++i ) + faceGC += SMESH_NodeXYZ( face->GetNode( i )); + faceGC /= face->NbCornerNodes(); + myUpdateDestination = true; + myDlg->myDestinationX->SetValue(faceGC.X()); + myDlg->myDestinationY->SetValue(faceGC.Y()); + myDlg->myDestinationZ->SetValue(faceGC.Z()); + myUpdateDestination = false; + } + } catch (...) { + } + myDlg->myId->setText( idStr ); + + myNoPreview = false; + redisplayPreview(); +} + +//================================================================================ +/*! + * \brief update preview + */ +//================================================================================ + +void SMESHGUI_AddNodeOnFaceOp::redisplayPreview() +{ + if ( myNoPreview ) + return; + myNoPreview = true; + + SMESH::MeshPreviewStruct_var aMeshPreviewStruct; + + if ( myMeshActor && myDlg->myPreviewChkBox->isChecked() ) + { + QString msg; + if ( isValid( msg )) + { + try { + SMESH::SMESH_Mesh_var aMesh = SMESH::GetMeshByIO(myMeshActor->getIO()); + if (!aMesh->_is_nil()) { + SMESH::SMESH_MeshEditor_var aPreviewer = aMesh->GetMeshEditPreviewer(); + if (!aPreviewer->_is_nil()) + { + SUIT_OverrideCursor aWaitCursor; + + SMESH::smIdType anId = myDlg->myId->text().toLong(); + aPreviewer->AddNodeOnFace(anId, + myDlg->myDestinationX->GetValue(), + myDlg->myDestinationY->GetValue(), + myDlg->myDestinationZ->GetValue()); + aMeshPreviewStruct = aPreviewer->GetPreviewData(); + } + } + } + catch (...) { + } + } + } + if (!mySimulation) + mySimulation = new SMESHGUI_MeshEditPreview(SMESH::GetViewWindow( mySMESHGUI )); + // display data + if ( & aMeshPreviewStruct.in() ) + { + mySimulation->SetData( aMeshPreviewStruct.in() ); + } + else + { + mySimulation->SetVisibility(false); + } + + myNoPreview = false; +} + +//================================================================================= +/*! + * \brief SLOT called when the viewer opened + */ +//================================================================================= + +void SMESHGUI_AddNodeOnFaceOp::onOpenView() +{ + if ( mySimulation ) { + mySimulation->SetVisibility(false); + SMESH::SetPointRepresentation(false); + } + else { + mySimulation = new SMESHGUI_MeshEditPreview(SMESH::GetViewWindow( mySMESHGUI )); + } +} + +//================================================================================= +/*! + * \brief SLOT called when the viewer closed + */ +//================================================================================= + +void SMESHGUI_AddNodeOnFaceOp::onCloseView() +{ + delete mySimulation; + mySimulation = 0; +} + +//================================================================================ +/*! + * \brief SLOT called when the face id is manually changed + */ +//================================================================================ + +void SMESHGUI_AddNodeOnFaceOp::onTextChange( const QString& theText ) +{ + if( myMeshActor ) + { + if( SMDS_Mesh* aMesh = myMeshActor->GetObject()->GetMesh() ) + { + Handle(SALOME_InteractiveObject) anIO = myMeshActor->getIO(); + SALOME_ListIO aList; + aList.Append( anIO ); + selectionMgr()->setSelectedObjects( aList, false ); + + if( const SMDS_MeshElement* face = aMesh->FindElement( theText.toLong() ) ) + { + SVTK_TVtkIDsMap aListInd; + aListInd.Add( FromSmIdType( face->GetID()) ); + selector()->AddOrRemoveIndex( anIO, aListInd, false ); + if( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( SMESHGUI::GetSMESHGUI() ) ) + aViewWindow->highlight( anIO, true, true ); + } + } + } +} + +//================================================================================ +/*! + * \brief Activate selection + */ +//================================================================================ + +void SMESHGUI_AddNodeOnFaceOp::activateSelection() +{ + selectionMgr()->clearFilters(); + SMESH::SetPointRepresentation( false ); + onSelTypeChange(); +} + +//================================================================================ +/*! + * \brief Destructor +*/ +//================================================================================ + +SMESHGUI_AddNodeOnFaceOp::~SMESHGUI_AddNodeOnFaceOp() +{ + if ( myDlg ) delete myDlg; + if ( mySimulation ) delete mySimulation; + myFacePicker->Delete(); +} + +//================================================================================ +/*! + * \brief SLOT called when destination coordinates are changed +*/ +//================================================================================ +void SMESHGUI_AddNodeOnFaceOp::onDestCoordChanged() +{ + if (myUpdateDestination) + return; + pointLocationChanged(myDlg->myPointOnFace->isChecked()); + redisplayPreview(); +} + +//================================================================================ +/*! + * \brief SLOT called when 'Node on face' checkbox is changed +*/ +//================================================================================ +void SMESHGUI_AddNodeOnFaceOp::pointLocationChanged(bool onFace) { + if (onFace) { + QString msg; + if (myMeshActor && isValid(msg)) { + SMESH::smIdType id = myDlg->myId->text().toLong(); + if (id > 0) { + if (SMDS_Mesh* aMesh = myMeshActor->GetObject()->GetMesh()) { + if (const SMDS_MeshElement* face = aMesh->FindElement(id)) + { + if (face->GetType() == SMDSAbs_Face) { + gp_Pnt point(myDlg->myDestinationX->GetValue(), myDlg->myDestinationY->GetValue(),myDlg->myDestinationZ->GetValue()); + gp_XYZ closestPnt; + double dist = SMESH_MeshAlgos::GetDistance( face, point, &closestPnt); + if (dist > TOLERANCE) { + myUpdateDestination = true; + myDlg->myDestinationX->SetValue(closestPnt.X()); + myDlg->myDestinationY->SetValue(closestPnt.Y()); + myDlg->myDestinationZ->SetValue(closestPnt.Z()); + myUpdateDestination = false; + redisplayPreview(); + } + } + } + } + } + } + } +} + +//================================================================================ +/*! + * \brief Gets dialog of this operation + * \retval LightApp_Dialog* - pointer to dialog of this operation + */ +//================================================================================ + +LightApp_Dialog* SMESHGUI_AddNodeOnFaceOp::dlg() const +{ + return myDlg; +} + +//================================================================================ +/* +* \brief Process InteractiveSelectionChanged event +*/ +//================================================================================ +void SMESHGUI_AddNodeOnFaceOp::processStyleEvents(unsigned long theEvent, void* theCallData) +{ + (void*)theCallData; + QString msg; + if (isValid(msg)) { + if (theEvent == SVTK::InteractiveSelectionChanged) { + if (myDlg->myPointOnFace->isChecked()) { + // Pick point on a mesh surface + QString msg; + if (myMeshActor && isValid(msg)) { + SMESH::smIdType id = myDlg->myId->text().toLong(); + if (id > 0) { + if (SMDS_Mesh* aMesh = myMeshActor->GetObject()->GetMesh()) { + if (const SMDS_MeshElement* face = aMesh->FindElement(id)) + { + if (face->GetType() == SMDSAbs_Face) { + int xClick, yClick; // Last event (move or left button bown) position + myRWInteractor->GetDevice()->GetEventPosition(xClick, yClick); + gp_XYZ faceNode(0, 0, 0); + SMDS_Mesh tmp; + double Ni[3]; + std::vector tmpNodes; + for (int i = 0; i < face->NbCornerNodes(); ++i) { + faceNode = SMESH_NodeXYZ(face->GetNode(i)); + vtkInteractorObserver::ComputeWorldToDisplay(myRWInteractor->GetRenderer()->GetDevice(), + faceNode.X(), faceNode.Y(), faceNode.Z(), Ni); + tmpNodes.push_back(tmp.AddNode(Ni[0], Ni[1], 0)); + } + SMDS_MeshFace* face2D = tmp.AddPolygonalFace(tmpNodes); + gp_Pnt point(double(xClick), double(yClick), 0); + gp_XYZ closestPnt; + double dist = SMESH_MeshAlgos::GetDistance(face2D, point, &closestPnt); + double xPick = 0, yPick = 0; + if (dist < TOLERANCE) { + xPick = xClick; + yPick = yClick; + } + else { + xPick = closestPnt.X(); + yPick = closestPnt.Y(); + } + myFacePicker->Pick(xPick, yPick, 0.0, myRWInteractor->GetRenderer()->GetDevice()); + double closest[3]; + myFacePicker->GetPickPosition(closest); + myUpdateDestination = true; + myDlg->myDestinationX->SetValue(closest[0]); + myDlg->myDestinationY->SetValue(closest[1]); + myDlg->myDestinationZ->SetValue(closest[2]); + myUpdateDestination = false; + redisplayPreview(); + } + } + } + } + } + } + else { + double* aCoord = (double*)theCallData; + myUpdateDestination = true; + myDlg->myDestinationX->SetValue(aCoord[0]); + myDlg->myDestinationY->SetValue(aCoord[1]); + myDlg->myDestinationZ->SetValue(aCoord[2]); + myUpdateDestination = false; + redisplayPreview(); + } + } + } +} + +//================================================================================ +/* +* \brief Process LeftButtonPressEvent event: activate interactive selection +*/ +//================================================================================ +void SMESHGUI_AddNodeOnFaceOp::processInteractorEvents(unsigned long theEvent, void* theCallData) +{ + (void*)theCallData; + if (theEvent == vtkCommand::LeftButtonPressEvent && myDlg->myDestBtn->isChecked()) { + bool control = myRWInteractor->GetDevice()->GetControlKey(); + bool shift = myRWInteractor->GetDevice()->GetControlKey(); + SVTK_ViewWindow* svtkViewWindow = SMESH::GetViewWindow(mySMESHGUI); + if (svtkViewWindow && !shift && !control) { + QString msg; + if (isValid(msg)) { + svtkViewWindow->activateInteractiveSelection(); + } + } + } +} diff --git a/src/SMESHGUI/SMESHGUI_AddNodeOnFaceDlg.h b/src/SMESHGUI/SMESHGUI_AddNodeOnFaceDlg.h new file mode 100644 index 000000000..b7c5a1e83 --- /dev/null +++ b/src/SMESHGUI/SMESHGUI_AddNodeOnFaceDlg.h @@ -0,0 +1,140 @@ +// Copyright (C) 2007-2021 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, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +// File : SMESHGUI_AddNodeOnFaceDlg.h +// Author : Edward AGAPOV, Open CASCADE S.A.S. +// +#ifndef SMESHGUI_AddNodeOnFaceDLG_H +#define SMESHGUI_AddNodeOnFaceDLG_H + +// SMESH includes +#include "SMESH_SMESHGUI.hxx" + +#include "SMESHGUI_Dialog.h" +#include "SMESHGUI_InteractiveOp.h" + +class QButtonGroup; +class QCheckBox; +class QGroupBox; +class QLineEdit; +class QPushButton; +class QRadioButton; +class SMESHGUI_SpinBox; +class SMESHGUI_MeshEditPreview; +class SMESHGUI_AddNodeOnFaceDlg; +class vtkCellPicker; + +/*! + * \brief Operation to split a face into triangles by creating a new node + * on the face and connecting it to the face nodes + */ +class SMESHGUI_EXPORT SMESHGUI_AddNodeOnFaceOp: public SMESHGUI_InteractiveOp +{ + Q_OBJECT + +public: + SMESHGUI_AddNodeOnFaceOp(); + virtual ~SMESHGUI_AddNodeOnFaceOp(); + + virtual LightApp_Dialog* dlg() const; + +protected: + + virtual void startOperation() override; + virtual void stopOperation() override; + + virtual void activateSelection() override; + + bool isValid( QString& ); + + virtual void processStyleEvents(unsigned long event, + void* calldata) override; + + virtual void processInteractorEvents(unsigned long event, + void* calldata) override; + + +protected slots: + virtual bool onApply(); + +private slots: + void onSelectionDone(); + void redisplayPreview(); + void onSelTypeChange(); + void onTextChange( const QString& ); +// void onDestCoordChanged(); + void onOpenView(); + void onCloseView(); + void pointLocationChanged(bool); + void onDestCoordChanged(); + +private: + SMESHGUI_AddNodeOnFaceDlg* myDlg; + + SUIT_SelectionFilter* myFilter; + SMESHGUI* mySMESHGUI; + SMESHGUI_MeshEditPreview* mySimulation; + SMESH_Actor* myMeshActor; + bool myNoPreview; + bool myUpdateDestination; + bool myDestCoordChanged; + vtkCellPicker* myFacePicker; +}; + +/*! + * \brief Dialog to split a face into triangles by creating a new node + * on the face and connecting it to the face nodes + */ + +class SMESHGUI_EXPORT SMESHGUI_AddNodeOnFaceDlg : public SMESHGUI_Dialog +{ + Q_OBJECT + +public: + SMESHGUI_AddNodeOnFaceDlg(); + +private: + QWidget* createMainFrame( QWidget* ); + + QWidget* myMainFrame; + + QPushButton* myDestBtn; + QPushButton* myIdBtn; + QLineEdit* myId; + SMESHGUI_SpinBox* myDestinationX; + SMESHGUI_SpinBox* myDestinationY; + SMESHGUI_SpinBox* myDestinationZ; + QCheckBox* myPointOnFace; + QCheckBox* myPreviewChkBox; + + QString myHelpFileName; + + friend class SMESHGUI_AddNodeOnFaceOp; + +signals: + void selTypeChanged(); + + private slots: + void ButtonToggled( bool ); +}; + +#endif // SMESHGUI_AddNodeOnFaceDLG_H diff --git a/src/SMESHGUI/SMESHGUI_AddNodeOnSegmentDlg.cxx b/src/SMESHGUI/SMESHGUI_AddNodeOnSegmentDlg.cxx new file mode 100644 index 000000000..d400b45c7 --- /dev/null +++ b/src/SMESHGUI/SMESHGUI_AddNodeOnSegmentDlg.cxx @@ -0,0 +1,701 @@ +// Copyright (C) 2007-2021 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, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +// File : SMESHGUI_AddNodeOnSegmentDlg.cxx +// Author : Edward AGAPOV, Open CASCADE S.A.S. +// +#include "SMESHGUI_AddNodeOnSegmentDlg.h" + +#include "SMESHGUI.h" +#include "SMESHGUI_MeshUtils.h" +#include "SMESHGUI_VTKUtils.h" +#include "SMESHGUI_SpinBox.h" +#include "SMESHGUI_MeshEditPreview.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Qt includes +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// VTK includes +#include +#include +#include +#include +#include + +// IDL includes +#include +#include CORBA_SERVER_HEADER(SMESH_Mesh) +#include CORBA_SERVER_HEADER(SMESH_MeshEditor) + +#define SPACING 6 +#define MARGIN 11 + +#define SPIN_TOLERANCE 1e-3 + +//======================================================================= +/*! + * \brief Dialog to split a diagonal of a quadrangle formed by two adjacent triangles + */ +//======================================================================= + +SMESHGUI_AddNodeOnSegmentDlg::SMESHGUI_AddNodeOnSegmentDlg() +: SMESHGUI_Dialog( 0, false, true ) +{ + setWindowTitle(tr("CAPTION")); + + QVBoxLayout* aDlgLay = new QVBoxLayout (mainFrame()); + aDlgLay->setMargin(0); + aDlgLay->setSpacing(SPACING); + QWidget* mainFr = createMainFrame(mainFrame()); + + aDlgLay->addWidget( mainFr ); + + aDlgLay->setStretchFactor( mainFr, 1); +} + +//======================================================================= +// function : createMainFrame() +// purpose : Create frame containing dialog's input fields +//======================================================================= + +QWidget* SMESHGUI_AddNodeOnSegmentDlg::createMainFrame (QWidget* theParent) +{ + QWidget* aFrame = new QWidget(theParent); + + SUIT_ResourceMgr* rm = SMESH::GetResourceMgr( SMESHGUI::GetSMESHGUI() ); + QPixmap iconSelect( rm->loadPixmap("SMESH", tr("ICON_SELECT"))); + + // Segment + + QGroupBox* segmentGrp = new QGroupBox(tr("SEGMENT_GROUP"), aFrame); + segmentGrp->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) ); + QLabel* segmentLabel = new QLabel(tr("SEGMENT"), segmentGrp); + mySegmentBtn = new QPushButton(segmentGrp); + mySegmentBtn->setIcon(iconSelect); + mySegmentBtn->setCheckable(true); + mySegment = new QLineEdit(segmentGrp); + mySegment->setValidator(new QRegExpValidator(QRegExp("[\\d]*-[\\d]*"), this)); + + QGridLayout* segmentGrpLayout = new QGridLayout(segmentGrp); + segmentGrpLayout->setSpacing(SPACING); + segmentGrpLayout->setMargin(MARGIN); + + segmentGrpLayout->addWidget( segmentLabel, 0, 0 ); + segmentGrpLayout->addWidget( mySegmentBtn, 0, 1 ); + segmentGrpLayout->addWidget( mySegment, 0, 2 ); + + // Position on segment + + QGroupBox* positionGrp = new QGroupBox(tr("POSITION_GROUP"), aFrame); + positionGrp->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) ); + + myPositionBtn = new QPushButton(positionGrp); + myPositionBtn->setIcon(iconSelect); + myPositionBtn->setCheckable(true); + + QLabel* positionLbl = new QLabel(tr("POSITION"), positionGrp); + + myPositionSpin = new SMESHGUI_SpinBox(positionGrp); + myPositionSpin->setReadOnly(false); + myPositionSpin->RangeStepAndValidator(SPIN_TOLERANCE, 1- SPIN_TOLERANCE, 0.1, "length_precision"); + + QGridLayout* positionLayout = new QGridLayout(positionGrp); + positionLayout->setMargin(MARGIN); + positionLayout->setSpacing(SPACING); + positionLayout->addWidget(positionLbl, 0, 0); + positionLayout->addWidget(myPositionBtn, 0, 1); + positionLayout->addWidget(myPositionSpin, 0, 2); + positionLayout->setColumnStretch(2, 1); + + // Preview + + myPreviewChkBox = new QCheckBox( tr("PREVIEW"), aFrame); + myPreviewChkBox->setChecked( true ); + + QVBoxLayout* aLay = new QVBoxLayout(aFrame); + aLay->addWidget(segmentGrp); + aLay->addWidget(positionGrp); + aLay->addWidget(myPreviewChkBox); + + connect(myPositionBtn, SIGNAL (toggled(bool)), this, SLOT(ButtonToggled(bool))); + connect(mySegmentBtn, SIGNAL (toggled(bool)), this, SLOT(ButtonToggled(bool))); + + mySegmentBtn->setChecked(true); + + return aFrame; +} + +//================================================================================ +/*! + * \brief SLOT called when any button is toggled + * \param bool - on or off + */ +//================================================================================ + +void SMESHGUI_AddNodeOnSegmentDlg::ButtonToggled (bool on) +{ + const QObject* aSender = sender(); + if ( on ) { + if ( aSender == myPositionBtn ) + { + mySegmentBtn->setChecked( !on ); + } + else if ( aSender == mySegmentBtn ) + { + myPositionBtn->setChecked( !on ); + } + } + emit selTypeChanged(); +} + +//================================================================================ +/*! + * \brief Constructor + */ +//================================================================================ + +SMESHGUI_AddNodeOnSegmentOp::SMESHGUI_AddNodeOnSegmentOp() : + SMESHGUI_InteractiveOp() +{ + mySimulation = 0; + mySMESHGUI = 0; + myDlg = new SMESHGUI_AddNodeOnSegmentDlg; + myHelpFileName = "add_node_on_segment.html"; + + myNoPreview = false; + + // connect signals and slots + connect(myDlg->myPreviewChkBox, SIGNAL (toggled(bool)), SLOT(redisplayPreview())); + connect(myDlg->myPositionSpin, SIGNAL (valueChanged(double)), SLOT(redisplayPreview())); + connect(myDlg->myPositionSpin, SIGNAL (textChanged(const QString&)),SLOT(redisplayPreview())); + connect(myDlg, SIGNAL (selTypeChanged() ), SLOT(onSelTypeChange())); + connect(myDlg->mySegment, SIGNAL (textChanged(const QString&)),SLOT(onTextChange(const QString&))); +} + +//================================================================================ +/*! + * \brief SLOT. Called upon change of selection type + */ +//================================================================================ + +void SMESHGUI_AddNodeOnSegmentOp::onSelTypeChange() +{ + if ( myDlg->mySegmentBtn->isChecked() ) + { + setSelectionMode( EdgeOfCellSelection ); + } + else if ( myDlg->myPositionBtn->isChecked() ) + { + if (SVTK_ViewWindow* svtkViewWindow = SMESH::GetViewWindow(mySMESHGUI)) { + QString msg; + SMESH::smIdType node1 = 0, node2 = 0; + if (isValid(msg, node1, node2)) { + //Disconnect selectionChanged to keep selected element + disconnect(selectionMgr(), SIGNAL(selectionChanged()), this, SLOT(onSelectionDone())); + // Set selection mode to ActorSelection to avoid element's prehighlight during interactive selection + setSelectionMode(ActorSelection); + connect(selectionMgr(), SIGNAL(selectionChanged()), SLOT(onSelectionDone())); + } + } + } + else + { + setSelectionMode( ActorSelection ); + } +} + +//======================================================================= +// function : startOperation() +// purpose : Init dialog fields, connect signals and slots, show dialog +//======================================================================= + +void SMESHGUI_AddNodeOnSegmentOp::startOperation() +{ + myNoPreview = false; + myMeshActor = 0; + + // init simulation with a current View + if ( mySimulation ) delete mySimulation; + mySMESHGUI = getSMESHGUI(); + mySimulation = new SMESHGUI_MeshEditPreview(SMESH::GetViewWindow( mySMESHGUI ) ); + connect(mySMESHGUI, SIGNAL (SignalActivatedViewManager()), this, SLOT(onOpenView())); + connect(mySMESHGUI, SIGNAL (SignalCloseView()), this, SLOT(onCloseView())); + vtkProperty* aProp = vtkProperty::New(); + aProp->SetRepresentationToWireframe(); + aProp->SetColor(250, 0, 250); + aProp->SetPointSize(5); + aProp->SetLineWidth( SMESH::GetFloat("SMESH:element_width",1) + 1); + mySimulation->GetActor()->SetProperty(aProp); + aProp->Delete(); + + SMESHGUI_SelectionOp::startOperation(); // this method should be called only after filter creation + SMESHGUI_InteractiveOp::startOperation(); + myDlg->mySegment->setText(""); + myDlg->myPositionSpin->SetValue(0.5); + myDlg->myPositionSpin->setReadOnly(false); + + addObserver(); + + myDlg->show(); + + onSelectionDone(); // init myMeshActor +} + +//================================================================================ +/*! + * \brief Stops operation + */ +//================================================================================ + +void SMESHGUI_AddNodeOnSegmentOp::stopOperation() +{ + myNoPreview = true; + if ( mySimulation ) + { + mySimulation->SetVisibility(false); + delete mySimulation; + mySimulation = 0; + } + if ( myMeshActor ) { + myMeshActor = 0; + } + SMESH::SetPointRepresentation( false ); + SMESH::RepaintCurrentView(); + + disconnect(mySMESHGUI, SIGNAL (SignalActivatedViewManager()), this, SLOT(onOpenView())); + disconnect(mySMESHGUI, SIGNAL (SignalCloseView()), this, SLOT(onCloseView())); + //selectionMgr()->removeFilter( myFilter ); + SMESHGUI_SelectionOp::stopOperation(); + removeObserver(); +} + +//================================================================================ +/*! + * \brief perform it's intention action: create a node on a segment + */ +//================================================================================ + +bool SMESHGUI_AddNodeOnSegmentOp::onApply() +{ + if( SMESHGUI::isStudyLocked() ) + return false; + + QString msg; + SMESH::smIdType node1= 0, node2 = 0; + if ( !isValid( msg, node1, node2 )) + { + SUIT_MessageBox::warning( dlg(), tr( "SMESH_WRN_WARNING" ), + msg.isEmpty() ? tr("INVALID_ID") : msg ); + dlg()->show(); + return false; + } + + QStringList aParameters; + aParameters << myDlg->myPositionSpin->text(); + + try { + SMESH::SMESH_Mesh_var aMesh = SMESH::GetMeshByIO( myMeshActor->getIO() ); + if (aMesh->_is_nil()) { + SUIT_MessageBox::information(SMESHGUI::desktop(), tr("SMESH_ERROR"), tr("INVALID_MESH") ); + return true; + } + SMESH::SMESH_MeshEditor_var aMeshEditor = aMesh->GetMeshEditor(); + if (aMeshEditor->_is_nil()) + return true; + + aMesh->SetParameters( aParameters.join(":").toUtf8().constData() ); + + aMeshEditor->AddNodeOnSegment( node1, node2, myDlg->myPositionSpin->GetValue() ); + + selector()->ClearIndex(); + selector()->ClearCompositeIndex(); + SALOME_ListIO aList; + aList.Append( myMeshActor->getIO() ); + selectionMgr()->setSelectedObjects(aList,false); + onSelectionDone(); + SMESH::UpdateView(); + SMESHGUI::Modified(); + } + catch (const SALOME::SALOME_Exception& S_ex) { + SalomeApp_Tools::QtCatchCorbaException(S_ex); + } + catch (...) { + } + + return true; +} + +//================================================================================ +/*! + * \brief Check selected node id validity + */ +//================================================================================ + +bool SMESHGUI_AddNodeOnSegmentOp::isValid( QString& msg, + SMESH::smIdType & node1, + SMESH::smIdType & node2 ) +{ + bool ok = false; + if ( !myMeshActor ) + { + msg = tr("INVALID_MESH"); + } + else + { + if ( SMDS_Mesh* mesh = myMeshActor->GetObject()->GetMesh() ) + { + QString txt = myDlg->mySegment->text(); + if ( txt.contains('-')) + { + QString str1 = txt.section('-', 0, 0, QString::SectionSkipEmpty); + QString str2 = txt.section('-', 1, 1, QString::SectionSkipEmpty); + node1 = str1.toLong(); + node2 = str2.toLong(); + const SMDS_MeshNode* n1 = mesh->FindNode( node1 ); + const SMDS_MeshNode* n2 = mesh->FindNode( node2 ); + std::vector nodes = { n1, n2 }; + std::vector foundElems; + if ( !mesh->GetElementsByNodes( nodes, foundElems )) + msg = tr("NO_ELEMENTS"); + else + { + for ( const SMDS_MeshElement * elem : foundElems ) + { + if ( elem->GetGeomType() == SMDSGeom_TRIANGLE ) + ok = true; + else + { + if ( elem->GetType() == SMDSAbs_Volume ) + msg = tr("VOLUME_FOUND"); + if ( elem->GetType() == SMDSAbs_Face ) + msg = tr("NOT_TRIANGLE_FACE_FOUND"); + } + } + if ( !msg.isEmpty() ) + ok = false; + } + } + } + } + if ( !ok && msg.isEmpty() ) + { + node1 = node2 = 0; + msg += tr("INVALID_EDGE") + "\n"; + } + + if ( ok && ! myDlg->myPositionSpin->isValid( msg, /*toCorrect=*/false )) + { + msg = tr("BAD_POSITION"); + ok = false; + } + + return ok; +} + +//================================================================================ +/*! + * \brief SLOT called when selection changed + */ +//================================================================================ + +void SMESHGUI_AddNodeOnSegmentOp::onSelectionDone() +{ + if ( !myDlg->isVisible() || !myDlg->isEnabled() ) + return; + + myNoPreview = true; + QString segmentStr; + try { + SALOME_ListIO aList; + selectionMgr()->selectedObjects(aList, SVTK_Viewer::Type()); + if (aList.Extent() != 1) + return; + Handle(SALOME_InteractiveObject) anIO = aList.First(); + if (( myMeshActor = SMESH::FindActorByEntry(anIO->getEntry()) )) + { + SVTK_IndexedMapOfVtkIds IDs; + selector()->GetCompositeIndex( anIO, IDs ); + if ( IDs.Extent() == 1 && IDs(1).size() == 2 ) + { + SMESH::smIdType id1 = IDs(1)[0]; + SMESH::smIdType id2 = IDs(1)[1]; + segmentStr = QString("%1-%2").arg( id1 ).arg( id2 ); + } + } + } catch (...) { + } + myDlg->mySegment->setText( segmentStr ); + + myNoPreview = false; + redisplayPreview(); +} + +//================================================================================ +/*! + * \brief update preview + */ +//================================================================================ + +void SMESHGUI_AddNodeOnSegmentOp::redisplayPreview() +{ + if ( myNoPreview || !myDlg->myPreviewChkBox->isChecked() ) + { + if ( mySimulation ) + mySimulation->SetVisibility(false); + return; + } + myNoPreview = true; + + SMESH::MeshPreviewStruct_var aMeshPreviewStruct; + + QString msg; + SMESH::smIdType node1, node2; + try { + if ( isValid( msg, node1, node2 )) + { + SMESH::SMESH_Mesh_var aMesh = SMESH::GetMeshByIO(myMeshActor->getIO()); + if ( !aMesh->_is_nil() ) + { + SMESH::SMESH_MeshEditor_var aPreviewer = aMesh->GetMeshEditPreviewer(); + if ( !aPreviewer->_is_nil() ) + { + SUIT_OverrideCursor aWaitCursor; + double pos = myDlg->myPositionSpin->value(); + aPreviewer->AddNodeOnSegment( node1, node2, pos ); + + aMeshPreviewStruct = aPreviewer->GetPreviewData(); + } + } + } + } + catch (...) { + } + + if (!mySimulation) + mySimulation = new SMESHGUI_MeshEditPreview(SMESH::GetViewWindow( mySMESHGUI )); + // display data + if ( & aMeshPreviewStruct.in() ) + { + mySimulation->SetData( aMeshPreviewStruct.in() ); + } + else + { + mySimulation->SetVisibility(false); + } + + myNoPreview = false; +} + +//================================================================================= +/*! + * \brief SLOT called when the viewer opened + */ +//================================================================================= + +void SMESHGUI_AddNodeOnSegmentOp::onOpenView() +{ + if ( mySimulation ) { + mySimulation->SetVisibility(false); + SMESH::SetPointRepresentation(false); + } + else { + mySimulation = new SMESHGUI_MeshEditPreview(SMESH::GetViewWindow( mySMESHGUI )); + } +} + +//================================================================================= +/*! + * \brief SLOT called when the viewer closed + */ +//================================================================================= + +void SMESHGUI_AddNodeOnSegmentOp::onCloseView() +{ + delete mySimulation; + mySimulation = 0; +} + +//================================================================================ +/*! + * \brief SLOT called when the node ids are manually changed + */ +//================================================================================ + +void SMESHGUI_AddNodeOnSegmentOp::onTextChange( const QString& /*theText*/ ) +{ + QString msg; + SMESH::smIdType node1= 0, node2 = 0; + + if (( isValid( msg, node1, node2 )) || + ( node1 && node2 )) // position only can be invalid + { + // highlight entered segment + + Handle(SALOME_InteractiveObject) anIO = myMeshActor->getIO(); + SALOME_ListIO aList; + aList.Append( anIO ); + selectionMgr()->setSelectedObjects( aList, false ); + + SVTK_ListOfVtk newIndices = { node1, node2 }; + selector()->AddOrRemoveCompositeIndex( anIO, newIndices, false ); + SMESH::GetViewWindow(mySMESHGUI)->highlight( anIO, true, true ); + } +} + +//================================================================================ +/*! + * \brief Activate Node selection + */ +//================================================================================ + +void SMESHGUI_AddNodeOnSegmentOp::activateSelection() +{ + selectionMgr()->clearFilters(); + SMESH::SetPointRepresentation( false ); + onSelTypeChange(); +} + +//================================================================================ +/*! + * \brief Destructor + */ +//================================================================================ + +SMESHGUI_AddNodeOnSegmentOp::~SMESHGUI_AddNodeOnSegmentOp() +{ + if ( myDlg ) delete myDlg; + if ( mySimulation ) delete mySimulation; +} + +//================================================================================ +/*! + * \brief Gets dialog of this operation + * \retval LightApp_Dialog* - pointer to dialog of this operation + */ +//================================================================================ + +LightApp_Dialog* SMESHGUI_AddNodeOnSegmentOp::dlg() const +{ + return myDlg; +} + +//================================================================================ +/* +* \brief Process InteractiveSelectionChanged event +*/ +//================================================================================ +void SMESHGUI_AddNodeOnSegmentOp::processStyleEvents(unsigned long theEvent, void* theCallData) +{ + (void*)theCallData; + QString msg; + SMESH::smIdType node1 = 0, node2 = 0; + if (isValid(msg, node1, node2)) { + if (theEvent == SVTK::InteractiveSelectionChanged) { + if (SMDS_Mesh* mesh = myMeshActor->GetObject()->GetMesh()) + if(myRWInteractor && myRWInteractor->GetDevice() && myInteractorStyle) { + { + double N1[3]; + double N2[3]; + double pos; + double N1_SC[3]; + double N2_SC[3]; + double xyz[3]; + double closest[3]; + + const SMDS_MeshNode* n1 = mesh->FindNode(node1); + const SMDS_MeshNode* n2 = mesh->FindNode(node2); + int xClick, yClick; // Last event (move or left button down) position + myRWInteractor->GetDevice()->GetEventPosition(xClick, yClick); + + n1->GetXYZ(N1); + n2->GetXYZ(N2); + // Get 2D screen coordinates of each node + vtkInteractorObserver::ComputeWorldToDisplay(myRWInteractor->GetRenderer()->GetDevice(), + N1[0], N1[1], N1[2], N1_SC); + vtkInteractorObserver::ComputeWorldToDisplay(myRWInteractor->GetRenderer()->GetDevice(), + N2[0], N2[1], N2[2], N2_SC); + N1_SC[2] = N2_SC[2] = xyz[2] = 0; + xyz[0] = static_cast(xClick); + xyz[1] = static_cast(yClick); + // Parametric position of selected point on a line + vtkLine::DistanceToLine(xyz, N1_SC, N2_SC, pos, closest); + if (pos < 0) + pos = SPIN_TOLERANCE; + else if (pos > 1.0) + pos = 1.0 - SPIN_TOLERANCE; + myDlg->myPositionSpin->SetValue(pos); + redisplayPreview(); + } + } + } + } +} + +//================================================================================ +/* +* \brief Process LeftButtonPressEvent event: activate interactive selection +*/ +//================================================================================ +void SMESHGUI_AddNodeOnSegmentOp::processInteractorEvents(unsigned long theEvent, void* theCallData) +{ + (void*)theCallData; + if (theEvent == vtkCommand::LeftButtonPressEvent && myDlg->myPositionBtn->isChecked()) { + bool control = myRWInteractor->GetDevice()->GetControlKey(); + bool shift = myRWInteractor->GetDevice()->GetControlKey(); + SVTK_ViewWindow* svtkViewWindow = SMESH::GetViewWindow(mySMESHGUI); + if (svtkViewWindow && !shift && ! control) { + QString msg; + SMESH::smIdType node1 = 0, node2 = 0; + if (isValid(msg, node1, node2)) { + svtkViewWindow->activateInteractiveSelection(); + } + } + } +} \ No newline at end of file diff --git a/src/SMESHGUI/SMESHGUI_AddNodeOnSegmentDlg.h b/src/SMESHGUI/SMESHGUI_AddNodeOnSegmentDlg.h new file mode 100644 index 000000000..bdf756955 --- /dev/null +++ b/src/SMESHGUI/SMESHGUI_AddNodeOnSegmentDlg.h @@ -0,0 +1,125 @@ +// Copyright (C) 2007-2021 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, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +// File : SMESHGUI_AddNodeOnSegmentDlg.h +// Author : Edward AGAPOV, Open CASCADE S.A.S. +// +#ifndef SMESHGUI_AddNodeOnSegmentDLG_H +#define SMESHGUI_AddNodeOnSegmentDLG_H + +#include "SMESHGUI_Dialog.h" +#include "SMESHGUI_InteractiveOp.h" + +class QButtonGroup; +class QCheckBox; +class QGroupBox; +class QLineEdit; +class QPushButton; +class QRadioButton; +class SMESHGUI_SpinBox; +class SMESHGUI_MeshEditPreview; +class SMESHGUI_AddNodeOnSegmentDlg; + +/*! + * \brief Operation to make a mesh pass through a point + */ +class SMESHGUI_EXPORT SMESHGUI_AddNodeOnSegmentOp: public SMESHGUI_InteractiveOp +{ + Q_OBJECT + +public: + SMESHGUI_AddNodeOnSegmentOp(); + virtual ~SMESHGUI_AddNodeOnSegmentOp(); + + virtual LightApp_Dialog* dlg() const; + +protected: + + virtual void startOperation() override; + virtual void stopOperation() override; + + virtual void activateSelection(); + + bool isValid( QString&, SMESH::smIdType& n1, SMESH::smIdType& n2 ); + + virtual void processStyleEvents(unsigned long event, + void* calldata) override; + + virtual void processInteractorEvents(unsigned long event, + void* calldata) override; + + +protected slots: + virtual bool onApply() override; + + +private slots: + void onSelectionDone(); + void redisplayPreview(); + void onTextChange( const QString& ); + void onSelTypeChange(); + void onOpenView(); + void onCloseView(); + +private: + + SMESHGUI_AddNodeOnSegmentDlg* myDlg; + + SMESHGUI* mySMESHGUI; + SMESHGUI_MeshEditPreview* mySimulation; + SMESH_Actor* myMeshActor; + bool myNoPreview; +}; + +/*! + * \brief Dialog to make a mesh pass through a point + */ + +class SMESHGUI_EXPORT SMESHGUI_AddNodeOnSegmentDlg : public SMESHGUI_Dialog +{ + Q_OBJECT + +public: + SMESHGUI_AddNodeOnSegmentDlg(); + +signals: + + void selTypeChanged(); + +private: + QWidget* createMainFrame( QWidget* ); + + QPushButton* mySegmentBtn; + QLineEdit* mySegment; + QPushButton* myPositionBtn; + SMESHGUI_SpinBox* myPositionSpin; + QCheckBox* myPreviewChkBox; + + QString myHelpFileName; + + friend class SMESHGUI_AddNodeOnSegmentOp; + +private slots: + void ButtonToggled( bool ); +}; + +#endif // SMESHGUI_AddNodeOnSegmentDLG_H diff --git a/src/SMESHGUI/SMESHGUI_InteractiveOp.cxx b/src/SMESHGUI/SMESHGUI_InteractiveOp.cxx new file mode 100644 index 000000000..565fa3d2f --- /dev/null +++ b/src/SMESHGUI/SMESHGUI_InteractiveOp.cxx @@ -0,0 +1,181 @@ +// Copyright (C) 2007-2021 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, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +// File : SMESHGUI_InteractiveOp.cxx +// Author : Roman NIKOLAEV, Open CASCADE S.A.S. + +// SMESH includes +// +#include "SMESHGUI.h" +#include "SMESHGUI_InteractiveOp.h" +#include "SMESHGUI_VTKUtils.h" + +// GUI includes +#include +#include +#include + +// VTK includes +#include +#include +#include +#include + + +//================================================================================ +/*! + * \brief Constructor +*/ +//================================================================================ + +SMESHGUI_InteractiveOp::SMESHGUI_InteractiveOp() : + SMESHGUI_SelectionOp(), + myInteractorStyle(0), + myRWInteractor(0), + myStyleEventCallbackCommand(vtkCallbackCommand::New()), + myInteractorStypePriority(0.0), + myInteractorEventCallbackCommand(vtkCallbackCommand::New()), + myInteractorPriority(1.0) +{ + myStyleEventCallbackCommand->Delete(); + myStyleEventCallbackCommand->SetClientData(this); + myStyleEventCallbackCommand->SetCallback(SMESHGUI_InteractiveOp::ProcessStyleEvents); + + myInteractorEventCallbackCommand->Delete(); + myInteractorEventCallbackCommand->SetClientData(this); + myInteractorEventCallbackCommand->SetCallback(SMESHGUI_InteractiveOp::ProcessInteractorEvents); +} + +//================================================================================ +/*! + * \brief Destructor +*/ +//================================================================================ +SMESHGUI_InteractiveOp::~SMESHGUI_InteractiveOp() +{ +} + +//======================================================================= +// function : addObserver() +// purpose : Add VTK observers to process SVTK_InteractorStyle and vtkGenericRenderWindowInteractor events +//====================================================================== +void SMESHGUI_InteractiveOp::addObserver() +{ + if (myInteractorStyle && !myInteractorStyle->HasObserver(SVTK::InteractiveSelectionChanged, myStyleEventCallbackCommand.GetPointer())) { + myInteractorStyle->AddObserver(SVTK::InteractiveSelectionChanged, myStyleEventCallbackCommand.GetPointer(), + myInteractorStypePriority); + } + if (myRWInteractor && myRWInteractor->GetDevice() && + !myRWInteractor->GetDevice()->HasObserver(vtkCommand::LeftButtonPressEvent, myInteractorEventCallbackCommand.GetPointer())) { + myRWInteractor->GetDevice()->AddObserver(vtkCommand::LeftButtonPressEvent, myInteractorEventCallbackCommand.GetPointer(), + myInteractorPriority); + } +} + +//======================================================================= +// function : removeObserver() +// purpose : Remove VTK observers +//====================================================================== +void SMESHGUI_InteractiveOp::removeObserver() { + if (myInteractorStyle && myInteractorStyle->HasObserver(SVTK::InteractiveSelectionChanged, myStyleEventCallbackCommand.GetPointer())) { + myInteractorStyle->RemoveObserver(myStyleEventCallbackCommand.GetPointer()); + } + if (myRWInteractor && myRWInteractor->GetDevice() && + myRWInteractor->GetDevice()->HasObserver(vtkCommand::LeftButtonPressEvent, myInteractorEventCallbackCommand.GetPointer())) { + myRWInteractor->GetDevice()->RemoveObserver(myInteractorEventCallbackCommand.GetPointer()); + } +} + +//======================================================================= +// function : startOperation() +// purpose : Init dialog fields, connect signals and slots, show dialog +//======================================================================= + +void SMESHGUI_InteractiveOp::startOperation() +{ + SVTK_ViewWindow* svtkViewWindow = SMESH::GetViewWindow(getSMESHGUI()); + if (svtkViewWindow) { + myInteractorStyle = svtkViewWindow->GetInteractorStyle(); + myRWInteractor = svtkViewWindow->GetInteractor(); + } +} + +//================================================================================ +/*! + * \brief Process interactor style events + Static method. Used by vtkCallbackCommand->SetCallback method. + */ + //=============================================================================== +void SMESHGUI_InteractiveOp::ProcessStyleEvents(vtkObject* vtkNotUsed(theObject), + unsigned long theEvent, + void* theClientData, + void* theCallData) { + SMESHGUI_InteractiveOp* self = reinterpret_cast(theClientData); + if (self) + self->processStyleEvents(theEvent, theCallData); +} + +//================================================================================ +/*! + * \brief Process Generic Render Window Interactor events. + Static method. Used by vtkCallbackCommand->SetCallback method. + */ + //=============================================================================== +void SMESHGUI_InteractiveOp::ProcessInteractorEvents(vtkObject* vtkNotUsed(theObject), + unsigned long theEvent, + void* theClientData, + void* theCallData) { + SMESHGUI_InteractiveOp* self = reinterpret_cast(theClientData); + if (self) + self->processInteractorEvents(theEvent, theCallData); +} + +//================================================================================ +/*! + * \brief Process interactor style events () + Virtual method. Should be overridden in inherited classes. + */ + //=============================================================================== + +void SMESHGUI_InteractiveOp::processStyleEvents(unsigned long theEvent, void* theCallData) { +} + +//================================================================================ +/*! + * \brief Process Generic Render Window Interactor events. + Virtual method. Should be overridden in inherited classes. + */ + //=============================================================================== +void SMESHGUI_InteractiveOp::processInteractorEvents(unsigned long theEvent, void* theCallData) +{ +} + +//================================================================================ +/*! + * \brief Deactivate current operation in active VTK viewer + */ + //=============================================================================== +void SMESHGUI_InteractiveOp::deactivateCurrentViewOperation() { + if (SVTK_ViewWindow* svtkViewWindow = SMESH::GetViewWindow(getSMESHGUI())) { + svtkViewWindow->deactivateCurrectOperation(); + } +} \ No newline at end of file diff --git a/src/SMESHGUI/SMESHGUI_InteractiveOp.h b/src/SMESHGUI/SMESHGUI_InteractiveOp.h new file mode 100644 index 000000000..65894e315 --- /dev/null +++ b/src/SMESHGUI/SMESHGUI_InteractiveOp.h @@ -0,0 +1,88 @@ +// Copyright (C) 2007-2021 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, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +// File : SMESHGUI_InteractiveOp.h +// Author : Roman NIKOLAEV, Open CASCADE S.A.S. +// + +#pragma once + +// SMESH includes +#include "SMESH_SMESHGUI.hxx" +#include "SMESHGUI_SelectionOp.h" + +// VTK includes +#include + +/* + Class : SMESHGUI_InteractiveOp + Description : Base operation for all interactive operations in the VTK 3D Viewer +*/ + +class vtkInteractorStyle; +class vtkCallbackCommand; +class vtkObject; +class SVTK_RenderWindowInteractor; + +class SMESHGUI_EXPORT SMESHGUI_InteractiveOp: public SMESHGUI_SelectionOp { + Q_OBJECT +public: + SMESHGUI_InteractiveOp(); + virtual ~SMESHGUI_InteractiveOp(); + + virtual void deactivateCurrentViewOperation(); + +protected: + virtual void startOperation() override; + + static void ProcessStyleEvents(vtkObject* object, + unsigned long event, + void* clientdata, + void* calldata); + virtual void processStyleEvents(unsigned long event, + void* calldata); + + static void ProcessInteractorEvents(vtkObject* object, + unsigned long event, + void* clientdata, + void* calldata); + virtual void processInteractorEvents(unsigned long event, + void* calldata); + + virtual void addObserver(); + virtual void removeObserver(); + + +protected: + vtkInteractorStyle* myInteractorStyle; + SVTK_RenderWindowInteractor* myRWInteractor; + + // Priority at which events are processed: + // Interactor Stype events + double myInteractorStypePriority; + // Interactor events + double myInteractorPriority; + + // Used to process events + vtkSmartPointer myStyleEventCallbackCommand; + vtkSmartPointer myInteractorEventCallbackCommand; +}; diff --git a/src/SMESHGUI/SMESHGUI_MakeNodeAtPointDlg.cxx b/src/SMESHGUI/SMESHGUI_MakeNodeAtPointDlg.cxx index 6b1b7c140..8620d7e93 100644 --- a/src/SMESHGUI/SMESHGUI_MakeNodeAtPointDlg.cxx +++ b/src/SMESHGUI/SMESHGUI_MakeNodeAtPointDlg.cxx @@ -48,6 +48,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -74,7 +77,10 @@ #include // VTK includes +#include #include +#include +#include // IDL includes #include @@ -86,13 +92,18 @@ namespace { - enum { MANUAL_MODE = 0, SEARCH_MODE }; // how a node to move is specified + enum { MANUAL_MODE = 0, SEARCH_MODE, INTERACTIVE_MODE }; } +//#define SELECTION_PRECISION 4 + +//======================================================================= /*! * \brief Dialog to publish a sub-shape of the mesh main shape * by selecting mesh elements */ +//======================================================================= + SMESHGUI_MakeNodeAtPointDlg::SMESHGUI_MakeNodeAtPointDlg() : SMESHGUI_Dialog( 0, false, true ) { @@ -112,6 +123,7 @@ SMESHGUI_MakeNodeAtPointDlg::SMESHGUI_MakeNodeAtPointDlg() // function : createMainFrame() // purpose : Create frame containing dialog's input fields //======================================================================= + QWidget* SMESHGUI_MakeNodeAtPointDlg::createMainFrame (QWidget* theParent) { QWidget* aFrame = new QWidget(theParent); @@ -119,8 +131,9 @@ QWidget* SMESHGUI_MakeNodeAtPointDlg::createMainFrame (QWidget* theParent) SUIT_ResourceMgr* rm = SMESH::GetResourceMgr( SMESHGUI::GetSMESHGUI() ); QPixmap iconMoveNode (rm->loadPixmap("SMESH", tr("ICON_DLG_MOVE_NODE"))); QPixmap iconMoveWithoutNode (rm->loadPixmap("SMESH", tr("ICON_DLG_MOVE_WITHOUT_NODE"))); + QPixmap iconMoveInteractive (rm->loadPixmap("SMESH", tr("ICON_DLG_MOVE_NODE_INTERACTIVE"))); QPixmap iconSelect (rm->loadPixmap("SMESH", tr("ICON_SELECT"))); - + // constructor QGroupBox* aPixGrp = new QGroupBox(tr("MOVE_NODE"), this); aPixGrp->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) ); @@ -129,16 +142,20 @@ QWidget* SMESHGUI_MakeNodeAtPointDlg::createMainFrame (QWidget* theParent) aPixGrpLayout->setMargin(MARGIN); aPixGrpLayout->setSpacing(SPACING); - myRButNodeToMove = new QRadioButton(aPixGrp); + myRButNodeToMove = new QRadioButton(aPixGrp); myRButMoveWithoutNode = new QRadioButton(aPixGrp); + myRButMoveInteractive = new QRadioButton(aPixGrp); myRButNodeToMove->setIcon(iconMoveNode); myRButMoveWithoutNode->setIcon(iconMoveWithoutNode); + myRButMoveInteractive->setIcon(iconMoveInteractive); myRButNodeToMove->setChecked(true); aPixGrpLayout->addWidget(myRButNodeToMove); aPixGrpLayout->addWidget(myRButMoveWithoutNode); - myButtonGroup->addButton(myRButNodeToMove, 0); + aPixGrpLayout->addWidget(myRButMoveInteractive); + myButtonGroup->addButton(myRButNodeToMove, 0); myButtonGroup->addButton(myRButMoveWithoutNode, 1); + myButtonGroup->addButton(myRButMoveInteractive, 2); // Node to move @@ -302,11 +319,15 @@ void SMESHGUI_MakeNodeAtPointDlg::ButtonToggled (bool on) * \param int - number of the button */ //================================================================================ + void SMESHGUI_MakeNodeAtPointDlg::ConstructorsClicked (int constructorId) { switch (constructorId) { - case 0: + case MANUAL_MODE: + case INTERACTIVE_MODE: { + myUpdateBtn->setVisible( constructorId == MANUAL_MODE ); + myDestinationGrp->setTitle( tr( constructorId == MANUAL_MODE ? "DESTINATION" : "DESTINATION_BY_MOUSE")); myDestDXLabel->show(); myDestDYLabel->show(); myDestDZLabel->show(); @@ -317,9 +338,10 @@ void SMESHGUI_MakeNodeAtPointDlg::ConstructorsClicked (int constructorId) myCurrentY->SetValue(0); myCurrentZ->SetValue(0); if (!myNodeToMoveGrp->isVisible()) myNodeToMoveGrp->show(); + myIdBtn->setChecked( true ); break; } - case 1: + case SEARCH_MODE: { myId->setText(""); myCurrentX->SetValue(0); @@ -349,8 +371,10 @@ void SMESHGUI_MakeNodeAtPointDlg::ConstructorsClicked (int constructorId) */ //================================================================================ -SMESHGUI_MakeNodeAtPointOp::SMESHGUI_MakeNodeAtPointOp() +SMESHGUI_MakeNodeAtPointOp::SMESHGUI_MakeNodeAtPointOp(int defaultConstructor) : + SMESHGUI_InteractiveOp() { + myDefaultConstructor = defaultConstructor; mySimulation = 0; mySMESHGUI = 0; myDlg = new SMESHGUI_MakeNodeAtPointDlg; @@ -370,7 +394,7 @@ SMESHGUI_MakeNodeAtPointOp::SMESHGUI_MakeNodeAtPointOp() connect(myDlg->myDestDZ, SIGNAL (valueChanged(double)), this, SLOT(onDestCoordChanged())); connect(myDlg->myId, SIGNAL (textChanged(const QString&)),SLOT(redisplayPreview())); connect(myDlg->myPreviewChkBox, SIGNAL (toggled(bool)), SLOT(redisplayPreview())); - connect(myDlg->myButtonGroup, SIGNAL (buttonClicked(int)), SLOT(redisplayPreview())); + connect(myDlg->myButtonGroup, SIGNAL (buttonClicked(int)), SLOT(constructorChanged())); // IPAL22913: TC6.5.0: selected in "Move node" dialog box node is not highlighted // note: this slot seems to be lost together with removed obsolete SMESHGUI_MoveNodesDlg class @@ -378,6 +402,12 @@ SMESHGUI_MakeNodeAtPointOp::SMESHGUI_MakeNodeAtPointOp() connect(myDlg->myUpdateBtn, SIGNAL (clicked()), this, SLOT(onUpdateDestination())); } +//================================================================================ +/*! + * \brief SLOT. Update preview upon [Update destination] clicked + */ +//================================================================================ + void SMESHGUI_MakeNodeAtPointOp::onUpdateDestination() { myUpdateDestination = true; @@ -385,6 +415,12 @@ void SMESHGUI_MakeNodeAtPointOp::onUpdateDestination() myUpdateDestination = false; } +//================================================================================ +/*! + * \brief SLOT. Update preview upon Destination coordinates change + */ +//================================================================================ + void SMESHGUI_MakeNodeAtPointOp::onDestCoordChanged() { myDestCoordChanged = false; @@ -392,10 +428,12 @@ void SMESHGUI_MakeNodeAtPointOp::onDestCoordChanged() myDestCoordChanged = true; } + //======================================================================= // function : startOperation() // purpose : Init dialog fields, connect signals and slots, show dialog //======================================================================= + void SMESHGUI_MakeNodeAtPointOp::startOperation() { myNoPreview = false; @@ -404,7 +442,8 @@ void SMESHGUI_MakeNodeAtPointOp::startOperation() // init simulation with a current View if ( mySimulation ) delete mySimulation; mySMESHGUI = getSMESHGUI(); - mySimulation = new SMESHGUI_MeshEditPreview(SMESH::GetViewWindow( mySMESHGUI ) ); + mySimulation = new SMESHGUI_MeshEditPreview(SMESH::GetViewWindow(mySMESHGUI)); + connect(mySMESHGUI, SIGNAL (SignalActivatedViewManager()), this, SLOT(onOpenView())); connect(mySMESHGUI, SIGNAL (SignalCloseView()), this, SLOT(onCloseView())); vtkProperty* aProp = vtkProperty::New(); @@ -427,6 +466,7 @@ void SMESHGUI_MakeNodeAtPointOp::startOperation() // IPAL19360 SMESHGUI_SelectionOp::startOperation(); // this method should be called only after filter creation //activateSelection(); // set filters // called inside of previous statement + SMESHGUI_InteractiveOp::startOperation(); myDlg->myId->setText(""); myDlg->myDestinationX->SetValue(0); myDlg->myDestinationY->SetValue(0); @@ -442,6 +482,10 @@ void SMESHGUI_MakeNodeAtPointOp::startOperation() myDlg->myDestDZ->setReadOnly(true); myDlg->myRButNodeToMove->setChecked(true); + if ( myDefaultConstructor == INTERACTIVE_MODE ) { + addObserver(); + myDlg->myButtonGroup->button( INTERACTIVE_MODE )->setChecked(true); + } myDlg->ConstructorsClicked( GetConstructorId() ); myDlg->show(); @@ -453,6 +497,7 @@ void SMESHGUI_MakeNodeAtPointOp::startOperation() // function : GetConstructorId() // purpose : //================================================================================= + int SMESHGUI_MakeNodeAtPointOp::GetConstructorId() { return myDlg->myButtonGroup->checkedId(); @@ -483,6 +528,7 @@ void SMESHGUI_MakeNodeAtPointOp::stopOperation() disconnect(mySMESHGUI, SIGNAL (SignalCloseView()), this, SLOT(onCloseView())); selectionMgr()->removeFilter( myFilter ); SMESHGUI_SelectionOp::stopOperation(); + removeObserver(); } //================================================================================ @@ -828,6 +874,7 @@ void SMESHGUI_MakeNodeAtPointOp::redisplayPreview() * \brief SLOT called when the viewer opened */ //================================================================================= + void SMESHGUI_MakeNodeAtPointOp::onOpenView() { if ( mySimulation ) { @@ -839,11 +886,29 @@ void SMESHGUI_MakeNodeAtPointOp::onOpenView() } } +//================================================================================= +/*! + * \brief SLOT called when the creation mode is changed + */ + //================================================================================= + +void SMESHGUI_MakeNodeAtPointOp::constructorChanged() { + redisplayPreview(); + if (GetConstructorId() == INTERACTIVE_MODE) { + addObserver(); + } + else { + removeObserver(); + } +} + + //================================================================================= /*! * \brief SLOT called when the viewer closed */ //================================================================================= + void SMESHGUI_MakeNodeAtPointOp::onCloseView() { delete mySimulation; @@ -918,3 +983,54 @@ LightApp_Dialog* SMESHGUI_MakeNodeAtPointOp::dlg() const return myDlg; } + +//================================================================================ +/* +* \brief Process InteractiveSelectionChanged event +*/ +//================================================================================ + +void SMESHGUI_MakeNodeAtPointOp::processStyleEvents(unsigned long theEvent, void* theCallData) { + if (theEvent == SVTK::InteractiveSelectionChanged) { + double* aCoord = (double*)theCallData; + myDlg->myDestinationX->SetValue(aCoord[0]); + myDlg->myDestinationY->SetValue(aCoord[1]); + myDlg->myDestinationZ->SetValue(aCoord[2]); + redisplayPreview(); + } +} + +//================================================================================ +/* +* \brief Process LeftButtonPressEvent event +*/ +//================================================================================ +void SMESHGUI_MakeNodeAtPointOp::processInteractorEvents(unsigned long theEvent, void* theCallData) { + (void*)theCallData; + if (theEvent == vtkCommand::LeftButtonPressEvent) { + bool control = myRWInteractor->GetDevice()->GetControlKey(); + bool shift = myRWInteractor->GetDevice()->GetControlKey(); + if (GetConstructorId() == INTERACTIVE_MODE && myDlg->myDestBtn->isChecked() && !shift && !control) { + if (SVTK_ViewWindow* svtkViewWindow = SMESH::GetViewWindow(SMESHGUI::GetSMESHGUI())) { + svtkViewWindow->activateInteractiveSelection(); + } + } + } + /* + if ( myRWInteractor && myRWInteractor->GetDevice() && myInteractorStyle ) { + int xClick, yClick; // Last click position + myRWInteractor->GetDevice()->GetEventPosition(xClick, yClick); + double nodeCoords[3]; + vtkInteractorObserver::ComputeWorldToDisplay(myRWInteractor->GetRenderer()->GetDevice(), + myDlg->myDestinationX->GetValue(), + myDlg->myDestinationY->GetValue(), + myDlg->myDestinationZ->GetValue(), + nodeCoords); + double rad = std::sqrt(std::pow(xClick - nodeCoords[0], 2) + std::pow(yClick - nodeCoords[1], 2)); + if (rad < SELECTION_PRECISION) { + if (SVTK_ViewWindow* svtkViewWindow = SMESH::GetViewWindow(mySMESHGUI)) { + svtkViewWindow->activateInteractiveSelection(); + } + } + }*/ +} diff --git a/src/SMESHGUI/SMESHGUI_MakeNodeAtPointDlg.h b/src/SMESHGUI/SMESHGUI_MakeNodeAtPointDlg.h index d1d0f09ba..945f08f6e 100644 --- a/src/SMESHGUI/SMESHGUI_MakeNodeAtPointDlg.h +++ b/src/SMESHGUI/SMESHGUI_MakeNodeAtPointDlg.h @@ -30,7 +30,9 @@ #include "SMESH_SMESHGUI.hxx" #include "SMESHGUI_Dialog.h" -#include "SMESHGUI_SelectionOp.h" +#include "SMESHGUI_InteractiveOp.h" + +#include class QButtonGroup; class QCheckBox; @@ -42,28 +44,35 @@ class SMESHGUI_SpinBox; class SMESHGUI_MeshEditPreview; class SMESHGUI_MakeNodeAtPointDlg; + /*! * \brief Operation to make a mesh pass through a point */ -class SMESHGUI_EXPORT SMESHGUI_MakeNodeAtPointOp: public SMESHGUI_SelectionOp +class SMESHGUI_EXPORT SMESHGUI_MakeNodeAtPointOp: public SMESHGUI_InteractiveOp { Q_OBJECT public: - SMESHGUI_MakeNodeAtPointOp(); + SMESHGUI_MakeNodeAtPointOp(int defaultConstructor = 0); virtual ~SMESHGUI_MakeNodeAtPointOp(); virtual LightApp_Dialog* dlg() const; protected: - virtual void startOperation(); - virtual void stopOperation(); + virtual void startOperation() override; + virtual void stopOperation() override; - virtual void activateSelection(); + virtual void activateSelection() override; bool isValid( QString& ); + virtual void processStyleEvents(unsigned long event, + void* calldata) override; + + virtual void processInteractorEvents(unsigned long event, + void* calldata) override; + protected slots: virtual bool onApply(); @@ -75,14 +84,15 @@ private slots: void onDestCoordChanged(); void onOpenView(); void onCloseView(); + void constructorChanged(); private: int GetConstructorId(); + int myDefaultConstructor; SMESHGUI_MakeNodeAtPointDlg* myDlg; SUIT_SelectionFilter* myFilter; - int myMeshOldDisplayMode; SMESHGUI* mySMESHGUI; SMESHGUI_MeshEditPreview* mySimulation; SMESH_Actor* myMeshActor; @@ -110,6 +120,7 @@ private: QButtonGroup* myButtonGroup; QRadioButton* myRButNodeToMove; QRadioButton* myRButMoveWithoutNode; + QRadioButton* myRButMoveInteractive; QPushButton* myDestBtn; QPushButton* myUpdateBtn; QGroupBox* myDestinationGrp; diff --git a/src/SMESHGUI/SMESHGUI_Operations.h b/src/SMESHGUI/SMESHGUI_Operations.h index b91a92787..f9b6a32db 100644 --- a/src/SMESHGUI/SMESHGUI_Operations.h +++ b/src/SMESHGUI/SMESHGUI_Operations.h @@ -153,6 +153,7 @@ namespace SMESHOp { OpRemoveNodes = 4200, // MENU MODIFICATION - REMOVE - NODE OpRemoveElements = 4201, // MENU MODIFICATION - REMOVE - ELEMENTS OpRemoveOrphanNodes = 4202, // MENU MODIFICATION - REMOVE - ORPHAN NODES + OpRemoveNodeWithReconn = 4203, // MENU MODIFICATION - REMOVE - NODE, WITH RECONNECTION OpDeleteGroup = 4210, // MENU MODIFICATION - REMOVE - DELETE GROUPS WITH CONTENTS OpClearMesh = 4220, // MENU MODIFICATION - REMOVE - CLEAR MESH DATA OpRenumberingNodes = 4300, // MENU MODIFICATION - RENUMBERING - NODES @@ -182,6 +183,9 @@ namespace SMESHOp { OpConvertMeshToQuadratic = 4513, // MENU MODIFICATION - CONVERT TO/FROM QUADRATIC OpCreateBoundaryElements = 4514, // MENU MODIFICATION - CREATE BOUNDARY ELEMENTS OpSplitBiQuadratic = 4515, // MENU MODIFICATION - SPLIT BI-QUADRATIC TO LINEAR + OpMoveNodeInteractive = 4516, // MENU MODIFICATION - MOVE NODE INTERACTIVE + OpSplitEdgeInteract = 4517, // MENU MODIFICATION - INTERACTIVE ADD NODE ON EDGE + OpSplitFaceInteract = 4518, // MENU MODIFICATION - INTERACTIVE ADD NODE ON FACE // Adaptation ---------------------//-------------------------------- OpMGAdapt = 8020, // MENU ADAPTATION - MG-ADAPT OpHomardAdapt = 8021, // MENU ADAPTATION - HOMARD-ADAPT diff --git a/src/SMESHGUI/SMESHGUI_RemoveNodeReconnectionDlg.cxx b/src/SMESHGUI/SMESHGUI_RemoveNodeReconnectionDlg.cxx new file mode 100644 index 000000000..890c630f2 --- /dev/null +++ b/src/SMESHGUI/SMESHGUI_RemoveNodeReconnectionDlg.cxx @@ -0,0 +1,485 @@ +// Copyright (C) 2007-2021 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, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +// File : SMESHGUI_MakeNodeAtPointDlg.cxx +// Author : Edward AGAPOV, Open CASCADE S.A.S. +// SMESH includes +// +#include "SMESHGUI_RemoveNodeReconnectionDlg.h" + +#include "SMESHGUI.h" +#include "SMESHGUI_IdValidator.h" +#include "SMESHGUI_MeshUtils.h" +#include "SMESHGUI_VTKUtils.h" +#include "SMESHGUI_MeshEditPreview.h" + +#include +#include +#include +#include + +// SALOME GUI includes +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Qt includes +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// VTK includes +#include + +// IDL includes +#include +#include CORBA_SERVER_HEADER(SMESH_Mesh) +#include CORBA_SERVER_HEADER(SMESH_MeshEditor) + +#define SPACING 6 +#define MARGIN 11 + +//======================================================================= +/*! + * \brief Dialog to Remove a node with elements re-connection + */ +//======================================================================= + +SMESHGUI_RemoveNodeReconnectionDlg::SMESHGUI_RemoveNodeReconnectionDlg() + : SMESHGUI_Dialog( 0, false, true ) +{ + setWindowTitle(tr("CAPTION")); + + QVBoxLayout* aDlgLay = new QVBoxLayout (mainFrame()); + aDlgLay->setMargin(0); + aDlgLay->setSpacing(SPACING); + myMainFrame = createMainFrame(mainFrame()); + + aDlgLay->addWidget(myMainFrame); + + aDlgLay->setStretchFactor(myMainFrame, 1); +} + +//======================================================================= +// function : createMainFrame() +// purpose : Create frame containing dialog's input fields +//======================================================================= + +QWidget* SMESHGUI_RemoveNodeReconnectionDlg::createMainFrame (QWidget* theParent) +{ + QWidget* aFrame = new QWidget(theParent); + + // Node to remove + + myNodeToMoveGrp = new QGroupBox(tr("NODE_2REMOVE"), aFrame); + myNodeToMoveGrp->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) ); + QLabel* idLabel = new QLabel(tr("NODE_2REMOVE_ID"), myNodeToMoveGrp); + myId = new QLineEdit(myNodeToMoveGrp); + myId->setValidator(new SMESHGUI_IdValidator(this, 1)); + + QGridLayout* myNodeToMoveGrpLayout = new QGridLayout(myNodeToMoveGrp); + myNodeToMoveGrpLayout->setSpacing(SPACING); + myNodeToMoveGrpLayout->setMargin(MARGIN); + + myNodeToMoveGrpLayout->addWidget( idLabel, 0, 0 ); + myNodeToMoveGrpLayout->addWidget( myId, 0, 2 ); + + // Preview + + myPreviewChkBox = new QCheckBox( tr("PREVIEW"), aFrame); + + QVBoxLayout* aLay = new QVBoxLayout(aFrame); + aLay->addWidget(myNodeToMoveGrp); + aLay->addWidget(myPreviewChkBox); + + return aFrame; +} + +//================================================================================ +/*! + * \brief Constructor + */ +//================================================================================ + +SMESHGUI_RemoveNodeReconnectionOp::SMESHGUI_RemoveNodeReconnectionOp() +{ + mySimulation = 0; + mySMESHGUI = 0; + myDlg = new SMESHGUI_RemoveNodeReconnectionDlg; + myFilter = 0; + myHelpFileName = "removing_nodes_and_elements.html#removing-nodes-reconnect-anchor"; + + myNoPreview = false; + + // connect signals and slots + connect(myDlg->myId, SIGNAL (textChanged(const QString&)),SLOT(redisplayPreview())); + connect(myDlg->myPreviewChkBox, SIGNAL (toggled(bool)), SLOT(redisplayPreview())); + connect(myDlg->myId, SIGNAL (textChanged(const QString&)),SLOT(onTextChange(const QString&))); +} + +//======================================================================= +// function : startOperation() +// purpose : Init dialog fields, connect signals and slots, show dialog +//======================================================================= + +void SMESHGUI_RemoveNodeReconnectionOp::startOperation() +{ + myNoPreview = false; + myMeshActor = 0; + + // init simulation with a current View + if ( mySimulation ) delete mySimulation; + mySMESHGUI = getSMESHGUI(); + mySimulation = new SMESHGUI_MeshEditPreview(SMESH::GetViewWindow( mySMESHGUI ) ); + connect(mySMESHGUI, SIGNAL (SignalActivatedViewManager()), this, SLOT(onOpenView())); + connect(mySMESHGUI, SIGNAL (SignalCloseView()), this, SLOT(onCloseView())); + vtkProperty* aProp = vtkProperty::New(); + aProp->SetRepresentationToWireframe(); + aProp->SetColor(250, 0, 250); + aProp->SetPointSize(5); + aProp->SetLineWidth( SMESH::GetFloat("SMESH:element_width",1) + 1); + mySimulation->GetActor()->SetProperty(aProp); + aProp->Delete(); + + // SalomeApp_TypeFilter depends on a current study + if ( myFilter ) delete myFilter; + // QList filters; + // filters.append( new SalomeApp_TypeFilter((SalomeApp_Study*)study(), "SMESH" )); + // myFilter = new SMESH_LogicalFilter( filters, SMESH_LogicalFilter::LO_OR ); + + // IPAL19360 + SMESHGUI_SelectionOp::startOperation(); // this method should be called only after filter creation + myDlg->myId->setText(""); + + myDlg->show(); + + onSelectionDone(); // init myMeshActor +} + +//================================================================================ +/*! + * \brief Stops operation + */ +//================================================================================ + +void SMESHGUI_RemoveNodeReconnectionOp::stopOperation() +{ + myNoPreview = true; + if ( mySimulation ) + { + mySimulation->SetVisibility(false); + delete mySimulation; + mySimulation = 0; + } + if ( myMeshActor ) { + myMeshActor = 0; + } + SMESH::SetPointRepresentation( false ); + SMESH::RepaintCurrentView(); + + disconnect(mySMESHGUI, SIGNAL (SignalActivatedViewManager()), this, SLOT(onOpenView())); + disconnect(mySMESHGUI, SIGNAL (SignalCloseView()), this, SLOT(onCloseView())); + //selectionMgr()->removeFilter( myFilter ); + SMESHGUI_SelectionOp::stopOperation(); +} + +//================================================================================ +/*! + * \brief perform it's intention action: move or create a node + */ +//================================================================================ + +bool SMESHGUI_RemoveNodeReconnectionOp::onApply() +{ + if( SMESHGUI::isStudyLocked() ) + return false; + + if ( !myMeshActor ) { + SUIT_MessageBox::warning( dlg(), tr( "SMESH_WRN_WARNING" ), tr("INVALID_MESH") ); + dlg()->show(); + return false; + } + + QString msg; + if ( !isValid( msg ) ) { // node id is invalid + if ( !msg.isEmpty() ) + SUIT_MessageBox::warning( dlg(), tr( "SMESH_WRN_WARNING" ), tr("INVALID_ID") ); + dlg()->show(); + return false; + } + + try { + SMESH::SMESH_Mesh_var aMesh = SMESH::GetMeshByIO( myMeshActor->getIO() ); + if ( aMesh->_is_nil() ) + { + SUIT_MessageBox::information(SMESHGUI::desktop(), tr("SMESH_ERROR"), tr("SMESHG_NO_MESH") ); + return true; + } + SMESH::SMESH_MeshEditor_var aMeshEditor = aMesh->GetMeshEditor(); + if ( aMeshEditor->_is_nil() ) + return true; + + bool ok; + int anId = myDlg->myId->text().toInt( &ok ); + myDlg->myId->setText( "" ); + + aMeshEditor->RemoveNodeWithReconnection( anId ); + + SALOME_ListIO aList; + selectionMgr()->setSelectedObjects(aList,false); + aList.Append( myMeshActor->getIO() ); + selectionMgr()->setSelectedObjects(aList,false); + SMESH::UpdateView(); + SMESHGUI::Modified(); + + } + catch (const SALOME::SALOME_Exception& S_ex) { + SalomeApp_Tools::QtCatchCorbaException(S_ex); + } + catch (...) { + } + + return true; +} + +//================================================================================ +/*! + * \brief Check selected node id validity + */ +//================================================================================ + +bool SMESHGUI_RemoveNodeReconnectionOp::isValid( QString& msg ) +{ + bool ok = true; + if ( myMeshActor ) + { + ok = false; + int id = myDlg->myId->text().toInt(); + if ( id > 0 ) + if ( SMDS_Mesh* aMesh = myMeshActor->GetObject()->GetMesh() ) + ok = aMesh->FindNode( id ); + if ( !ok ) + msg += tr("INVALID_ID") + "\n"; + } + + return ok; +} + +//================================================================================ +/*! + * \brief SLOT called when selection changed + */ +//================================================================================ + +void SMESHGUI_RemoveNodeReconnectionOp::onSelectionDone() +{ + if ( !myDlg->isVisible() || !myDlg->isEnabled() ) + return; + + myDlg->myId->setText(""); + myNoPreview = true; + try + { + SALOME_ListIO aList; + selectionMgr()->selectedObjects( aList, SVTK_Viewer::Type() ); + if ( aList.Extent() != 1) + return; + Handle(SALOME_InteractiveObject) anIO = aList.First(); + myMeshActor = SMESH::FindActorByEntry( anIO->getEntry() ); + + QString aString; + int nbElems = SMESH::GetNameOfSelectedElements( selector(), anIO, aString ); + if ( nbElems == 1 ) + myDlg->myId->setText( aString ); + + } catch (...) { + } + + myNoPreview = false; + redisplayPreview(); +} + +//================================================================================ +/*! + * \brief update preview + */ +//================================================================================ + +void SMESHGUI_RemoveNodeReconnectionOp::redisplayPreview() +{ + if ( myNoPreview ) + return; + myNoPreview = true; + + if ( !myMeshActor ) + onSelectionDone(); + + SMESH::MeshPreviewStruct_var aMeshPreviewStruct; + + QString msg; + if ( myMeshActor && isValid( msg ) && myDlg->myPreviewChkBox->isChecked() ) + try { + SMESH::SMESH_Mesh_var aMesh = SMESH::GetMeshByIO( myMeshActor->getIO() ); + if ( !aMesh->_is_nil() ) + { + SMESH::SMESH_MeshEditor_var aPreviewer = aMesh->GetMeshEditPreviewer(); + if (!aPreviewer->_is_nil()) + { + int anId = myDlg->myId->text().toInt(); + aPreviewer->RemoveNodeWithReconnection( anId ); + aMeshPreviewStruct = aPreviewer->GetPreviewData(); + } + } + } + catch (...) { + } + + if (!mySimulation) + mySimulation = new SMESHGUI_MeshEditPreview(SMESH::GetViewWindow( mySMESHGUI )); + + // display data + if ( & aMeshPreviewStruct.in() ) + { + mySimulation->SetData( aMeshPreviewStruct.in() ); + } + else + { + mySimulation->SetVisibility( false ); + } + + myNoPreview = false; +} + +//================================================================================= +/*! + * \brief SLOT called when the viewer opened + */ +//================================================================================= + +void SMESHGUI_RemoveNodeReconnectionOp::onOpenView() +{ + if ( mySimulation ) + { + mySimulation->SetVisibility( false ); + SMESH::SetPointRepresentation( false ); + } + else + { + mySimulation = new SMESHGUI_MeshEditPreview(SMESH::GetViewWindow( mySMESHGUI )); + } +} + +//================================================================================= +/*! + * \brief SLOT called when the viewer closed + */ +//================================================================================= + +void SMESHGUI_RemoveNodeReconnectionOp::onCloseView() +{ + delete mySimulation; + mySimulation = 0; +} + +//================================================================================ +/*! + * \brief SLOT called when the node id is manually changed + */ +//================================================================================ + +void SMESHGUI_RemoveNodeReconnectionOp::onTextChange( const QString& theText ) +{ + if( myMeshActor ) + { + if( SMDS_Mesh* aMesh = myMeshActor->GetObject()->GetMesh() ) + { + Handle(SALOME_InteractiveObject) anIO = myMeshActor->getIO(); + SALOME_ListIO aList; + aList.Append( anIO ); + selectionMgr()->setSelectedObjects( aList, false ); + + if ( const SMDS_MeshNode* aNode = aMesh->FindNode( theText.toInt() )) + { + SVTK_TVtkIDsMap aListInd; + aListInd.Add( FromSmIdType( aNode->GetID()) ); + selector()->AddOrRemoveIndex( anIO, aListInd, false ); + if( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( SMESHGUI::GetSMESHGUI() ) ) + aViewWindow->highlight( anIO, true, true ); + } + } + } +} + +//================================================================================ +/*! + * \brief Activate Node selection + */ +//================================================================================ + +void SMESHGUI_RemoveNodeReconnectionOp::activateSelection() +{ + selectionMgr()->clearFilters(); + SMESH::SetPointRepresentation( true ); + //selectionMgr()->installFilter( myFilter ); + setSelectionMode( NodeSelection ); +} + +//================================================================================ +/*! + * \brief Destructor + */ +//================================================================================ + +SMESHGUI_RemoveNodeReconnectionOp::~SMESHGUI_RemoveNodeReconnectionOp() +{ + if ( myDlg ) delete myDlg; + if ( mySimulation ) delete mySimulation; + if ( myFilter ) delete myFilter; +} + +//================================================================================ +/*! + * \brief Gets dialog of this operation + * \retval LightApp_Dialog* - pointer to dialog of this operation + */ +//================================================================================ + +LightApp_Dialog* SMESHGUI_RemoveNodeReconnectionOp::dlg() const +{ + return myDlg; +} + diff --git a/src/SMESHGUI/SMESHGUI_RemoveNodeReconnectionDlg.h b/src/SMESHGUI/SMESHGUI_RemoveNodeReconnectionDlg.h new file mode 100644 index 000000000..9f5551952 --- /dev/null +++ b/src/SMESHGUI/SMESHGUI_RemoveNodeReconnectionDlg.h @@ -0,0 +1,110 @@ +// Copyright (C) 2007-2021 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, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +// File : SMESHGUI_RemoveNodeReconnectionDlg.h +// Author : Edward AGAPOV, Open CASCADE S.A.S. +// +#ifndef __SMESHGUI_RemoveNodeReconnection_HXX__ +#define __SMESHGUI_RemoveNodeReconnection_HXX__ + +#include "SMESHGUI_Dialog.h" +#include "SMESHGUI_SelectionOp.h" + +class QButtonGroup; +class QCheckBox; +class QGroupBox; +class QLineEdit; +class QPushButton; +class QRadioButton; +class SMESHGUI_SpinBox; +class SMESHGUI_MeshEditPreview; +class SMESHGUI_RemoveNodeReconnectionDlg; + +/*! + * \brief Remove a node with elements re-connection + */ +class SMESHGUI_EXPORT SMESHGUI_RemoveNodeReconnectionOp: public SMESHGUI_SelectionOp +{ + Q_OBJECT + +public: + SMESHGUI_RemoveNodeReconnectionOp(); + virtual ~SMESHGUI_RemoveNodeReconnectionOp(); + + virtual LightApp_Dialog* dlg() const; + +protected: + + virtual void startOperation(); + virtual void stopOperation(); + + virtual void activateSelection(); + + bool isValid( QString& ); + +protected slots: + virtual bool onApply(); + +private slots: + void onSelectionDone(); + void redisplayPreview(); + void onTextChange( const QString& ); + void onOpenView(); + void onCloseView(); + +private: + + SMESHGUI_RemoveNodeReconnectionDlg* myDlg; + + SUIT_SelectionFilter* myFilter; + SMESHGUI* mySMESHGUI; + SMESHGUI_MeshEditPreview* mySimulation; + SMESH_Actor* myMeshActor; + bool myNoPreview; +}; + +/*! + * \brief Dialog to make a mesh pass through a point + */ + +class SMESHGUI_EXPORT SMESHGUI_RemoveNodeReconnectionDlg : public SMESHGUI_Dialog +{ + Q_OBJECT + +public: + SMESHGUI_RemoveNodeReconnectionDlg(); + +private: + QWidget* createMainFrame( QWidget* ); + + QWidget* myMainFrame; + QGroupBox* myNodeToMoveGrp; + QLineEdit* myId; + QCheckBox* myPreviewChkBox; + + QString myHelpFileName; + + friend class SMESHGUI_RemoveNodeReconnectionOp; + +}; + +#endif // SMESHGUI_RemoveNodeReconnectionDLG_H diff --git a/src/SMESHGUI/SMESH_images.ts b/src/SMESHGUI/SMESH_images.ts index 676c0aad8..ee189aa91 100644 --- a/src/SMESHGUI/SMESH_images.ts +++ b/src/SMESHGUI/SMESH_images.ts @@ -195,6 +195,18 @@ ICON_DLG_MOVE_WITHOUT_NODE mesh_move_without_node.png + + ICON_DLG_MOVE_NODE_INTERACTIVE + mesh_move_node_interactive.png + + + ICON_SPLIT_DIAG_INTERACTIVE + mesh_split_diag_interactive.png + + + ICON_SPLIT_FACE_INTERACTIVE + mesh_split_face_interactive.png + ICON_DLG_NODE mesh_vertex.png @@ -279,6 +291,10 @@ ICON_DLG_REM_NODE mesh_rem_node.png + + ICON_REM_NODE_RECON + mesh_rem_node_recon.png + ICON_DLG_REM_ORPHAN_NODES mesh_rem_orphan_nodes.png diff --git a/src/SMESHGUI/SMESH_msg_en.ts b/src/SMESHGUI/SMESH_msg_en.ts index 871b155b0..7c52712ec 100644 --- a/src/SMESHGUI/SMESH_msg_en.ts +++ b/src/SMESHGUI/SMESH_msg_en.ts @@ -888,6 +888,18 @@ MEN_MESH_THROU_POINT Move Node + + MEN_MOVE_NODE_INTRCT + Move node by mouse + + + MEN_SPLIT_DIAG_INTRC + Add node on segment + + + MEN_SPLIT_FACE_INTRC + Add node to triangle + MEN_MIN_ANG Minimum Angle @@ -1080,6 +1092,10 @@ MEN_REMOVE_NODES Nodes + + MEN_REMOVE_NODE_RECON + Node with reconnection + MEN_REMOVE_ORPHAN_NODES Orphan Nodes @@ -3612,6 +3628,18 @@ Use Display Entity menu command to show them. STB_MESH_THROU_POINT Move Node + + STB_MOVE_NODE_INTRCT + Move Node by mouse + + + STB_SPLIT_DIAG_INTRC + Add node on segment + + + STB_SPLIT_FACE_INTRC + Add node to triangle + STB_MIN_ANG Minimum Angle @@ -3700,6 +3728,10 @@ Use Display Entity menu command to show them. STB_REMOVE_NODES Remove nodes + + STB_REMOVE_NODE_RECON + Remove node with reconnection + STB_REMOVE_ORPHAN_NODES Remove orphan nodes @@ -3896,6 +3928,10 @@ Use Display Entity menu command to show them. TB_RENUMBER Renumbering Toolbar + + TB_INTERACT + Interactive modifications Toolbar + TB_TRANSFORM Transformation Toolbar @@ -4308,6 +4344,18 @@ Use Display Entity menu command to show them. TOP_MESH_THROU_POINT Move Node + + TOP_MOVE_NODE_INTRCT + Move node by mouse + + + TOP_SPLIT_DIAG_INTRC + Add node on segment + + + TOP_SPLIT_FACE_INTRC + Add node to triangle + TOP_MIN_ANG Minimum Angle @@ -4396,6 +4444,10 @@ Use Display Entity menu command to show them. TOP_REMOVE_NODES Remove nodes + + TOP_REMOVE_NODE_RECON + Remove node with reconnection + TOP_REMOVE_ORPHAN_NODES Remove orphan nodes @@ -6713,6 +6765,10 @@ Please specify them and try again DESTINATION Destination + + DESTINATION_BY_MOUSE + Destination by mouse click + MOVE_NODE Move node @@ -6741,6 +6797,120 @@ Please specify them and try again Mesh to modify not selected + + SMESHGUI_AddNodeOnSegmentDlg + + CAPTION + Add node to segment + + + SEGMENT_GROUP + Edge between neighboring triangles + + + SEGMENT + Edge + + + POSITION_GROUP + Node on Edge + + + POSITION + Location by mouse click + + + + SMESHGUI_AddNodeOnSegmentOp + + INVALID_EDGE + Edge is invalid + + + INVALID_MESH + Mesh to modify not selected + + + NO_ELEMENTS + Edge belongs to none face + + + VOLUME_FOUND + Can't split an edge of a volume + + + NOT_TRIANGLE_FACE_FOUND + Operation applies to triangles only + + + BAD_POSITION + Position on edge is incorrect + + + + SMESHGUI_AddNodeOnFaceDlg + + CAPTION + Add node to triangle + + + FACE_GROUP + Triangle to split + + + FACE_ID + ID + + + XYZ_GROUP + Node location by mouse click + + + XYZ_NODE_ON_FACE + Node on face + + + + SMESHGUI_AddNodeOnFaceOp + + INVALID_MESH + Mesh to modify not selected + + + NOT_FACE + Not a face selected + + + INVALID_ID + Face ID is invalid + + + + SMESHGUI_RemoveNodeReconnectionDlg + + CAPTION + Remove Node with Reconnection + + + NODE_2REMOVE_ID + ID + + + NODE_2REMOVE + Node + + + + SMESHGUI_RemoveNodeReconnectionOp + + INVALID_ID + Node ID is invalid + + + INVALID_MESH + Mesh to modify not selected + + SMESHGUI_FindElemByPointDlg diff --git a/src/SMESHUtils/SMESH_MeshAlgos.cxx b/src/SMESHUtils/SMESH_MeshAlgos.cxx index 9f0c88e20..9bc76d69d 100644 --- a/src/SMESHUtils/SMESH_MeshAlgos.cxx +++ b/src/SMESHUtils/SMESH_MeshAlgos.cxx @@ -2252,6 +2252,56 @@ std::vector< const SMDS_MeshNode*> SMESH_MeshAlgos::GetCommonNodes(const SMDS_Me return common; } +//================================================================================ +/*! + * \brief Return true if a node is on a boundary of 2D mesh. + * Optionally returns two neighboring boundary nodes (or more in non-manifold mesh) + */ +//================================================================================ + +bool SMESH_MeshAlgos::IsOn2DBoundary( const SMDS_MeshNode* theNode, + std::vector< const SMDS_MeshNode*> * theNeibors ) +{ + typedef NCollection_DataMap< SMESH_TLink, int, SMESH_TLink > TLinkCountMap; + TLinkCountMap linkCountMap( 10 ); + + int nbFreeLinks = 0; + for ( SMDS_ElemIteratorPtr fIt = theNode->GetInverseElementIterator(SMDSAbs_Face); fIt->more(); ) + { + const SMDS_MeshElement* face = fIt->next(); + const int nbCorners = face->NbCornerNodes(); + + int iN = face->GetNodeIndex( theNode ); + int iPrev = ( iN - 1 + nbCorners ) % nbCorners; + int iNext = ( iN + 1 ) % nbCorners; + + for ( int i : { iPrev, iNext } ) + { + SMESH_TLink link( theNode, face->GetNode( i )); + int* count = linkCountMap.ChangeSeek( link ); + if ( count ) ++( *count ); + else linkCountMap.Bind( link, 1 ); + + if ( !count ) ++nbFreeLinks; + else --nbFreeLinks; + } + } + + if ( theNeibors ) + { + theNeibors->clear(); + theNeibors->reserve( nbFreeLinks ); + for ( TLinkCountMap::Iterator linkIt( linkCountMap ); linkIt.More(); linkIt.Next() ) + if ( linkIt.Value() == 1 ) + { + theNeibors->push_back( linkIt.Key().node1() ); + if ( theNeibors->back() == theNode ) + theNeibors->back() = linkIt.Key().node2(); + } + } + return nbFreeLinks > 0; +} + //================================================================================ /*! * \brief Return true if node1 encounters first in the face and node2, after diff --git a/src/SMESHUtils/SMESH_MeshAlgos.hxx b/src/SMESHUtils/SMESH_MeshAlgos.hxx index 5c5df659b..36bbeeb45 100644 --- a/src/SMESHUtils/SMESH_MeshAlgos.hxx +++ b/src/SMESHUtils/SMESH_MeshAlgos.hxx @@ -199,6 +199,12 @@ namespace SMESH_MeshAlgos SMESHUtils_EXPORT std::vector< const SMDS_MeshNode*> GetCommonNodes(const SMDS_MeshElement* e1, const SMDS_MeshElement* e2); + /*! + * \brief Return true if a node is on a boundary of 2D mesh. + * Optionally returns two neighboring boundary nodes (or more in non-manifold mesh) + */ + SMESHUtils_EXPORT bool IsOn2DBoundary( const SMDS_MeshNode* node, + std::vector< const SMDS_MeshNode*> * neibors = nullptr ); /*! * \brief Return true if node1 encounters first in the face and node2, after. * The nodes are supposed to be neighbor nodes in the face. @@ -225,6 +231,7 @@ namespace SMESH_MeshAlgos /*! * \brief Mark elements given by SMDS_Iterator + * \sa SMDS_Mesh::SetAllNodesNotMarked() and SMDS_Mesh::SetAllCellsNotMarked() */ template< class ElemIter > void MarkElems( ElemIter it, const bool isMarked ) diff --git a/src/SMESH_I/SMESH_2smeshpy.cxx b/src/SMESH_I/SMESH_2smeshpy.cxx index f69c70eef..67150c6e4 100644 --- a/src/SMESH_I/SMESH_2smeshpy.cxx +++ b/src/SMESH_I/SMESH_2smeshpy.cxx @@ -2491,10 +2491,10 @@ void _pyMeshEditor::Process( const Handle(_pyCommand)& theCommand) static TStringSet sameMethods; if ( sameMethods.empty() ) { const char * names[] = { - "RemoveElements","RemoveNodes","RemoveOrphanNodes", + "RemoveElements","RemoveNodes","RemoveOrphanNodes","RemoveNodeWithReconnection", "AddNode","Add0DElement","AddEdge","AddFace","AddPolygonalFace","AddBall", - "AddVolume","AddPolyhedralVolume","AddPolyhedralVolumeByFaces", - "MoveNode", "MoveClosestNodeToPoint","InverseDiag","DeleteDiag", + "AddVolume","AddPolyhedralVolume","AddPolyhedralVolumeByFaces","AddNodeOnSegment", + "MoveNode", "MoveClosestNodeToPoint","InverseDiag","DeleteDiag","AddNodeOnFace", "Reorient","ReorientObject","Reorient2DBy3D","Reorient2DByNeighbours", "TriToQuad","TriToQuadObject", "QuadTo4Tri", "SplitQuad","SplitQuadObject", "BestSplit","Smooth","SmoothObject","SmoothParametric","SmoothParametricObject", diff --git a/src/SMESH_I/SMESH_MeshEditor_i.cxx b/src/SMESH_I/SMESH_MeshEditor_i.cxx index 323a6603a..9efa484ff 100644 --- a/src/SMESH_I/SMESH_MeshEditor_i.cxx +++ b/src/SMESH_I/SMESH_MeshEditor_i.cxx @@ -834,7 +834,7 @@ CORBA::Boolean SMESH_MeshEditor_i::RemoveNodes(const SMESH::smIdType_array & IDs //============================================================================= /*! - * + * Remove orphan nodes */ //============================================================================= @@ -865,6 +865,58 @@ SMESH::smIdType SMESH_MeshEditor_i::RemoveOrphanNodes() return 0; } +//============================================================================= +/*! + * Remove a node and fill a hole appeared by changing surrounding faces + */ +//============================================================================= + +void SMESH_MeshEditor_i::RemoveNodeWithReconnection( SMESH::smIdType nodeID ) +{ + SMESH_TRY; + initData(); + + const SMDS_MeshNode * node = getMeshDS()->FindNode( nodeID ); + if ( ! node ) + THROW_SALOME_CORBA_EXCEPTION( SMESH_Comment( "Invalid node ID ") << nodeID, + SALOME::BAD_PARAM); + if ( node->NbInverseElements( SMDSAbs_Volume ) > 0 ) + THROW_SALOME_CORBA_EXCEPTION( "RemoveNodeWithReconnection() applies to 2D mesh only", + SALOME::BAD_PARAM); + + if ( myIsPreviewMode ) // make preview data + { + // in a preview mesh, make edges linked to a node + TPreviewMesh& tmpMesh = *getPreviewMesh( SMDSAbs_Edge ); + TIDSortedElemSet linkedNodes; + ::SMESH_MeshEditor::GetLinkedNodes( node, linkedNodes ); + SMDS_MeshNode *nodeCpy1 = tmpMesh.Copy( node ); + for ( const SMDS_MeshElement* n : linkedNodes ) + { + SMDS_MeshNode *nodeCpy2 = tmpMesh.Copy ( cast2Node( n )); + tmpMesh.GetMeshDS()->AddEdge( nodeCpy1, nodeCpy2 ); + } + // copy surrounding faces + for ( SMDS_ElemIteratorPtr fIt = node->GetInverseElementIterator( SMDSAbs_Face ); fIt->more(); ) + tmpMesh.Copy ( fIt->next() ); + + // remove copied node + if ( nodeCpy1 ) + getEditor().RemoveNodeWithReconnection( nodeCpy1 ); + } + else + { + getEditor().RemoveNodeWithReconnection( node ); + + // Update Python script + TPythonDump() << this << ".RemoveNodeWithReconnection( " << nodeID << " )"; + + declareMeshModified( /*isReComputeSafe=*/ true ); + } + + SMESH_CATCH( SMESH::throwCorbaException ); +} + //============================================================================= /*! * Add a new node. @@ -1567,6 +1619,121 @@ CORBA::Boolean SMESH_MeshEditor_i::DeleteDiag(SMESH::smIdType NodeID1, return 0; } +//============================================================================= +/*! + * \brief Split a diagonal of a quadrangle formed by two adjacent triangles + * so that four new triangles appear in place of the two triangles + */ +//============================================================================= + +void SMESH_MeshEditor_i::AddNodeOnSegment(SMESH::smIdType nodeID1, + SMESH::smIdType nodeID2, + CORBA::Double position) +{ + SMESH_TRY; + initData(); + + const SMDS_MeshNode * n1 = getMeshDS()->FindNode( nodeID1 ); + const SMDS_MeshNode * n2 = getMeshDS()->FindNode( nodeID2 ); + if ( !n1 ) + THROW_SALOME_CORBA_EXCEPTION( SMESH_Comment( "Invalid node ID: ") << nodeID1, + SALOME::BAD_PARAM); + if ( !n2 ) + THROW_SALOME_CORBA_EXCEPTION( SMESH_Comment( "Invalid node ID: ") << nodeID2, + SALOME::BAD_PARAM); + + if ( myIsPreviewMode ) // make preview data + { + TPreviewMesh* tmpMesh = getPreviewMesh(); + TIDSortedElemSet elemSet, avoidSet; + TopoDS_Shape shape; + while ( const SMDS_MeshElement* face = SMESH_MeshAlgos::FindFaceInSet( n1, n2, + elemSet, avoidSet )) + { + if ( avoidSet.empty() ) + { + shape = getMeshDS()->IndexToShape( face->GetShapeID() ); + if ( !shape.IsNull() ) + { + tmpMesh->ShapeToMesh( TopoDS_Shape() ); + tmpMesh->ShapeToMesh( shape ); + } + } + SMDS_MeshElement* faceCopy = tmpMesh->Copy ( face ); + avoidSet.insert( face ); + + if ( !shape.IsNull() ) + tmpMesh->GetMeshDS()->SetMeshElementOnShape( faceCopy, shape ); + } + n1 = tmpMesh->GetMeshDS()->FindNode( nodeID1 ); + n2 = tmpMesh->GetMeshDS()->FindNode( nodeID2 ); + + if ( !shape.IsNull() ) + { + tmpMesh->GetMeshDS()->SetMeshElementOnShape( n1, shape ); + tmpMesh->GetMeshDS()->SetMeshElementOnShape( n2, shape ); + } + } + + getEditor().SplitEdge( n1, n2, position ); + + if ( !myIsPreviewMode ) + { + // Update Python script + TPythonDump() << this << ".AddNodeOnSegment( " + << nodeID1 << ", " << nodeID2 << ", " << position << " )"; + + declareMeshModified( /*isReComputeSafe=*/true ); + } + + SMESH_CATCH( SMESH::throwCorbaException ); +} + +//============================================================================= +/*! + * \brief Split a face into triangles by adding a new node onto the face + * and connecting the new node with face nodes + */ +//============================================================================= + +void SMESH_MeshEditor_i::AddNodeOnFace(SMESH::smIdType theFaceID, + CORBA::Double theX, + CORBA::Double theY, + CORBA::Double theZ) +{ + SMESH_TRY; + initData(); + + const SMDS_MeshElement * face = getMeshDS()->FindElement( theFaceID ); + if ( !face ) + THROW_SALOME_CORBA_EXCEPTION( SMESH_Comment( "Invalid face ID: ") << theFaceID, + SALOME::BAD_PARAM); + if ( face->GetType() != SMDSAbs_Face ) + THROW_SALOME_CORBA_EXCEPTION( "The element is not a face ", SALOME::BAD_PARAM ); + + if ( myIsPreviewMode ) // make preview data + { + TPreviewMesh* tmpMesh = getPreviewMesh(); + face = tmpMesh->Copy ( face ); + } + + getEditor().SplitFace( face, theX, theY, theZ ); + + if ( !myIsPreviewMode ) + { + // Update Python script + TPythonDump() << this << ".AddNodeOnFace( " + << theFaceID << ", " + << theX << ", " + << theY << ", " + << theZ << " )"; + + declareMeshModified( /*isReComputeSafe=*/true ); + } + + SMESH_CATCH( SMESH::throwCorbaException ); +} + //============================================================================= /*! * @@ -2065,8 +2232,8 @@ CORBA::Boolean SMESH_MeshEditor_i::SplitQuadObject (SMESH::SMESH_IDSource_ptr th */ //============================================================================= -CORBA::Long SMESH_MeshEditor_i::BestSplit (CORBA::Long IDOfQuad, - SMESH::NumericalFunctor_ptr Criterion) +CORBA::Short SMESH_MeshEditor_i::BestSplit (SMESH::smIdType IDOfQuad, + SMESH::NumericalFunctor_ptr Criterion) { SMESH_TRY; initData(); @@ -4489,7 +4656,6 @@ CORBA::Boolean SMESH_MeshEditor_i::MoveNode(SMESH::smIdType NodeID, // move copied node if ( nodeCpy1 ) tmpMesh.GetMeshDS()->MoveNode(nodeCpy1, x, y, z); - // fill preview data } else if ( theNodeSearcher ) // move node and update theNodeSearcher data accordingly theNodeSearcher->MoveNode(node, gp_Pnt( x,y,z )); diff --git a/src/SMESH_I/SMESH_MeshEditor_i.hxx b/src/SMESH_I/SMESH_MeshEditor_i.hxx index 3d7072ed4..58c55686b 100644 --- a/src/SMESH_I/SMESH_MeshEditor_i.hxx +++ b/src/SMESH_I/SMESH_MeshEditor_i.hxx @@ -100,9 +100,10 @@ public: */ std::string GenerateGroupName(const std::string& thePrefix); - CORBA::Boolean RemoveElements(const SMESH::smIdType_array & IDsOfElements); - CORBA::Boolean RemoveNodes (const SMESH::smIdType_array & IDsOfNodes); - SMESH::smIdType RemoveOrphanNodes(); + CORBA::Boolean RemoveElements(const SMESH::smIdType_array & IDsOfElements); + CORBA::Boolean RemoveNodes (const SMESH::smIdType_array & IDsOfNodes); + SMESH::smIdType RemoveOrphanNodes(); + void RemoveNodeWithReconnection(SMESH::smIdType nodeID); /*! * Methods for creation new elements. @@ -170,15 +171,42 @@ public: */ void SetMeshElementOnShape(SMESH::smIdType ElementID, CORBA::Long ShapeID); - + /*! + * \brief Change node location + */ CORBA::Boolean MoveNode(SMESH::smIdType NodeID, CORBA::Double x, CORBA::Double y, CORBA::Double z); + /*! + * \brief Swap a diagonal of a quadrangle formed by two adjacent triangles + */ CORBA::Boolean InverseDiag(SMESH::smIdType NodeID1, SMESH::smIdType NodeID2); + /*! + * \brief Delete a diagonal of a quadrangle formed by two adjacent triangles + * so that a new quadrangle appears in place of the triangles + */ CORBA::Boolean DeleteDiag(SMESH::smIdType NodeID1, SMESH::smIdType NodeID2); + /*! + * \brief Split a diagonal of a quadrangle formed by two adjacent triangles + * so that four new triangles appear in place of the two triangles + */ + void AddNodeOnSegment(SMESH::smIdType segmentNode1, SMESH::smIdType segmentNode2, + CORBA::Double position); + /*! + * \brief Split a face into triangles by adding a new node onto the face + * and connecting the new node with face nodes + */ + void AddNodeOnFace(SMESH::smIdType triangle, + CORBA::Double x, CORBA::Double y, CORBA::Double z); + + /*! + * \brief Change orientation of cells + */ CORBA::Boolean Reorient(const SMESH::smIdType_array & IDsOfElements); + /*! + * \brief Change orientation of cells + */ CORBA::Boolean ReorientObject(SMESH::SMESH_IDSource_ptr theObject); - /*! * \brief Reorient faces contained in \a the2Dgroup. * \param the2Dgroup - the mesh or its part to reorient @@ -231,7 +259,7 @@ public: CORBA::Boolean Diag13); CORBA::Boolean SplitQuadObject (SMESH::SMESH_IDSource_ptr theObject, CORBA::Boolean Diag13); - CORBA::Long BestSplit (CORBA::Long IDOfQuad, + CORBA::Short BestSplit (SMESH::smIdType IDOfQuad, SMESH::NumericalFunctor_ptr Criterion); void SplitVolumesIntoTetra(SMESH::SMESH_IDSource_ptr elems, CORBA::Short methodFlags); diff --git a/src/SMESH_SWIG/smeshBuilder.py b/src/SMESH_SWIG/smeshBuilder.py index 1d5269c19..80f2c6d21 100644 --- a/src/SMESH_SWIG/smeshBuilder.py +++ b/src/SMESH_SWIG/smeshBuilder.py @@ -4098,6 +4098,16 @@ class Mesh(metaclass = MeshMeta): return self.editor.RemoveNodes(IDsOfNodes) + def RemoveNodeWithReconnection(self, nodeID ): + """ + Remove a node along with changing surrounding faces to cover a hole. + + Parameters: + nodeID: ID of node to remove + """ + + return self.editor.RemoveNodeWithReconnection( nodeID ) + def RemoveOrphanNodes(self): """ Remove all orphan (free) nodes from mesh @@ -4591,6 +4601,30 @@ class Mesh(metaclass = MeshMeta): return self.editor.DeleteDiag(NodeID1, NodeID2) + def AddNodeOnSegment(self, Node1, Node2, position = 0.5): + """ + Replace each triangle bound by Node1-Node2 segment with + two triangles by connecting a node made on the link with a node + opposite to the link. + + Parameters: + Node1: ID of the first node + Node2: ID of the second node + position: location [0,1] of the new node on the segment + """ + return self.editor.AddNodeOnSegment(Node1, Node2, position) + + def AddNodeOnFace(self, face, x, y, z): + """ + Split a face into triangles by adding a new node onto the face + and connecting the new node with face nodes + + Parameters: + face: ID of the face + x,y,z: coordinates of the new node + """ + return self.editor.AddNodeOnFace(face, x, y, z) + def Reorient(self, IDsOfElements=None): """ Reorient elements by ids -- 2.30.2