From 0b67c2b63e6abfd764031232f80dc3fe26231a9e Mon Sep 17 00:00:00 2001 From: eap Date: Tue, 20 Dec 2016 15:43:13 +0300 Subject: [PATCH] IMP23371: [CEA 1441] Define the faces where we impose the boundary layer from the dialog box of MG-Hybrid --- .../images/hybrid_hypothesis_advanced.png | Bin 23768 -> 24804 bytes .../images/hybrid_hypothesis_arguments.png | Bin 33522 -> 34492 bytes .../images/hybrid_hypothesis_faces.png | Bin 0 -> 15015 bytes .../images/hybrid_hypothesis_layers.png | Bin 18008 -> 18972 bytes .../gui/HYBRIDPLUGIN/input/hybrid_hypo.doc | 16 +- idl/HYBRIDPlugin_Algorithm.idl | 5 + src/GUI/HYBRIDPluginGUI_Enums.h | 4 +- src/GUI/HYBRIDPluginGUI_HypothesisCreator.cxx | 330 ++- src/GUI/HYBRIDPluginGUI_HypothesisCreator.h | 17 +- src/GUI/HYBRIDPlugin_msg_en.ts | 8 + src/HYBRIDPlugin/HYBRIDPluginBuilder.py | 23 + src/HYBRIDPlugin/HYBRIDPlugin_HYBRID.cxx | 1854 +---------------- src/HYBRIDPlugin/HYBRIDPlugin_HYBRID_i.cxx | 4 - src/HYBRIDPlugin/HYBRIDPlugin_Hypothesis.cxx | 238 +-- src/HYBRIDPlugin/HYBRIDPlugin_Hypothesis.hxx | 65 +- .../HYBRIDPlugin_Hypothesis_i.cxx | 64 +- .../HYBRIDPlugin_Hypothesis_i.hxx | 5 + src/HYBRIDPlugin/HYBRIDPlugin_i.cxx | 2 - 18 files changed, 510 insertions(+), 2125 deletions(-) create mode 100644 doc/salome/gui/HYBRIDPLUGIN/images/hybrid_hypothesis_faces.png diff --git a/doc/salome/gui/HYBRIDPLUGIN/images/hybrid_hypothesis_advanced.png b/doc/salome/gui/HYBRIDPLUGIN/images/hybrid_hypothesis_advanced.png index 956ade5406a004c9be2fbf6ecd0d63f44e2b9172..0891faaa49efc415eef516242f7d2288d423f123 100644 GIT binary patch literal 24804 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 literal 23768 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 N{5{Nzsv)pJGs(+aQE7V-EkmEs( zzb8*n1YM0V${hi@uMN|3eX4kvf!9AbPkz(b=kgxQQjZzNdMpp)3!BjgKr_D3X;cv8 z&g-`+Z;g1Cz?8ETQ1|KcXZ7r4SXkH!lXbbjfBzcKRIT&RA=aY!5YENtGJMSkXX@%2 z5S5ljR8>`dX?-SR0#=FG)k!f!Uw^;auBo|sZmkf*0uNqCXQlB7?F*e+^bDU9krq=S z?~4}zyxra1b#d6(>~5AVJPUt+y0Nm-8Jf&#fywW_SKvlTn;nsfi{A286~!UYi75)8 zf*QLy!kL+wt?@!U2z9;MOJ^4sobgw(ww#==5PM^&LLJaVQU%>mIZd+9NpGWhyi7W- z96w(8lhxTTKwCTgP4Z++hZcR0>{dd-4QuP_TH6WGF_I!-QhszmYr`$4?H&yKK#h!S zy@bl~w)h-jHUJTW(R@ zsbMGat?87orf<a)s#Mv7R-8XxcrZnX=I=FdZ7f47zWnwuj7j0pwEQ3i}oAZgV^=A(T+ z2cZ#Ms$YxW;&tg&*1VRwF#Yh$Chj>tVp!1$2M?#jP;irz=c-M2tp+r)-d_X_6VvUC z(g>RHcI^gZYq&Mda9?El5&O$vGz=u%#)9mUTeRnQWf><3TR|bg3d<2#iBL60)LN_d z=7w%Y5h(+3+o{@d*aq+@yXXsd5rr4QIRB=JAt3%a82@rnP@ z0Z{nt&aD-yKDjdxl!Lar2L{lU6H%`w>v&w5b=hIERSVT(sD=RP4R2R&v#2zw?Yzt( z-7-r2j^kO>z1ARxa)4^#&(R>Q;elU0!|j&c@L_V@pj8OPqLl1?6wZ>7R8OJccZ6KH zyOZupdz}1?hfBg~S`!>(TqGghfG*^DQ>OJ1U z_k1#ba@uUw;&K0CDc{$#f_hS?lXhOKz*w`dO0hCjRO5aO`J%PCO5C0>G z%Ye;MZSp*(1;Bt>h~>|47B)`e*Pt9aTRS`XJAp9uhNnAj06Um*xVU=eCS*y_(0UE_ zxY@9~cFDHPQSrGVC*k2PZ?CAtsC;4vxG^_A?H=8j?UkQ%+X|qV^MBrJ z**EJht1cSw11Qi5m%2}MGA4ifJ`E*G zV53v8YP`%*4Dk8NEprisWNi+X-;vcMxsHwwVnjp)-6z>DJ(ZM{l&#sC=S7;O5l@xi z!S|tn8Yhto(0%S`Xjq|l+iHEF>JptQ8~ zLw5Empb5qLjZ`!IANceQ3_xXp)zZ@PdAQyrAg91diSPKOsGxve_2UN(1Uv2#$qj7a zQRBUOW$x=?}fK!-8Q#clV5JPGk#BEzWm;P=sak;a=sb=^nDoTMbsIz*Gc`si)y zu{T#o1*z~@60UD*%2COYh6FtOq&D(H2ATEFoA4734l+P!!fVgqv?{ zZ1CcFpi&69ikgjcRr)wf(!=W3h~I4|9NEm^s?p|0xUH-)8DEs>$Tr6Zl(yM-6sqNS zH?EotORI_K>FJ#zqqN7`_~FjoAFYv|A#Y>q>CLGQnJa*P4TFe?2og|ST&$b@T2g%y z6*tr4;qbA-^%rh*-Q|*Z>~m4Z-vuHFubi(OUl>-wm$%Lm6l?j1vYSeWy8&F=QLb0J zyr$gqq^h0kvx4dlO5n~~G&#)k=g&dEMOvzd6tUhLOVz7o#1i)?avWU2Yaw35*`m9eSlw8;uo_#Doe4W$O)N$|1>8kdq z6G&+<=@@lOY!;jO5HToWJ+PFcGG40e<7-=)FqbXumU~F(>hh0{j*i@)+p`I3Nj<;A zxyq&recbyo=6dkj&6URq=H}B;LHq3oBeEoQwdEF(%ZgeG16Vv z?#$a$NiIQ<&7aV#q`X2vLxL1_Cmv$OVaE&Y6dJB6=g_YAG4t66*k1! z&OG>d<*f;s;*x#l^t= z!(wPuyH|PgDseVrVK1P@%#8W1c`*9$99_e6bipDXF?D8iyz1&| zDy7iczN{1D;3P5$Z-y7plGwq1PD~4qXHx>D zt<|fGANjr1Cca4zRkBJyohoBA9{yQ}BW!r-k{+g@ma7op_i$}7-{gU1+8Yzx(9mG$ zTclnXCOMWjRYicdkGk$~#e9UK{=O-z(JM zb-1A<7%)iZ#KUb=WsHmw=8Z9WPs6Ej#1U+19w~V*zc<~0cDlh902J$L%k9|vTdXiU zZlQcI<;yc&NT3{>Gz|#BzckTjc&O za+Wukz%TXd*N6u=#Ox0?5-q>o_SryrE24vzsM3o9>Jc><76OtWA*+5E$bP0MQ?23umlTxo1CntZgl=bYD9oX6Fc2e<$?n@)Phiov%EcQ)# zl1frTlr;56hdPqdl1JsXP&M=ORHHgSI6*i-0zO_h%qhe(O4I@u^=V~0 zuS~!*DW?Y1)DTor2?pdR)lE8`N0$~zgkqWMp1JC`d_`{1$4pTOnX9uW6bQ}ZLp$I( zwh963HF6(tx|7%8XDX9J?;(~uYe7`4kA!Z!lL(o&^(;53MOsTz`%WN`R!^npTyB7~ zjhN#v#huG4F+7ar0waj6GrHz)T+c>a@&upeSS@}kVQZWH>U7KKU-f)zIxDEBp4-0n zxD9}*Qy+cO{~da3x$01-M?XSx@|~>(ng3e^a+v=UmCJG%Vr69&79HI!aM&Caj79_t z5q`KbZRs6OEWlUtZ__?YmV3vXOOcWtA^)N~hRK}m(5%qwd9373((b3_!)`KA_Eo}m#Vr#KQpt;%b zPVr6(a2qtwUbhj%zOtJIF9;Cy{rc4&pWBZ;UR$b7gpD0Q@LY=)@az3wSlE)ZPft#a zfk6t~(T`0Z6-HC{ZStt(WRkwVK2bS2RO#r40)-w1Xz`{`8h=ft&$jA7ShN&C?g3Q- z_HIJ?p?*g&ntm;)M&&n%5+ZkRUa;-Y|0``IzdTlB{w&vgdC(LV@ip)s2{Xct6@%1x z6ZFM*SL}eIFPbbjXrlJHo`~PXrL$Xayhth|cAdZ>cz1?^4T+)UWxx`# zJ4*fpn)vYgguRymywJZv_wL5z?UCsp9#lShS5NA}moHz;DQ(WinSFR|d1u|WkU?Y0 zLBi=SjSep+`sOxfYk>!!X2FOp!6`hT%6o9CP>l@S05)*Xpl9yI=ot)cPZ=GCR9Cxx z&&|!b-CgK9867mxET?Mhc^1C$=bP#9GL0k9Zh*ee?!Wj$q$oQlpVoSZtNQ3PG$rK* zC1jd}Jxl~IwkO@ty8K(?@0$O}jssieFi>m?ifF5`JQ#>NH1W#Z5~11v>x~XT{v|i> zxcwgQv1}KrW`1#vXK%Q@k20TEF}2hh~u=l_SM*lX#JO84MOURCwu z%-+GqG?LJdrJo(NOtfA);JW{68MYVvHfu}Qi50IMOLkv8#Jyd)B@ps>|DRihjgqZ> zMp|0fs5|`R#Kgo!9y{_~{>V#*g~s4ovHjzTRR#hazg%@s|HMSlzE?VTbJUmt-&$W> z6h9199t8zuYhsfnij*7IRD{%Y%P~sxeM!%JV`7x%!^1j1c;`*!b+RNZK9xUW);$t6 zlmqtgZV9_mkd6-Su=!SaUZ@#+KKJ?R>gsusOUZ5&NhRmV@B&@E8k1FX`O#CN(HPg$FqBi4C{S zDJ?DYZ8hCwZN{A^!O$nm*4P!jJ3D2&*%t*9j-fycgSsyQdArt=<-vAt6Y*c`Bel;R ze9I2x=lndm#i~-4X((n`)Ym+hhw9H}^Q~@pk%R-ip!hOGw3tT{0yY+y7YSb3&qn1d zXPAs_7#(ko(3zPp$Vl+;Kz{xOqG`2t@YNX8%2d_5%PCL?j1Lc%K6%}K(f$Hx-#R4B zo{vY4XZvG%Yj>baaLQLQxv4G;i}HH4@t<<(Kq7b2cp*nSID2vq(Yn2__0 z+Z8Q!q2l);9?Q;O+nJCAYp>6&3b)(d+#G?4iHV+((PY2TE%|IFU%SbjLihT%6L4d| zPy}(jyK?e5pP+r>kN0Fu!Go2xOD!mnoz~VXP7J;v3phG@>3Tq3;`Z?9D+pdlB1A^n zj={;1j$CI_O8q(79og-Bw5}B?Uv2Oe+!NdqWk6ry*z(~NE)C5BNF+pTf>c1hXHC$C zAqB9bJqR&-NH5DezZfJfpZRA_ZnO+KZH@6)X8OF0z8BBR81;dC3(TX543wQqLsTMn z^@wu0s8rD;7!Bed&dGRy$+~>e6kpK~Vmw>TJaD~=Hs4(6JNKVd*{;f@k7d5X+)&&l zpBC6?Qtpl?P@5dv^Tp* zPH7-P`jg5i zo5?%)C2^ED-(K0JcUQZT1kTp7xX(`+`Vy!yDoeM)I1qVLsHwofz-U)GGdMdtSJ=*+ z#M{LYHeOtR49^hHQeSQHSdvm7$KMlitWemXr==Y;;{ZkDV`#LRe4vR%mnb$oe9d9l zqOSzb=)GHIX&FBxu7CZB!tIoap?-J6Rq7(G9NiJx8IofV8uQfDY0N+P`NhfQZY{Cl zLtbY3ivZu()hiolZ3>WYpQK>mC{;@54<=zB@ru6hAroSM>%%L4+s48eauWtzNx=E? zWI6?dHMX+Ssfr#Iof3BVFR=Gh{?9NVGRpp&mu9w2Ex&@!pHj;5(eF*-(Pt&E8;a?f z8A5NCfp$2gm&U``X?Cc3m#3tzsFQvy@;a+YmqK(&{gpf4CawT|RpHkEP9hX2yoqtD zgIA_ln`OTKHuTf7kq|fi3Je_|rgY(lZFA+ydNp}8|X@xFZ z9h#*MRcX>JMNO;gz{>G5ZiejkK$6PX0e2;Gg}ztcY%T!6Qk=AHBl$g-a%A*r_) z&3|x(SVN5U8Hotg{!&>nrUq9?)hc=#Mf=Mi-=7j?s+cNsIc$fvcwdIQJ$qJ&3}mqL zou-0PS+H7-`yN}+>ZGGbD%C7fVoTC;H0m z@Wg-Ya&H0}Yb48*X}tIlR^$;2AGDfUSnU(aCQ|f%{o0zy zXVWKZ%<;&mi}Sgyoh1iOpeI96x!Z0GxTzXmYXRQEg((jOJ13%XxS2yB;+Z`CzW{Yc z;E}o(9>H4z!qk#tnA9*m-Eu6C8w}{#E{fbi6%Foihwss3=6i(#sDrfrO zmdZ~umQu*r!UhdY2Mr4Yi4lu#SlBbQ@r{K3bzU-mQudJ%5G}a^nVQ~w_dXE_QiFd7h0j~~DX&kN#cwZziav@M zE&2bPBNnv8_B!{%)2p@bRu;Jr#MqsJg^+SzbZsX*{_N=?oteQ}K3E9{XXo{Q5JbeJ z3>;&61d`MdmSuE}$RoUig9EvsE3%4O&L_`vC@_!!dx)(3Ys9#=z_?UbI8dcP1u58_ zhin&KKSw{HOy_;S3J>Ij@zv9_6X}in+f~y-b?C(iVFshrrhCb5$wfVIcCjlNxG1F& zMvKH!2DfEUd7UA*Kc^6|PRlvEm~eN*H65EM10mU!c7rrI+3k?f6w0J@pU`%%qcekS zIfkgkYJ|I4|J6}vp63Au2K?i?K|4a2)gHvh?kpRqJSPdi&8F-9-~b1kuXX!RPoOD8 z^vM%=Yg+JRG4}bZ44h=h5}~n>xW{)HU%ns${k`Ljq?>l+(8KHoEU45qLPJA?1b_}&E*JVr8u*J36jBF0&on#_vSSm2ab*lZ zjrbM;g7@yBmnvDvf_1XYAkLSrqgcuFP^1tGDSk0J>$F2vM#=FO8fU}F; zb6C`N_U<_()6SUs3#(qplU8b&{qXM9UME(iN%xd?gEK)076tUn=K4l^Q3wIh>E8JY z%N%OY*4c!zwcVhC8fv}%?-r(#F@mMYVQ!0mvqCZdcn_25whMVO5cBczX;--x4%U9K zOSgNB&y~jk*iYAY#dqx0kxm+Dpgk4eyzU*(YrX_8^R>)FxnOjk49aJ_`I?h#T==^@ zw(yXFsOa_&a7e)JbnQ}%ztGecQ(eskz)+U=)rUW0e+%hF4rR zF{v`KpnewC?3d_N^19#g0tKm8CTBEOTAlFce#qCL&HWK(t={7*-=QG(CT@=u0Fr^BZj0`sWeI zaxG_kUP|(@VWMc~1vRnGZQ-6$4VItaVY%b*abRWLEe5H6f5rIr$G&Q2X3s}t=u~)U zu=xk)Ve5dvVeG<8w26tyUq{}K1$YPq8%AO5^IKy6#{~~4>oXNOE~HGa%JcCGF*smK zV4DvG|D6j?--_eb{EW+6p?A}VFwXpG&AV_Ah#)zp%(O#f*ohJ>$%#} z2}KwP{D)nS{j1w=4!R2;<)mC8&Q1E7JT%OCW7qdfT!p6lh>)hW8#@skiU5T%^c%iE zy49*9Z84MLHn7HDIsBO+0sLJ(Qx5W*ifB@2io@?1%>NiY6bbvfd`=yeCK2-5nMf>u zzjG%vWMnm&tx=P%RjGb?g&)y&GP^UelQNsjH`uj0uPl&c1Uq5U^$yZCa|1PB$1 zTru6Eh8~I+6ootU0-~T#9c{iws|KQ~Thj_6g@~Uxa3@ZL;dI^$mqQ=YqLF??`GiD2skCYXdrnge&bRBbcX0Hv%gZvsymmT@wr2m?RW2Y#+vF#xhyls$MJ<)uAY_Sc^r?)kGJ|F87$R&TYP_Mpu7OI zR@YmKPFJ_Ni^jE>73hl>XX7=NDSPjIfTunBYF#$B_Bv(iW_8tM;r*15^&G1rA0OP= ziVW4YEnP6~?<%ux&aWa4WnSjy&sbTN{#QF!8r4*?t&cdMg4njGErQS@PADMr6hILb zHG~<10wOZXAVU~}2@cI53MzsK7?3azA&NjCB%~D)B{CC+KtMqtB!(am#t?4NeeYWD zt#{vB>-~8D-k)0QoKx$ZT~(*{_tmcb6%q;43TyE_fn0jznX&uCGpzuTm=g+Rz|vgs z*d;AHSDKm&?!v}{7K6#fC$0J}7hf)BR+-UnRQfU;_ol%rfI5pPK!AwOoVOgK<|278 zd;|`wT=33Av2$m+WDYB=C$h?2XjQ86)NnT<)3B&Q3TJC=J&bg)w#G}z5!*rH3~c$Q zmK42}G}><)SflTzmc*!mDxy}`q4z%IY9sgK+!CxoZ znpF;7?e5_bPT;mH+JH>bspA)|eSJ%fgx5&uc~0H{#V{?uC?`5r$^4we_Q;me_;E7r zUrnF$`sOO9qMO_BFstLsz*XWn$XPfg|6?$3ac0c>ORxB7P|d8U43}=;SvBp^Jm;m`T#JiI@wlpke<#rpCuwSG5EiaPK>qu&NDBUv^l(1iLryM;mV74|i z_LKN+_`~}hR_L4vMgX${38YM&e>~WJaY=OZ*(g^|>a&`Vw5>2Peq7klINAfdHAIcS z8D4XCWezLE=*j;GrtJZSouq?+Pa>rS_CPSbG_-;T{IFIU&YS;#k5U%J0(t_Orm z4VU+7zNYnHi)Err;2Y2@iQnIZ&pXk&ox)bn=IjUAVnxOx?;6ppu`2ymZLw_Z-HMaU zkJrwKE4WO&ajLCiR&p`hz*a@axKn7KyE=SkIZC#Eiuss$gUb!C>nQO~N3T+OU@H!p z*J>qqo?3VX;9>y|H2T$DW6_J=L>#{eQya?ACt(AQb%4=>`UH7p+9@!Xmv#E=+o1R-{O$7rL&(W-X?Bue{@Ab-7!U#< z=Z1_s%^%5$3`1ZV##3A}VakZw!6+AIKfEw46(EWcdK)5!AW+4g!MePQNkbk)!W>H2=;{b{ zWKtg)$2a7uJZb&|A^ zk=^W^odvdz3wh2h=9}3M0Hf}Fy`$c}nsrL+)mmEmYR<0` z=vCx&r=rWq98Y_ljoLGvB}`7+J5_@JCQHv~&QkN`*(xB!yd&EEqMz6O`Pon*@~!gv z!LUc2MGPXrn(utqJvy={%l_*0d=%&V*AfZtAk5@xX&HqV%l;4{ZtHS{IP|E2{5yWV zB@)RZ*A65DEqqB!vI|b-a?QioOpaS2UN5@6D1)DL9ev`JHY<``yU)xP?R%Lbgm== zoL`5x{IKcO-?Rk~r@V#Dp!a&E)@}Z`rNsxV#HFM;UVlM=1+L>K@nNa|R^PFvvF7Bi zBj(=TJc9pL=+*8sz7VrEj0gxBicT#qoe3pHsl55i>LOOYgUrq9}2XUDhecnE66U2Rk+0)AJe4ci?)m zQfuZHDgmM-S^wG{ihqn~OVcR0UuNpH;|`>N2GmL&u2DR>j#(Y}%%95BCO9oS2wFe? ztR>KTsL0|D_x|{A4hJ9wN3&2!U2?CL^d0-s%h`!?`d$t3yEr{0;*j48 zb&|<`Hoa^pX#QNtndcl3K_;{D?3)zV7gjbGF1B)-NrN31RjIk8!KK=kmq!I%a{9?c z>`G7<-d%Zgw0RoM6LF3`zjv=*=Jw19pT1*AouQx-DS4yeqKm%CxfBZ0r@cI7NkDJU zHeJjVBqjGAF@KPdWXKg`jlYjZ6rwH^>xcZvB@KyUM^|JyVo;pLQ@{@ueVT@xqn!5c zWiiSy1_0XG0mRj28yytWRzUyUK1j{FXgm=1>v^XJ_0ce!F2WTZ4A{!&Fa_upe~v8z zcTmsGtul;1&UuC-6m{l*R@;`6EPXNQ!i9J{YwI6<+HDx;Bg&ngS-f^iL@;dmQU2P8 z*NAC-TzYxXXo-x`?dnVQZByUsD}zQaAXsxe15JkP5b<2~f2O9vN?tSCtGf1h)<@4XwTvkzW`A#gu%agQ}($?_{hK(@B z{0>Zai31|W6|nqpp24xH6KYVL>3L_H@Fi;PcC9jP7(lJ%Az z9x<7blM$F@9tj=Vr*3W>BNc_(b@A-ku+}O%mUaoI9vL2;G`;*8D4@EO4jw#WY`mIu zOZt-$Cc4<`C}sTys9hPq{t08}wNGMg#SEFyMl~XeG=v4wIL8z9YMP#NzJ9&cr*O5o zbY5sAH59y@PN@m5oT1`414>S{Lqi0;V2{Y?XAk+}(AO009kXN&8 zzEVLs_{p}i)l14`j|)ibUD9PrW_U^MBbmtKbn`mis|tcFPMaVG%263H3BRd~#G30_ znwd4GBzK*+DCp#ea=XhqpJbcDo*DV%+i|7kU_reckFKK@1vcOb<4LyglrvNa_a|LB zjKJo2G?z&(=$*7Eu%}gBphmiHtXQFP5y~nxgo6{nrPqjmvS8D{>Ms0#X02zzPf-^y ztG;p3r9Jgjd^QbI@B#DHr=#M*Rh86(v6A;6zx&1cgwe z&-=C5|K9bM^)cHRuU+eJ z$?t}sKkogImm@N;qVsnO%_^a7jm26*e z&}qH429VN+#@KQ>@W{0u-Udtz-E8u|E5$@g?E2{FV<%47{d_RY^hI=eq0MZRJ~Sxn z)!60rw-vnGl8acU;HY+P!{J`N1Fs<4Ti@ekG~;Ym?-~=WMt*nzl+d>hw@WtFwv4Ugx?r^MzBHS+y?18 z@ed!mzYr?go(l|olRIbB(^+P+vtT?7&0}EKBsl#lciH%Y0aRL4ykXuNUy^zcY!2oA`12v?K4z|$#gfDQNIy) z2$5NuP5aF!BBO+SpH{VWR8gazudSrippT`TZ#7yj&9}gD7~K-??n^)3!qRmD%JMBT z#)>iw-Q)G0I?ctmi)=vUOo2@SoIxNB;#KPwPDe!4$QWZOJ)-xl0_c|$?_mx~TK+%m znn=I5-K72psO4!rKJ%V(#o1E+ZrW~IgWa2LqsEaGuP^L&^wLB@N+*$MZDUhE_;I?p zDZ7$UAevh{2?h)wCrf-g=Y6yUh*dfFTf9_r7I1rdn(vEq0V>XS`Sn-9TaP>8>D-=q zCKk9F$G2muG6r*}%&jk7dej<~^MqRUWO5sHz@d7aHN3Nt`aHuqFmHU}-BoVmqy2dc z)w&6hw@S933P5hU%Pj2E%haSyg`h$n2<&NlunlPG6=L*KM?yz%c7D2E5)H8)JFRPo68LBk~=LC8EdBdc`n?R{q?ql55#9TK^{3eWJwa}vL}-gvERSN3QAUm zDKU~O(Ob7}J$^ITu85?)6e3*snXb*V0xCUoAZA_Sln`gz7Jgv_TDF|+V zq%aVXmBKf6p(A0DJ`)-jQFA|#L_e_2sTnyZi_;A}9UUFL#4EH)nN*dMXP>hp{bsYNP3s0YoI|R?fzgIk$ zJV34le`0Q3U!OCNybwP8$CjjAmjP^Scd2t8=+{_k^If5oW#O`BEkb_9zeyUNb<%V( zR;tJ@sQl2S-}rhK&dz1n;Gvb`J^M;rh8Axk44Ozq*Y_!TPY&pz+1Woq%n{dgRYlIg zk&QIQe3TS?;p721Bs@!0IJCl$rmf%br^XB{pO|Ni`VlV5W|EFCtr}DbUmMu;V);Q@h&# z<+-~UdLSX=FPc$4vYeqf=@jJ{_}Nd%T-?R!vd-i>9~?8k$uCj*dk@;+-e}y<)h%v? z%N51g_zy-~?d|^R*{d`Dh2v7n#wWIVByJuKxV!f`W@C-QYRNIugAc@WjkfLimh;|r zE7A`z(xt^~AYfKK#HmBbsZvSVL_zS<1)6?<7 zdty8^ABHnrgeS;&?EwIg{A6lpUjBk;ZZAfL@|RTrnx^jI6vgVq3lkb>#j*)(8_2}{ zg`&?Me#yVb|DWV7`c>HVtXffpogb)Dxa*BzU$|@gc=-bF1sojQOUd`5N^o$G1mWP|GoL>NXN1`& z--5$q2VqH-=itxtxlu59kND}mrUSTs0{n--o1pDv!@-fjNs0=oxTfyTxo9Yx-uyVS zMaRU1pIR(jexxWWMo=#?Q)e+(S~`6(F}=2pCNYO}VY6fARa)yc(>gxZI8$6-stOj0PPlMBN6=u4NI@`AJeXbp0uZZX$5=$WGu7kjV6|6Z!6z|#aT zj`+uqV277t>-7a=nz-cH6wz0aSD}eTGK%UDf-n)-y<8$Gj$y0PrV2_m>~)If1fLj` z1F~)OoNY7mgUuhs#iOvCELzZYdiE}9(m!%~1(n$;upo|gwZcY)q_RAwgf;SZ<$g>f z^rppEqTG7Jx#gUxE^2T2XN^W^+@~rJ59Pqe&*QmA2CVXZU22}Qim{-g2`Z1iI@o?0 zve3wCy7ITR0}4Nyv_wY5LZ?;kx*PbuT$c8xr_Sun&HIzWD-~tDF2-z8q=M?ts{>w4@pE=TA za-{y$-|5n3tj&X@(z3j+Q-7#j6OdM&Z|x+{n7*xZZG040He%n1L*N=7dyIxUCfk!( z4@FA1sc(9gNweG?k6&@?bcX4Z*4)`~<6;Nd?UijCcP+HBmsG`K#Uo%&$_ZpTnbK~l zJCcj&qK;(cnJ*Dq36Nl(OVnMzX2q6Q>r3Urh_|Fo*{&^G{%JYZLcO9Dr;Y09>9Wa< zFGpo!d3$PaKOl3{(_{AnwA9y%vrgNhK&hy5be>w`ckW$iV%X4GRM73M64TC}EUzxS zR2{FQ5JtH8kRtgRgX9H~@~$3%-nBZTXdW>o8_if%iV@Szm^2=zB5)?^Vudy5c>w z@^>5CLsC$$Tne!vPdt{_bD2&n?$SOa)A8HX(zS5->1bX+DaWa9zOEAZDsLMO*vx+J z;d=bTs?RPYYU*C@-2y>#5~=ve(QvLn>)yfRs^wqS)6W`5mYXmFHAZqCA> zp&B&4>PWZ2J^oo8W^#gyVegg4=pp@ppSF5K+U4qS^!fl+>$Sz(&!lX)=&z&(Yp`+g zmO8e+iCA&k`_izr2Wb>pO*>V$F zWEeDQe@oK3M#EICXn5bUPR3X4QEoiLK9I^8C|AI8`dP}lVV9V{taI|Tp0$op2d*B% z(Eb@cE70D7sjY55yAy{c{FzDA!OwUH&-)pTIp(knN?WN+SVHC%mcTMa?3+DMIEsgK7LiyqALadiOyuNcuh!PZ=OgC$JWiR!Zg9V1(HQybGo$`_oO$mC zTFQd{~`1LX=wEqa=;4X3AWQk|@Y)~XV(nA@XO z^{hi4tGU&9q4x@`Sn=A$pOp0<$<)hEEJuRtAGL%kwy27jjiJGbDJm3=Sxq-5Wlo=& z&*r}Em7f=K;{5r}C!uGUoPuI$YpwsxAF~Q-%dlSEz>J-<zC~e zK69_)mj@xq$NO@9oDPY~6#AlrvGxvLn#tOhe}f8+%;4UG`Nu2D^^2ScTU$lV`o~W- zn!lSQ<7?mxSieF@Cl_1q;xIm^G*j+Wy+CAekNIP8l**7S6K#1T`F8*F@+)5{!}T}j zCY9AJHQ|Z%#YD-rlN(>l((*XfJlZTyxtVqQW@?PhoY%v`zew8You1VSRR$>?J~{v^^K`@2l7p#0ABV}fFr{1ek2w-~OC7I~ z_lZFQlw)tdxK;9eqBZx<~PVtWq^|M063cRIkKP(vT3?eA3)b@f)^toV20eH zma6r(`gwd}P<<;hRWjl8F~U}&Fjn43>9O^Xj5F_PGtf+f=i{ntQmoK<5{mgY#@wq^ zt~aUPVfJcc*5=^coK-9>SeLo8*2A~5XQ(4+MiTMXY1Oyi8iY78KF{>GkswIN6b~QP zNg!ZK)GX!Cg7?`pV-&r2h#9|973?e z$YLqomY#P9gR;NzWGm3kLiuhQ=H~ZgalMf5?b@-Fhy{8o1^@t$sGd+ zYgqQ5?uy4|Ll*+&n>WPv#XPXjf^}lwApXfd@cD3kx+RmrpSFm{=8!G@uaDLqQ4 zRWg&quDqp`{^v@;1$g95o*!RFze(E+t9^d$^?=|tPbgS7jzErx4jL@ldL)zh1N}g7 za328~ap-hwM3d#5+IMNNdUaz!^*!(DyA86}e|w%!MPz+Yp_2tZduE%z%`#0`!^%v5*#DV*#qT9r5?-~91>gT z>}ZlI?y6`M+mi~J3^xTnplu9vzT*1yPSLPSA=|&Ilf8@qw{5oOeKeV)*+k^Y2BQYy z;M7#o)3Y5W`$@F>i<7~rP+b_~xe5|lSG{k@YB+!kjjmZW?Vrr4-c|cN7dG&j^i|KT zH;LsSda)`?-1(kf-ijq;WXJEK2v@7aV8);`wBm3F!hD)FW^v_oW02434YOYz z`G8k5y(#aINfZ0o$2 zoU#On0vZ|WlqVwHopI43p1i=8ab!d92RDj6^u*YlH$Q)>CgHFRSn)A3GR|+GQ?7K$ z8=Z%no7}wBs-}it>pj_@d4TTda&K77{+;GL>{Np0uw}9#r?WPoS~$1d?Ikpho>m>z zIn#4`pRv1Nr8b}A!Qt+BkdQ@JPXcq)LP+s1i``= zCe2_foNjR2dqoL}WLE1hQhCDN-GwjUu`;P&_}n)HU4~)1Wm#!@1i_w&i3cv8Ys-*{ z&6ibBp}}n7r!u6$#DuF!e)@8|>f@a|T$x_eKt~YjdpWsUORFo@5OfM^z3({Q-rl}_ z>O!OkGbe+me6O=fT-P5{?^PzoBqtmG#N;k20zeWS-NxZ;+6hxkUSaIRs0CJ`%6TM% zk0R!&d%%g^M!owTH}!8%tjEW#d=E17hCcfG9unmKvXxG#UvKx&`U3Qt z$+S)ZXqvGFw1U#!_eqPzs+z}Dw>bldu+gRw`nfw>(>tHF>R~_3_|03ZlC?t(EjOwv z^B0}y$Jl->l9{?^s6>_C9kz7WCZzb@HxV}%#5g^(vwTTBw*0Ck0Sdz%NMfHIHkQrC zvnlTLdYRq(IKih8+XV+R)mGcpxXlW!kK#)nSGb>PQOYNYH~5A=Rx9ly#^=D@o^N&w zE3SBT7?`0JZ5`i>n24zTl9~DIt?0)D(E84G>;CDQQHXjX z2uFCM5GcqV!|@&6u?3T@PDmk$9Pk08B0h$b%$G_3UH-A-rBe_xq127~47$fUt06Rec}1R|ZCj#X#GY)O8iPud z$#L?X;L^aJHr#B3*G@(T7XSUJvWZ+qSKj4`l}25l*Uh=9xlMX!heT9xWTeUXcU)21 zsU9$gUm7Pe=w_c-LNK&w!?##W9(|3A6Lp=tCa0vt+oqtTMAw7BOG--qh*gdGQ9Ncg zv`vwtng@QszBG=E@ zxa>zQJkO2XXFVRS!xHt){rKk)_?4BE%!a>nVK1+g5^2Y0et7M3LnxcfMpbUX26sPM zAI)w(qu3%Yn_OqsS!vu`+Qn>puRdC&9TglHab>t7zTTH60ouuGF&w@(?rDMa;cJB%_YO2lq1jYpX>g;JOG>cI^$J z;0>X4-ACG$tEP?4UdP&s6J?N-s&3=*LOa95<73w5dxt?i{_P2D@W+33nL`(Wg*%n8 z+!;1fD~nGgAV3Vg<)HgiiT}Yz7cXW%-zQN%Scw}O(o`2@S z+4gwnOmEm3K0D6#cdeGdL++(GkEJIi(5Ii+*%S2D%N9pNaNq)?a5}#Y<#0NF5D>V( z)JGxYw_+m#yd=_E8<)+3JR0F?baHY}ZRt=r4u3deEG7Q7=D#OFokrth*vfRP+OdQ! z#Wqv|*4+i4MY#Qaiml;>oFS>cdxU3iweyhyj>>2l}|H<;=fji$@7#w{Y`&Kdg@j=@KgFd4M+z)L&_rv?3 z7T1Rs7e&l~jQcwO0HoGOA13zaWRiK~>+3nIwdnC8y3CsOh`oJta^5huOorY^BOu>A zT<@_-hvK!&}F13`u&fwGF-j5R4hkmPAF}v%bEmWaty*uaO z&)`EU_qKw|c!}pcyQRu-G3TkTc=h7DZ#aO`q9U1OxRXzb+979a$z=}tnrAFwWcF+bIS*b3nc8}{6H1@`sg42Nrpsy{^21e8r>eZ$rw?zQ%19W3^^SQ5h4pSqmQAjrR?riIr z1@G18yp=M1qR4_EsR^4%%{He#sPXT0%D8v6!`R-@et2>s2B8LH!aTwr`iO9*O{&76lR0jz z7+31}?nbB8GvJMcA*ahe@2i*FNqf-VkysW}L&ehD=QJPu^8BldcrH2KgT+;IMgR(qHy0y0g7@$A}W+f#Ub?2?D!VU8Mf(* zX-mk_$#7m^im&X9OzOMO0{4^eKa5$BQ&Fw#?pjgf3-E`2?2u5X(Rz*-;iu>^()zt6 zo!5>mRFAY-&uhAQI*5&=q-<>QWMZM2>X#vChAW!tTD?prr9Ci17=JYJ>TB%G-oewY1us5SWM*;Iu!ZRV$&@d#vV z8nx#n?kC~{X?(It%z222MK;to6TOVD9Do2Ym}V@vS|GkBdsBHnJ=a2x)S5onP*uQn zdEq@>=QEb?obi(AcR;;HN2^cUm|xq)L+4m8_Ed`lkF{2t!O1Lduk4?;GA-F4l)Z@a z8lN*&@4JnW4{ridjiCc+qO2BQvT-2e&6C9x95%CyT@m;oF$|acY<~Ued3sdPdga=+$>Y3d zve$SPIQE_OV~u6(*H0XbC zef;DJv*|$M=ySyGnu=YqQnf0_?!o$o2BkW0FGsD?7LlF_f>6vQ2%o%nSpVMDutg2P z1ECl5dy?@z@ebCh?Ier~b?xsV6IBwDXZ}a7KcBbS*v^VK7i`!;4+8|{Lv7Zk=w(+sj^_BAJwN6X!C9lG;kAdWR z$qyKxD){X|^WvLT864kDY`9o*!AZebUiR45E{-((*ZrR%fJ+4fF4g9FsGv+*xtxSS z5+UxF?SB63D#Rxp{?X;-HJU~Pv%B?+WEpKN8+Yr_B}(Ze$QP0Mx()s7zx+#^R*)*P z6AcIRn{oxFTquz(qpkC9oUJ1^;JlT^b~%BAqx(r1nIOLxt04_EXa80iv-ruJ2xG*r z>E$o(5;WuYblBvf@vx^>zNMsm8bAHH zOEzVO2b1(gZjMCcr`t=rFMcQcVLvJ0(Gvon*_AOH3s-GL^aM*p0`pKs0W(dypLAiz%j zxw)0{BgKFODhJtv1u-axk1DfjaMT&_WQteU(Wq zRlBafO3*|u==bcUk;V+)3&Jzh^=&3ZQc?HF$VfWfMoiy4>BMDVqNwn@ zpPHErrpsRJ&mEneb#`}$1P4D?E7M6@tEjb^lTuLlO1kvO_4bm_$tq6Tv0#jDDk~MBUA~EUc||$BN&m z(qLKCB)`C-IRrh|h#;-H25bvDH%BNSAOOCxyWVc)@bECxackIWvizsQ#d?2AwdDkg zy1Kf>XyH$NpF3m6@GW&iy0IF}m7aLoBE1%FIXSsFM*VaEbEa7Z$b8DBAC1=R?2ymP z8Lf25n)KT0we{4{CSD$&Od%69wHMM+Pz1aQLSZ%@7Uka^!%vfgW+C{n*m+{U5szRV z#b@^<2V8XtPz&)W0-=ZBpBvm|z>=A-HXjKN4HYgJd4+}53EqVFJlx;dYSmc8uX&H? z3rq6YaafKcgI;*wUzv)u5PM&Krj$)qC{m(;1B!opJgvIfSTRhzMvb5`L0Qy>9S-HAB8QfZEYg4>U<8fIB!zGi%9B{GVv+&1dI>TH*yV&w=7kHcD zcCv1FFwa+Oy8vdNhgC9hv_N5x%NE4(%8cxpEv4PVFz)M`PZdQ=k!ekv$Jdsd%F0!& znRO5W4v79*R0KY*z(;iL9FC5*Y^yw1^9;TspWm=`{*JHh!p{mbGtt#w0rT91Jpody{N?Ft| zAkD`wD5T;R0krw9-!@-PoauVB4B#OmDk`c-3ah!3%tfB9E%$h>^~~l-0jfk4kyxJ6 zD|Gbs;XG+X6cq71rRZlY()>Lbut?)RgL*fuuwp+U8?}mUj+5Q#1?FUviz?13{X@!>;ezdr5P``mQh&}=(k#ZlNj-qF|1RY zVC@1nNfmhHBLoCoK6h3=_tSE24l;z$f z3xuWGE_@afWbnpxy4pPaU4z$$u5er!^D0s<7|xZ%NV%~Z&J9tVF+Br6myWLPkVQ>6 z0T(lLNBg*k7V^&Z@Po~Kb9ZML_SSf5N><<4*x05wwWU-4)nNzf(3T^xih{r}9RY^J z=a5QvFvSL6jPY8$KRHYMrYn-LgXf@C;x1UczDeN5mI8xHPEaw^TU2D)Y4d%`IK+rU z2bgJ057!fImmsoVf|cmD6o3ul*J4f-zro3R|KP0YNWQF{i%WrM2>NKTYHy)T$=LG2 z!C<~@$~Qib+I}w(EjDiNZw@YRZcP^rs0#1i zeFgUnR~Sl&Xc`%jvssR_>NHlVO{9VecL;jAxV_!;jM($Ti0q%OgSnWfjv4jz1q7f} z58{t_`0i4Gpa+WrLViz^be+)21ZY_=U>4nPE|39X>QS~BlBBnP`Dect1QtQ47nk;v3JiNF-huDPUtBCE5b#b_ZTr4>U9)qJA`$$kb7Bx1)kVJe=`&+Ju4j@k zm7eRzcmV?v>G89Me=6So(@p#jJhH0%0W=l?ppEy<4ng?GOs=Grzo4)uqki!#S>LLM z`H-UQggnm30BfkvIF-ZD$a|hT+l|Yk6}M|nL|EU*QufIyhVrd>fF#l)@+w;})NC}^ z$x?k|>)Su~&(%8Phz z9Vz=Q`r<0e3q4b}$%VzRiw=c=H(0J9NBsSBFZYXV>lyY2b`zVlT!{#x4nXcPh=|fx zypTv=pgeifV&F;qwWI_e4kSaBVwLENd5?^AzJ&@2*M_dsZ+o3%V-Za*vEk=yiIbx1 zqs7fWbRW~H1bLkIbAbXIPRNoBX-f_&DWR2!B>1@BeASQ)x0V1hj}i!w9zmr3fy1nx%uAJm2-hX&!}((;4gK3Mv`hZYtLIL_)kZ}6w@xdqE|2CH~&YYEYeEt0&>rv}}1_!wI_MKPw9w@f@J|b=A0tkKIxWYo?5fDpNQ)E-vwZo@| zCjm0rJaY$+#67d5vABKQ^F(DeFHxVApPzrkd*oV<@y-(59aaH_LQjT!AqotcWQr?P zM!}sk6U4-AO8x;8hP~s~;x{9MZhnCg;rzoXF)_ksrPIGUJ2iRbqz!kcTV^bLKm$;ab4kp`G{*YW5@U-Nu#ll?kufeI>4IwEKW;R#-Y!|llF)X~A^eo6B2 zV+}69=VQ1U%P}&_bx!w|bf6S|jfrVL#-eTTdEj^1pUn~ufa}PEq)bE{jDP@5z~$&$ zSYe3EZy(pGK^I|Nq^}HICjuV(U=ZTodHx!)qdT)ilCD6-=Z^t^#%}jF>F9R2?Lq&J zdV}*Cy1qAm%F>%~sIo84XLi=Zk-d5L&Z);}AcLoOd#tU}=K+3(QZ`s8ms%>Y-_b`y1IKhAm8qHN zcFJ`0CF+K2A5(jKI}WoEb!fIilNx;_A&kE8Gz)m9z8<7v#ilF zh$J*_zoZUCAxy|S56%9>v-Fz7RtFGXeY`IDotxEeWvjW$0Do-`ppwGe9T0Wp2%?x~ zt1b5HN49INhK8+l9lT6U8EmL#A1yk!(}QCrH%H~#{rUNft#Yl*6jd+xR&Awm&+$Rs zeB~qqWNNMH$MC{lS}l!X<1&-UDK#%2-%H5F?wm+ls~3RbOF7AdDl489x-o_?=##F;#Qy*Ds4OyaW) z>_4FtwW&D8FRk%{`GDSc*UP)ReG+%q6_yt^U?G4;#?h<|0vK|21kJ$Vx55#)yTpJ- zWn=;{P918nxica!kfl*!P;E1pTz|4rHOkNJjue5%manqK+&o=IxG|8%66(;msp#s; ztJ^TuawG44u^&)X#d3FjR^vJgCNQ7J`EY@}ZIx61SsI4JNAAJ(b@AHfsi&w!{$XLg zu~3oB#pUJp#h-rPYrA1fB*5Rl+yN@rVJTfgWn)vueu4Y?b(hP+9k!PR4YAKCYMNT_ za9;28QpFAn9zX-(Sn(osDHrf+v}D0#f{P;J>ruF;tMEBC_X$MBZ*Q1n`PG@ubechV zmntF3`lGiu45a%?yAetn)#CRb;%NqX!Ej=VEp0CO1-2ngK=jzRM@|pgCz*0IZ~KM8 zMZe>UMz-dloI@DxM5hm_!Lkn`@(=C{tzIBCbPHd_>c@`g1&yJsfbjhWD0yIrv&Sqn zk5ABrEl1y3=;ywF1;&{szQ>GCd)nu=8;VTG9yeKK3UFxx%tL6^)zSG*6t!iky<;+e zQPm${?vwC$fV!fh+J#np{klFMt>k>4U__=BM0j(<;&}O7tyHUjZ>A2IgiF6dFp_FZ z^dbBw>w{EWTuBWl>#v3~KWBZHOPi+CYW`L?zYYIG+xBen=HXt@%&aggGAt}?=#E44 zqqUWGZcQ4C3&YE80c*?B1^cz03Y$51n9`W&us+SJ=68J-(ItH_)FDwH_erQ^jM@Bn zROSYc*NlY4q~By<)=l*Mz;@(vysLavzc+y%hle2)Bo}~h+k;xJH3$uV{15`9YToU} zx+{`M((&|liU9_h`dfF**q4Her{q)%hBxPX$hh3$F7x*SB5p12PDva-{D3tZ@6U3v zn*I5q@cQ-n>O&0?UtY{YcR zc`3E~_5{Q<*kvG<%Va0l8pPD3hcR{eNbC7#nVW%q9k6UaEw#I)z{YpRr0*L*zaz}0 zK}yfne6_001~#fpj?a8vqXS=7O7#m4vlS<;I$hPY&2TQ_?o?Bv1!>mqOkD;dMi+h$ z2xJN+W6k&1mT-=H*W7@GI`k(rnSZ((I}Y0B}R=Jv9iMrtOz@>}U9F zHpqY%laW`yMnS3d(Xd_ir>?b{lB)Tt&|xcN{y!jcVqY~RIQVHC-Buu2Or)e^)_4ok zI0@G&oOX{wADz9y8!i)(n6CEj+{OX(Id>;z4iTi$-|&9l*evs9D-feoPTeUwo-XdF zhh`R!;jme-!cY%zR0EF@SD;mC9gpr7<3ymCup0`r!9f< zP^=EI8ExBg)if6{IW?R2y6_^yW6#djmdrU{k9=z}%L!}x`-tS+{B3%oIz7lc=UELv z|3twl@&)Oxsi`T8g{ibKRDnz1*Yx_oCLk*L4sW#YXOEMMJrnPx5~C>X4^7a)E{~6( zA}$4Qf3hKr0n!#Yzsely>J4bHs5nZd?E=5b%NIQ^cZkvY-*qZtPzZTU>c7*a&j#Q2 zXLsJ7-`L(Z+UK=&yt;}59^Hh#cb4*o9H`o}WTn$@4DX7-n^tKvJ>^U7Re4I{+#T0` zLvHpl4bX7Bh`^~TllAwNF(cs73!7MCM9rqzGE??|u@ci z^Q4H;ro&Vmii(P$3_T0(1+0)mMJ0}0aEpSR{Lf11!<$S4<78ILpPzx`XuPE^Hjp7O z7{>SzW)F`Qf+s-Q5!xM|R8^?K_4SWd%~Z8{m7)g>RnyX8GwNo0LFM8g3L#*|J8T^r zi{Q8DMMdeq4J*;eU)$PoySY9Yn?QPAs)`TbHr#(==4pb0h9j?AsaLP{qUg2jVA&pz z)yn8Jkp@65@NFR=^*W}@8e$0>%@wPb;BbB-AtE9|#(C!pRKc--dWN1N7KZIW%1ZY1& zYhUv_ZLF|T|!R+U# zC{*Api4{Z=!fVuea=qN?1O8SwJyMcTLn)O^`e0@|L>*(5 zz(ads^Fu+#B4A`G?4@o3NP}dPRW7Iw8=hc%k%-TBBwSnE+3WiIKuyIb2M4xhZ$Jrf zm@F`Xp9G`~OOwImBbhs!x!MTD94NZSIo(^Bv;Wi=2K)|9MK=Gm0^kq|Y1R7C9)Ofy z-EH*u7Xuo7yIx2{>G2$N5$i8-xxBhEE+PI049T{-VaQ;FRv3z75EBmqLvsM&7fnzB zvp$%TvgR#tRV|=gAd{~-l5bX{^@v98DG6CNyq=!kcg?B)xG-lELPylb3hmtY%-=49mxSKl}aJa%?_1p9v@A zi`m?yXNM-u=LAK4db{*Rt;BeEwMg6;rq*|TpXy8EiTZti_wvR%&6M<4mE}YkAx!ZH z3%l|dfahACuK_VR1cNG*T0tP2bdTFHS9V9e zZ#)H!Eixj7U6GzVZuREE&e^%P=wZHvKUXtM?e&33GOPI`kMsRJki7v&F>Uuh8uX+~ zD$=Z?)Lqz>0~UZN3eKXb7!W4=(q(s6EOA0#BqKSw>6HnYSc&mcyRAmsM+8fCNTns+ zm13xxG*~Ow=X-lEeSO3o*TV!bWlNkDo72$2Z@( zoX*Za-rL);O|+Y^y^H{Xoj%eQQh#jk=|P+Wq{kcJup(GD9qAI&*msR%g*Eg(VErtffs z+>YNsVOKfyPs2WtI!B9?p&+}H9)q2&3cH6XrD#_|*Q=B?G@-e<RC`=22fNTZ)wGBg8U2KTzAx;?*TX^X%y>bgeLuCnBcBBQgX* z4Qcb~F)a{v@Xx9KBcn!iU2g9@@gFaa0C};BNw3*4# zzjxmEG7HVnUZu9$zTW?tZnNn4`O_2iyaWD~k45PIha*_UiTVkRc%M3|7nu-{$7z`~(!6WOnQJ z!&maX|Ea<#HYpd#VYHaP;V9E(!tVf+W^Smw!-es z3YCn3@)r;VVRSf|OpTj64NOBobB#Kbu! zmLGl^Naued_(9=a9R|irL%?Fn^jlK1(kSAKA0J<|dV%ZgH{{Tl&bIB=MX?<{|rp$H{cv@;FClB7)%BC~KR9WL@8m*4F5%_G?Mc#v( z9-N6q$bw+&)cFn0tu$ln@6?8qzXq50KZ*ySGQhwyHv3oESob0KSeKEEB4#8Je{e=d z#+1EfcT|g!v7S|b?mxM|qMY6PziI*g8xCNnkrzOH_39<4i#6y^uEC_$3zv$gNtX4t zBJ9xe0kgd;5?9vKlNZ#V@hIoZnRdryBnjA-$vTjL$nP>~s7ghk%wVkSbVh9zB{`&RDTCe(LdE(l_Y+sQ+ zq&4f{9}z=nJ;ExuSF3H1oAKrL1P2~t3vld~l-i$w8Jyd#%(7>BnEAQy8(RvO!^W$r zwl>)nZTt=;SWBNG6Zp#&tfbW~nCxywi%Qs5yk!UMp+Q1XNik04wNFzp5NVRi+(~d8zgu zVIbO7sCa3ux$>zy3Nd$hL6CZS7ZvSaf(W+jaCzTymUwG+pIJ`q5=Nq3wKvx6SQT&V ztppSVar_)BUbh$R`kNjJ&QU?0xEb2Y3%|7WCl5XQ_2&@eDM0DnCu z5hbnsJu&zX5ncm19)l$8`p zi2))2*kW~}^^c*o>WAtvQaY2eJ99%-VJgSu+((@N(TJYNG73xeKk-Ik&})95#_a@Z zhe#_$6frS*ZcS)Ky}$A|goK8Yy?u-LM8Ox}fb8t-7wV5#L0F&+CzePYNIN_~?;0A4 zK0N%?s@wcqfeNq(BHKG+cr4nHTumfk)R|E?xo)9@5~Xa<04c}K$t3ASM*N;;ue&5J zOLh>;(RErt`G2YDb$F5r3NlPkOW}|(@;`?BGFtC#S{anD;=UW9a zZe`JTsbIPsl5Dif;LOQVKs}ryg9T2f3jP^0EY;z6>a7Dv;uX z11#y0I3FLLZgcY!NN9b%8wm?7{ycxH>*^3GH7%|3Tjc{0v+sF%d6zReQ9oy(*h!jG zG}0`!b~ytb1QuaJ%xcNm4R@ba7 zufr$FJXLp*|4Crk3n{ydE80-f-ZeHhhJ8;cm%;|P0DS5nAn^e@pi6TTzd=>(6W+t< zqpM3Od>yz9ta>eIQE61m%{gK%l_P-}w~haLM)3RhEA8tegZv#ymCT*Qk0WNl@z(On z{s8#S78ykQHu7D6C)!1b$H+9XchY5tW|N8#Fvi`)!$DsCfQ4L8!vy zjV^d&Gw40$2FsXzy=h^?0@7gj4mTzy=C*2n3Z z*iO^OCA9pc(+2W#Ng=?;w@CAoj>lH8Yb8Jua3y|QRDAb#FbY_>jyBnlC1qo@SM7q1A zTR>VmC8fK&?|5Bn?|s%@XPM{(BLTt!Fp__qfat zC9xSMYQylkC-hZ(EbGI*&=Q{-qXyHD|1!ROrW|3JUfpdW(xxobp9gXzArwSCVoLB*dtw&eKOokyJ~=V{t<+qb5esfQE>K zA}Z9j9HgM0_Bb|wU0}iWaOWy5!`iWa8eRPcadk4%DV7+iV-Gx-dV+bc_k1_@KF@&1(%WJzj==0bL{7S#h ztgNhHAo}GODP1TMA*{mJa(pjYa1_qc=fPDo8)s)06(RFm{q&u6-Pc>~RZ^`tEFWMJ zrW*8np?oDILWchA*)tOC5P1y^ciB3|a#=TbrnS|9j&HRb;@NM3@3b(6W>D6_0gKCd zFO=A8D(DQYGB7o@w6i0k*%PrUce_@F|D6=;y@;Ww`m{w8S49gv8>m?Q^!9DJ*X={# zXn=Qgbi7!O;8)y2CL)Lk{h5$gP|yY(Sd3n6b1g+=GIFoT=F#DwJAKMHwD*s$5mc)3Uam^^0H)_USU-|A=OJ~CFsYt* zFYhh~*;(G{cpUEEk5~96rY$ccEc!LVUtH+)p^va5d%^I&BIks+XwfLni;j*)sUrvq z-HV_Mj1XvB7REBNUo%{;xxGfmBJjPrfi*NS!Fw7gM~q1s+V$-s@bvDpvy2m4a4>2{ zgO1O@`q<y14&`2HSa{_Y!KhgHa_C!=3c~w@0`h%B@XpE za|L&c+_slxWtHwPQ!w}AXGP?fxPV`g&8Cww_aPaaKNF_P4Jdtmh4(HcDaj46JDYAE zlVuwG+S$pfDBjqh;^5?L8yG-sZEZT)(#b=!+I>Wb@MVMhJ}co!?AN8O%U8DEbBN>S z^iw-d#cF!3hNa8()awQ5A!Qr1NY+tDv=GLvthcl}caPZaFUZ;6sg_?KT(5o)hU_a_UmSgFbbDa_P9i5W%4CTS0)%5~hMf6$k2qhy9CyLH zW}@gEa+sK=!HC0-#2 zS=8O{yOB|heM>qYy6=&Ggi3jy2I_Q9u^rTsWK@ffW>By@hj%hb>%1751%f}BIT<@S zU%ABC#HPEF*mI0@u%gqK(DxHWska#Kh6UxJ*f}|M?j>{65k8a;A;bQ7GQGlthf2uv zL57e!k(Eyy1{@;e+qaa9+w+C;yX&gFqP#K(4iUOG3f}u@dz{IEjj>_)_kz5MoMcLx z5Onke0bsSu7A7HsJD__-Mn?9P3;HQ~)c7K75cpSwiX$K*B4X$W9UB>0VLSX2@U0r5 z7jjBa_XFTC2q+vMuT_;d+ms7Zf2!il?%=Q&^i9AE?FqVkq20-b{8Z5N;z!Cr4KAz< zWwXJ(Iq10huRPVEXJM6hlt#e_;4_Q5AO4a@7Zm=nH75-J$22AMoYD^E85nl-UO`{J z&sr1P!+=4++I5r0_d&0`(9poZ;Eb;h42lT^>Q4A4QBkzz5OXDBKWE$HG6zIugX0K( z(k$z|H})m7%906vaTtO5l~sq86m|)-=Iq=JsKsAzQSiM41bjp+uKRiE-xVa*CEPxa zJVJ5+j3oM#UlC(5hRC5I%+6Fcw#VPHdy(i$isMM=Jh9^#u5lL^7yIYqo9iszaK3v} zF4spANWfILQf-ftoH@@jTjja30Phs(6++7$}K4SWOy1h%{C($UlGStyP` zTZTIDz+|RZc^Y(z24MdDeD4-2IuC2XV>>o6q2CvGue-E;|DCuiT$MIFZbDho=4?le z=VVCOcvEs=wyKIiVTLTeCvEff#+R)^U_^fS`0?X|vlWpkfpCByzVLrDHvS>~i*;P( z)GI}f*T7nUfrdu-LKuxza>fu>ve9*xY#!F$!9nguQ%T7mr?U}}SjYQ2YN(i=e3Zo8 zUo)cYA07R0C3`7|ND<$F;nt?A{@L9pqFTGv;EVxa6@Egp`4Kz?)GC<+aq$LIK~WnM zb7<{iJpM=a>x$F28_PzBoA{4GwiIR{=j|>=C1bQcsPio^S1dCm{+!oZCodv*xKlcj zk;I9l-o=%ig_c04ST)`GF2)SMA|w&PkO@z7j<>2gJA>|BI*)ngjYoPp9+S@18Zm^a z;wzvrL&S&(eZPW)%FC+GGPE6xmHr(OC}(3&A>b1_OhRaI6jM@q3L&B8fz6eib0Vw5HjpUmhA3D4Et9|_DZJbF|- z4GyAhL+Q};cXOtvE^}hNV6f1Q$a((`9*q|({OZb0G!Ftr?& zM+K!6n!jXx**kAn;T4k@y4uj@#U#wBlaiAn4_siIFODQdlfAtUUx3z2zjju#j%Ks6 zuuhQBx}t)UT7(MO7Mvs|g@O|Em?RFb!KbLFhb$6c zrFN~em%lQ3#Ac})=<6#anox4H$-LIdL9e7e7cw+;^06tZ`4YhgR02cI zCP5(~q7qwk_0x9wDXBxiUbHi{AK7E5+O)KcfVm;TVJm~cXb-f1?t)a6%DaKd7(pR`ki~)zK0rIou=1dPBT9(Ei$ESiXu-+ zRLlpE3i_(o}i|1mVT;@$CU4!tDOS zLYzBBkg$ae z^4+t0O@D>oZqY%4M4ljik1bSr3e7618D^W9_z~ZHsgg4D<%XYjf2L}O0yjY3$ zUW`@gG8j`JKb)K1FW0?m=>DAi5oNo1@@GnUS5wX*OK0{j?sUz*ij=p>L#O>|7<_#E z@0}=ZK=>qiggAs3c(wn2$U`j}nstw6iY*+gSeoFdXf`{@AJ*pNJbW+MWK(iO3n398 zYmKETxNKHcgMl2J9(TR>_29_AEuZ+=@ibRLrfv9eZ$Cwjo7;I$NL~GzgiNv!K$ze4 z8L4UZ2*}MgE6Pj;i9Y!I>zlU80sU)hJg0tuzJx=?OW8Km&BaN6?5VjJC;y!1txZ|p z6X09S%g=vbn%a^fmFIa%P=+7&i##X<<#mH^03`2l0{dX9H5i)ma zvH79XI4Eb0_!VtDcrz}}TUtI8rNdY^UCI`zpVBqoIM;sRRBv|B*Z$M479$$n{ryS=2y>qMXZ$q0(v05r_V$OMVn+APvc<>nsWDJ!bJ6i!7l9W($AdM@X!52xGgX}55@i`&}>-rnAT zG5E*(8wO%u)MpOS!wTJ!;$4G-s;a6B^Nz>Br2p~^<=>&s_EnYRe?=UzUsZIx@QA%{ z7-%)B2}+xef;-p6UW@4WjATQT3Ty^7-;F$~WdviN&v&=a z;6U}Tq(NeDq8zZ$Pi6=sfQA3oAF$a4Jl?%y`H>RYxYtYkktuALGu76Uh0<2bV<)P4 zgsX11ZS7E0XLEbSN~`@irUKKEO z@aEz4cz{7foS~8kz{0D&Rh1`rgm5M%lXYj31T@r^L&%;jsB3yT1DF#41#dXaL@@->yPyhfB=Y8F#Y38$9 z95M%FQ8BUBo*r~3CnrSIJtGH#tATjdTKlTkj&KlmXW5etybqO?4vl=auqobmuA;8W z#uO_|oEaGguRJcqkzFl=B-Dmm{SJ=Nd=dedm$-F{Sj9}kOUTf2L!EKm^{r?4&FUp- zll$_|^%TES9Y~H;asd4C!f2ti^zzu*?>mE6!F+H$sDVD)fc8$a1qQ&*rfK5)X^SA@ z8}?X&m)1Yk)Gl^wZV~t95I|nmoy4p0Dt`J3z1P4{&EaDUN=>)BxUPeXA9u+MPxZRE$hj8`;zbSg!!g&m9j{qVPa%) zLzFsJA5^D*23|oo@#k@^E_v!NA-VldZ*dzkc^Z=YzONTsuRIB@t7dQFC7w-AitJ z^;KJo?p(Vc#ia9by{`@LW^JKB=rL2@jrVI2D_?jo=ii_)LnfI!y*Ztzto*%H=e17| zGAYJK`2{&>MOQ+V4!uuM(3d=eE*TEH4MaD11VLJJ^!xTF@`a?)tiQUWGB?KZE7Y!6 z0pQE~=P#kkGG7wFQlL?n$S}d}FK)m(P%=MXnGhBM31 ztJ*PTQEMEiM2bgJ<{AzGnj(MoYRJ;l4qW+|$T%yjIPTT+duAyza?!5ux}%*a#=Ftr z^cfWOs`8IGari}~_4jHb{(y#@E0KMdEv=Y%?VX*SJHHQM2+NcZ3Vxql?H0BhV1;;U z234+5Y%?fce94Iipou9f=hyEZN4QK3YuEI3MXQ=HTe{W}_>-kIpPhcpu~iAJ>D+(z zhFMu!vmI=XyMQg&_Me+&xPb;^kDpzLXlU#jscVLod^6LJR2L2_t88oF0dS38XhQ35 zZI!o}vzRo0Fk@$9Go~hnv#P2t#Jy%ZgXLObcs(IyXmD5hqO$ubNwW?99;jAy*+>th zC4616$Y>kb?5f+WPE;qAV@K{FeX7(k7%nqF9dTNxSD(+Wl(?0%v({KQGiEiZsAF}O zIP6;Ceq8pwY83lgdPqr0$wlu+$id;M*v>Z>EbON*do^cy%1HJ-FW|+WOck=Ty_*g_ zUt{oT$wKfIzS5tm-gT>C_7)`axP1YjTX3;P&C4_PyTZ-jST|S2d)(NFmWlCkfUc=P zi&PZAg%}zewF9a>f`{t?pvc`ia^_Q|DEt6npRr%Dx{AxD|GeJuyd4Pa={K{Su~)>N zjmQ9PEpF}QS4k_Z*evJt<38bj0w{g-XV~GT%0+UUVhUbW9ho;3e1oHGvePMr*3I}c zii7F-;XR#K|3ae31Afh?5|WaKHDbhmH4zK|53&*ssuUJ3GHkvFMXFS1T7dV1`IJ(t zu0`iklppbC#z2A4nl3?#Vzl0jy2a&??DhSvn#1Onf8NGjHv^Rq7A#LHG6wuQT{pFyy;uiIN5gme%t%Z9^ zj_YEM>-9>sENDn15;g;pWcmwteHm;u2y04NCEY6s$={@cf|$wi@x_ByvXz0J){94& z@;W*Ze*OrN(Xk)LDp{Ilq9n38Jj$LV;NgiUxURc~d28tujCr(#xz+uHlGphsB@YKN z1zs?y+Fe_#nw7OhoLGGaA$j={9z;po6*=^_Hle6bp9+qW{v|P#mP;$FzGAd}4ES5o z&D0lDWqO2wop4-JA->{~o#8QaFKNDfmz5%{Ko}jysPYf!Sg~+h#dA#U*5hDRNy){^14qY?4lZ8_g|!+$Md@=Cq^g;&@tbuO?=8ytU=; z9g0T|y{Z2T#PxWtAx)EF6FrDVWnY^K`?r)KBVXEBgjHQ#ZE9-j(_o?!+XdbwdE4gM zUrsy?e0gtk_IU-a&u)V^_kVob)8f`OFz}nI6;y5Zz4$jNJX(XSEDKwlEaQxIz^0LvZSqU;%_9(GgF5s@6PjIzYEnvD9*80wE&j4u zzc@yUH03FY_!s<(>{~@d+7FD?DTPv#0|wHZsHb&9*qP;B8j@9K4OK3n(6-pS!^z3E zV^tDI=?q@{d99tOV-gMx4a>y-&Qh?#3(Ca}m-FTfP-9L?M~CtvS0)|sJAlHCeTsv1 zIvAU(v@+RV5t3n*?$vO8m7aG10l9&^f&!clzqcqsKxdjv9_aYzjYUKSZU0nISa>Ms z!XJ~wlWt4tKX2Po zDtvX6ALUlVfDux@HZzX&bF`ns9~Af@r} zxJ4lfDL<`z^!Tw55G4+Pa~w?l2Bv|hykdn*t_4b&j$d?)YMd7V@H~7OYdoHA99$W z0%~QIXU)#QDy)@(y!Y(TP#UZC?>QWsq101TO8~5V#)aA|XY31HkB}w=(}Q0whCc>G z0C_i%%pGxvsm*S|4Fy-{+Z)uWd{)$J>rD}&A@L-(M~1QWl5zAMVfgH2zr~r?tek9+ zpwJ-2$_AGn3=uKWO|MT;AC{6pq3722HUJK)hFOE(&vv=L(4k5@^hbZqAyNP{WMMto z*6ha%W(V}*Gf~99+L~k_kmSEowM{~FJzb4IJnXt}1FicGr)f&5&bHl)T;1IbMsxaW z9k;Qu>D7zM!}+9QO)8@MNG89+)SBqrKrbLAtS_D+{YI0sQ}%NjRYgrrR|0dk?_i5( z12!SoRC>uC1MuFeWQV(Xu67CCzJC2$7mB^SZl7V(sXw2}DZw3MPp>8?yL#D+&7l1u zFORCJGviKmfdDs=`xJx*_eB1CtsklPB?E4e$3!Il|Bfy66?HnRnQhx#kVCyyEj+eX zhlk|>Q}Q7>nGoc9`D4X@fddqH%SoI+FRbpp9>52Z@V7vI{#0}0pOh1_J=+{b$V~Ml z;%mMWPhvuGbw&E?+%Yp5>&^C+k}z>S92k&!U6o$C^W*1*>$WmD(67$^#IlNtQFUj4 zW#r`L-veZWjCb@|zoofLeQifgTv}4tMqH=T!sMpINMZHotRYj~gtWrn0Yrx7jYTP` z*TKTCwY~h)%ZicF!=t`ZvU+diB!Xnct-MJUFWNEdwVj{8WhM7>L190sGHETwJZm8< z6BDDwnuRm+T4&-F94r$1Gt0kBr15nB><=$AISnPsSTYd1=3SN@Pj-fd%TpI7h3Ev6 z6@yp%_*>VAy#dLy?a2Qg`72n9aQXB<^lG?@WbuPH#c{!V(A`HJA0$LzrE5&B5imLw z9>ZWEO2zp2AcXJc+sI<28dF`PS_?~L9$iJ0Mh^~YHLH+{i_2*sZCF>DYxhdrB|TpGkAjXQg|~27LN|P5A#!EUNHA zUwZEg3%J&8t%aVRM|xv!j zp1mpQZqe8%2LKj!DP_och{biCdJgypm|Yn0RNX#ZR9DSj*2msq!CX0}X0 z_LZXej3{lqa5Bv#f=IQ=ttwkMovl+-<&{hJhoEjd^;Osn;Ag)u>%*qiI76?#SvQ%j zca#K6sB!>M5@4-~bwEB_$RnF4r3IEAZQNrruvVgTzasJ%6@~afW9XOt3F@ul+dFru z#JljNQde-tV^jIBT=0PPqiuXn;gA4)Qd{p%M$02~@Hh?(c8#Ii4+K4s^_Dwsvx)xv z2^9<&G3M&8^)7;P<-GQidXLAhfw$nBZ{ztQFcs*Q&QF0Np!viW2+&#(Q8z=7GW?`(%*68VR*qtdXr>vYqHOdxPZ&yeV zDAzPH^7dwTxC^T*dgv*kmHmkL#uV0;m}zLvXJReRS1Zn2H)bQ~)`Ehj!+jgm$;lG4^MrmzexzK<)-Ee8uKw=!hoi2b8;XExKpwh zr+XZg{d(k9bxOI#+J9JJvL+87n5JN^s#X!zz}_N;4PzZ=G9x^^k$LfglAMa_$qUNx z!XH&&y5x9->`Uh3(mBa8s@rpB@_LTst=G~v-lDvVOZ}dE*mge8a%D8A9qP7b*8S|+ z$(|)>JdArgi{v(`b9$-%4!${{lOA6YW)MG z$X^0?$>oYFlO#N3u#_PY7P~4@YF4}(Y z=rm6ehnpS~Sty?v(-c;9;gFEQ+D;NqpQY|1R~($w@y&p{w6PiTu(LyuI<~EAQs)&aP%0oks|cX)>cpEU`nl(wzJ`z3&+v z2>W^uH@?`PRwMVIqgT-t@6na90!09jYgF@0b&9SqgZ$^T%^KId5E5!8jDIFEcJni{b4t0HfZ_MKazJA~7?ziRU1MY!3e3gAo}Rp&VT2)}Cka!{o`LdK zTfK=T<}|ItEWZN-Jpx(g^>WW5dE~*x6NvLWU$4UsZ{4A^_t5J2lxLh6qbAQ`AQUpV5$_MtkmivS zqZpBvwY}h@h8b;~oS0m0!q$HDbXs4ZLoF$nm+;*K15EXF1_nEz)zWMJYaXyzM{yWE zJ37L~9nUFg1n)SwT0onYSxmk&H0f8~nPdyh`IO9w&u={!oc8OCQ z_YFEeJIie!H{Bc>y1a$1<2eMq>N(J$pM-P(y+rk75uv!5n2gLqZvtMfE1a-=Yr7P= zK=%3f5f$%??2jTM#nEaw0-nOc{XYqzLGg9*9)&5O(=u|F{znf6G(q^!5&0heH3;9} zbi$5~DAY96w1ki43zydRP)$rs9y~l_`7;d|24(>gjH-5@+V^p&{&}LR73MFr@%RPz zuUdAd{rSU*#RiFZzc5n&Hj4nmh9gQq7_Qmos~~l(1gRY7xjVRry2m*v{kZ*2f7n-= zcSRi-gs}x6a<=o0En?7X0l`o*P`5G;t07;Xaq@HMuGoevof#jP&1ZE|PJ`9%=kEZe zf1Pq0+1F2$`V&V0%-x0899OL8LaBzySdaKECr>&n|JrA9Z*V>Bpb2eca&nmW?Y0hw z{aR?o4m6rCg)l_M#`-ffU%&$W13NUP`^1nbp|^T}Qis&S)TbzYabVDVbJUMX*;n-pDJpYH7hW}4J^HJyLf)ymk)Zu`s7TG87cSq@%a~N|+@r<_KJ9?W=5!m!bHyEv z$aB6M*yo6#^BdH>>VAy#O=kqImDID`YUa#c-`??DMAhX1NQAN(5&rIO)g7p;ddV{I zXXO6{j1oVJEQ?jF3knJj+CJkfE^kLny+5R)r5<@Eyxh`jWwx!OK<|Gw5{qfDrl6*# zhDYS;5JW~S(r@)W2;IiP;X_y$3TQWs09bcXHCtQ8jLgj8W>0q!F|lRPpXm3LKf__` zpp^M_6^0L>B=yWGKKnt};WCi8A~o7IbRn;3cu~OYLvZ5ORE)&_AXck1-D~~ zf!f`UfE1Mw^*$!S`5LtN`b((KD&Q%ty?9V|-avW|AWQpki~e3tmbNj;6JDJW&e zf6oo);JfYM{%QKcGb9c2r6-?+DUUSz}}4W7{Ssuu)J@4tB0c zfY4sY^y|N4Yz`YgVRnGqCugQo_s{qZmE0k^>m^#^l7rv!KVgi$$p))cFw^SA$Y1TL zAz|ZRn6<3T@pJ#d+5GYWdO1iBOn-ppP9!CoO$8gW&oN$353zYq+hxwS>8P zVedGFDN6i9z&%~j7dwNr;@#w$37{-o_fo?BTG z312~&zu1Xhg|=@7e9EiCQ})Wv%tC2{uAkz6BoiI6gjONMRv)fZ2D9aK>g`6xY%$b= zi;L;N8)3WHHV0qh=LZL9BNzyHNNsFt&m9BvSQT1&)FzGJVQWB6cYb27_w})OZD-ch zu(MfBhXPSsZ!x1oeWt9YMhp-kt)73EVEtx>a?YIScDSd6f%*j6gQ#yyCvc&ho}S{e zJJB+YnCM@h5lX*P&}#8oRJ|JR3br+8cCq1MGB(L5D0mFo$aGyin!f+U%C>%WVk9mT zv&o$*ALYDFr(SehOU4undObdZT2n!Jx=drL7pN?ybN@R05U2*@WlCvkd^CZ ziR4hmvkTB$f9v^#In{E{9yXJ&@Z!GEL==gHG@-(Tl$8zztWU!w$!GiKf9i^s2VxcL z{~of<&AT7}Mf0RAJ_V0}-|!$G8gQaLmq`c!4u9zNIIUUUG&<6N2yU~yCLN3aD)w(# zM6uPgM0?LGrstHsC&`0JJ5oDS<(Pu4q>a8J#*1rf0TFyxh_0@#&RLQWe$o>RA0R%8?|WsIy%>duuJR$f!ayW(0F{_%{AUTV^%($g%ep*p^VkP zJd!QD>>@6=ZFhr8V{04r2tnP`zkSrG#5rI0L3v>0#3USK518snNt>P;{TJV8OPlF3 zkX?YqnH0?HMmriUAu6y^K02k@1t42a(LwyM!mchXEKJP+?!xrWxgaKUIk8!IG{Qo4wD<3Mq0*Yc?YV`#n!Fwq{(q3hXWvvB?5JYq za&!>Xl^Zk;7k>)1Vp0Gjj_Kx;pl*lpJ-U$vG)cq{M5k^rIf0}ni0Dfv~$v{zMUlj>}Hd+AO<+9H~&J^SKlS$@UyuaJOe?my; zZ>{W+O$Gd=|071H*-D{f=qf`eA1-bn4v27hyt+QHNo&yv`wLn=z^Z%a%X4uh`DBD0 z3%vEC&sstf11IW*4nZXg=))Kf71e;-5rxRY!1G`ACC`>;02lD^JE{l{gY}01|K-A` zG?lUeacotq;y*8sab9h04ui6m;;L{tz7I=9z}Jpsp#34DlwTjAGqWsD{NK2ZZGyy{ zr0r2XB!4!)n9+qVG?}9zBlQVg!c)~>e%o{c>x_!x`(NG-w**hdcH+0QX15k zaqz2U@#ngZfch2f&fRLf`xda${f8)A$s*eHH^bk+*G?J;P+apgQ2;>smj+dXCS5uH zG#CLA93rcGJ&|f#zSP)iU=>;i!W1^xAM5Q~rI~jzpE=+Gf1PnMhymK|fQ$Pi3wi;)lu*;3^G_&${Wi0W<`cf=$|-)>1U_A97DS^6F39qu2S z_SW%Pz4$|D`qKAciCOdx-;8?zx#xYgE7O|l(_k?TJ{GW}WOz`}*iQ$1RyDq@egZ75 zg4X_{=nEF@>n8SIuYc8=G;z;VJJP)7KlhzKRq?!i`Vbh0I=|AWl^jb8Aidmwha{H-LFQWJ%UkcozS-oBustsOO%?q>zkaAjvc-Fn!m|MbymeAj%R85=WD;{4+=i6lUmpLzbD!m`HtQxeF=#!e_{1aAOv$g~BVE-cui zMS_?K5un9hIIeB=5ltkGxdy2sMPZ@T<@2s3n-%@jBmQM1c)sG_? zX$Vt2zY+k0b$9YP5k>P|z=X?*RRt%wl=wa%NJcF^j;Zd*<6~KE%>S^&Y;+gKJ0K-E zSzbU8QF8g#x(^H#-E4#!M_{n&)kCN#)^c}+#L7BZwzO?M)G<1mSN-==5N#tMI{@f! zaiog;F*o1*zsdx;Rr8<$h#XK@Z4J7}$UP}Q(_%fv#Ckid(H4F_ur~*QBkJ3TtHM+R ze?#+H^4L#ZYx;r8Y_Y3BEM#@MjT4?t>{%3~l_2Ml)7w&RTL|Ru93Ex=qx6rYoMdDp zSxWRiolO^HYb$G@Gy~FhEvmcU?5SG4L!LSPg_#n+Wp^P0VA_>+91?DB$P8+#CE0Jv*o<7RZi$Ih4fw7^F^7LGN=F5b&jf8(?O#F!fdG zAt*&H-TG&#!v7{J{f8=t|G$4aT9S_fYOfT&3xeSrvPr8$iZ7k2@|U328YcWqKoMMh z_{@X~y~+wkHyFc(bibF&e|$OrK>GigmH+F-iS1ka($g?>^(V61UXHA;h358e?2O=@ zIS~$3S>O~qepYDTh*kjPrtdmpJFZ*!kOhnbP;M%%tpi)V-7DX;swMI^I4@gXa=Ms( zMqV4^5aN76W=`W0{wkbw9kB^ppyu6t+pj?4_nH(Ib~Y1P-crb3sx2}Gc=qN5=}Ev! z^pr;ow=2^AgEmqc(947=)}P}p11~M)`LlE8+|J>+KhM3q=^j3GO+-?siCU*QAM?2= z9Ar$ooc87%TK_m<67+;P0>I{jsYjxPIXq!Mo$kl`ZnpN_2pd!%u^3h#K<__Px26>y zKzH*-)~1garjJ&0xW3vh9nO{2;ox=_N#*l|8a4A`oHuk!FD|9bUb>y5w%(ktY0w)J zBD}L-br>&DLPXmS1X2qrM=g8v)sbXKD6!8^dkK*-<JzcTNtr6bo0YU^*Bcc>(z^{ofvH$ z9)=VKb*q2AZY<1a@Vu^Bxe`c#PRVw!p^3BT>)Ammv5+yjBu}<2M8Lk z=RHITAygc4L6j*T7!}M+2TLIapzmCr{neiP@!?*hYfuP&(DlAGn)UuW)k@PS2}0nI z;ox)@*^lI#s<&$By_=nNJ#ZVs=Y{htGwSokGFn|-e`PskQ(IrxKHQ^Le!tWqiFc7CI*9^jAHqQI5P8qwjF-+dw+xtB<>$&L9%FR*qF&e~Nnb@>~t*`p`p;>q?OCQrY zY?mI4jE=rC8+jgk_T!&}TMs8xVq3*M@hnDw*fuzUA|`{Nun+~#h{_MgB}{(vu+bV9 z81Zh%z5BduZk|gbE32!dUPA()n{XoUYoq#!^!`|dbSKbU*1xinB_@f>A7~apBaE$& zUPyTW2fIpXhony-y^K&gP%a=j1`AH z*tTw292O%QR=u0Zs)b+F_CK_uM>hkqVCcFdNbU`KcDCX50Gq+iOu4lv^7chW8$$m@8$43NE zr|ss*iKekVCe($bR8hgHZt&RqfjHB(SvY0Hh8732X{kk#_ zdY79K#Ek{obJ$+dqk^6=tz%}R@?K}O^=__u)0O$SxH!2OD$9e>3tsq;SNbao7w`Jb zU0hugc#S=q5xU1X!$QJ3xJPrzU$8#S&XvuSoGfv<-hC771)jEpBbw5sW~bd(Ys3av zwp3kNMC1@d`U+hoQTK-czLv> zJzu86fv2-HdLrFfocO_mi{;F0$$qYfV1@f{JVh58CN=4LCe+rBPUZ#$?r9NjcfnQ)vR8Ra|kl0818}h`ySde^cCi8 z@2#Ry41OZI5%lPM`vMwSI!3X8k=Wl$f#$lFLJIdl%$?b=eb^tN1Edq6uogiVE}_U# zE4%_LN<0+QG=Yr)&1g+zP;zN&7l$d-)kiQ46u2#59S7{d9|m#=H8Y= zt0!4QoT_(~h-vu2URjSdDgr=qBVy?FC$tWiu91&kjYIW?BI2Yw;{H>tLNZa$F|fT1 OcXzFI2mb#5 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�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 diff --git a/doc/salome/gui/HYBRIDPLUGIN/images/hybrid_hypothesis_faces.png b/doc/salome/gui/HYBRIDPLUGIN/images/hybrid_hypothesis_faces.png new file mode 100644 index 0000000000000000000000000000000000000000..7f0a84f67cb7f471b0a7ed8e998e47e0e642ff9b GIT binary patch literal 15015 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 d2UhKG9K+qx}5L7lIJn%$}YmOec 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 Zav$kClbi9<5*$Ia)b;P9?mm3+e*v&o(I5Z- diff --git a/doc/salome/gui/HYBRIDPLUGIN/input/hybrid_hypo.doc b/doc/salome/gui/HYBRIDPLUGIN/input/hybrid_hypo.doc index 77e5b8e..71ada99 100644 --- a/doc/salome/gui/HYBRIDPLUGIN/input/hybrid_hypo.doc +++ b/doc/salome/gui/HYBRIDPLUGIN/input/hybrid_hypo.doc @@ -198,8 +198,6 @@ MG-HYBRID USAGE EMail: ) \endverbatim -\n -- Limitations - Some of the MG-Hybrid parameters can not be changed in SALOME and are set to their default values. The parameters concerned are the following : global_physical_size, boundary_layer_size_mode, boundary_layer_initial_height_on_surface_tags, boundary_layer_max_element_angle and optimisation. \ref hybrid_top "Back to top" @@ -258,6 +256,20 @@ Pay attention: theses groups should be defined into the shell mesh from a previous group defined in the geometry. +\ref hybrid_top "Back to top" + +\section hybrid_layers_faces Faces with layers + +\image html hybrid_hypothesis_faces.png + +In case of a mesh based on geometry, if Mesh layers on all wrap +on Layers meshes tab is unchecked, you can specify geometrical +faces on which boundary layers should be constructed. After clicking +\a Selection button (arrow) you can select faces either in the +Viewer or in the Object Browser. \b Add button adds IDs of the +selected faces to the Face IDs list. \b Remove button removes +selected IDs from the list. +
See Also a sample TUI Script of the \ref tui_hybrid "creation of a MG-Hybrid hypothesis". \ref hybrid_top "Back to top" diff --git a/idl/HYBRIDPlugin_Algorithm.idl b/idl/HYBRIDPlugin_Algorithm.idl index 7f6233a..9732ad5 100644 --- a/idl/HYBRIDPlugin_Algorithm.idl +++ b/idl/HYBRIDPlugin_Algorithm.idl @@ -78,6 +78,11 @@ module HYBRIDPlugin */ void SetLayersOnAllWrap(in boolean toMesh); boolean GetLayersOnAllWrap(); + /*! + * To mesh layers on given faces. + */ + void SetFacesWithLayers(in SMESH::long_array faceIDs); + SMESH::long_array GetFacesWithLayers(); /*! * To make groups of volumes of different domains when mesh is generated from skin. * Default is to make groups. diff --git a/src/GUI/HYBRIDPluginGUI_Enums.h b/src/GUI/HYBRIDPluginGUI_Enums.h index 8b2bf77..c351ed3 100644 --- a/src/GUI/HYBRIDPluginGUI_Enums.h +++ b/src/GUI/HYBRIDPluginGUI_Enums.h @@ -29,8 +29,8 @@ enum { STD_TAB = 0, ADV_TAB, - ENF_VER_TAB, - ENF_MESH_TAB + ENF_MESH_TAB, + FACE_SEL_TAB }; // Enforced vertices array columns diff --git a/src/GUI/HYBRIDPluginGUI_HypothesisCreator.cxx b/src/GUI/HYBRIDPluginGUI_HypothesisCreator.cxx index 5b50e17..f34c87e 100644 --- a/src/GUI/HYBRIDPluginGUI_HypothesisCreator.cxx +++ b/src/GUI/HYBRIDPluginGUI_HypothesisCreator.cxx @@ -28,12 +28,13 @@ #include -#include -#include #include +#include +#include #include #include #include +#include #include #include @@ -414,7 +415,7 @@ QFrame* HYBRIDPluginGUI_HypothesisCreator::buildFrame() aStdLayout->addWidget( myBoundaryLayersGrowthCombo, row++, 1, 1, 1 ); QStringList typesBoundaryLayersGrowth; - typesBoundaryLayersGrowth << tr( "HYBRID_LAYER_GROWTH_UPWARD" ) << tr( "HYBRID_LAYER_GROWTH_DOWNWARD" ); + typesBoundaryLayersGrowth << tr( "HYBRID_LAYER_GROWTH_DOWNWARD" ) << tr( "HYBRID_LAYER_GROWTH_UPWARD" ); myBoundaryLayersGrowthCombo->addItems( typesBoundaryLayersGrowth ); aStdLayout->addWidget( new QLabel( tr( "HYBRID_HeightFirstLayer" ), myStdGroup ), row, 0, 1, 1 ); @@ -682,16 +683,35 @@ QFrame* HYBRIDPluginGUI_HypothesisCreator::buildFrame() anEnfMeshLayout->addLayout(anEnfMeshLayout2, ENF_MESH_MESH+1, 1, ENF_MESH_NB_LINES, 1); anEnfMeshLayout->setRowStretch(ENF_MESH_MESH, 10); - + + // selection of faces + + QWidget* faceSelGroup = new QWidget( dlg() ); + QGridLayout* faceSelLayout = new QGridLayout( faceSelGroup ); + + QLabel* facesLbl = new QLabel( tr("HYBRID_FACE_IDS"), faceSelGroup ); + faceSelLayout->addWidget( facesLbl, 0, 0 ); + + myFaceSelector = new StdMeshersGUI_SubShapeSelectorWdg( faceSelGroup, TopAbs_FACE, true, true ); + QString aMainEntry = SMESHGUI_GenericHypothesisCreator::getMainShapeEntry(); + QString aSubEntry = SMESHGUI_GenericHypothesisCreator::getShapeEntry(); + myFaceSelector->SetGeomShapeEntry( aSubEntry, aMainEntry ); + faceSelLayout->addWidget( myFaceSelector, 1, 0, 2, 2 ); + faceSelLayout->setRowStretch( 1, 10); + + // add tabs tab->insertTab( STD_TAB, myStdGroup, tr( "SMESH_ARGUMENTS" ) ); tab->insertTab( ADV_TAB, myAdvGroup, tr( "HYBRID_ADV_ARGS" ) ); - //TODO remove or er usmay be lateful to select layers... - //tab->insertTab( ENF_VER_TAB, myEnfGroup, tr( "HYBRID_ENFORCED_VERTICES" ) ); tab->insertTab( ENF_MESH_TAB, myEnfMeshGroup, tr( "HYBRID_ENFORCED_MESHES" ) ); + if ( aMainEntry.isEmpty() && aSubEntry.isEmpty() ) // mesh not based of geometry + faceSelGroup->hide(); + else + tab->insertTab( FACE_SEL_TAB, faceSelGroup, tr( "HYBRID_FACES_TAB" )); tab->setCurrentIndex( STD_TAB ); // connections + connect( tab, SIGNAL( currentChanged ( int )), this, SLOT( onTabChanged( int ) ) ); //connect( myLayersOnAllWrapCheck, SIGNAL( toggled( bool ) ), this, SLOT( onLayersOnAllWrap(bool))); connect( myLayersOnAllWrapCheck, SIGNAL( toggled( bool ) ), this, SLOT( updateWidgets() ) ); //connect( myToMeshHolesCheck, SIGNAL( toggled( bool ) ), this, SLOT( onToMeshHoles(bool))); @@ -794,7 +814,6 @@ This method updates the tooltip of a modified item. The QLineEdit widgets conten is synchronized with the coordinates of the enforced vertex clicked in the tree widget. */ void HYBRIDPluginGUI_HypothesisCreator::updateEnforcedVertexValues(QTableWidgetItem* item) { -// MESSAGE("HYBRIDPluginGUI_HypothesisCreator::updateEnforcedVertexValues"); int row = myEnforcedTableWidget->row(item); QVariant vertexName = myEnforcedTableWidget->item(row,ENF_VER_NAME_COLUMN)->data(Qt::EditRole); @@ -825,7 +844,6 @@ void HYBRIDPluginGUI_HypothesisCreator::updateEnforcedVertexValues(QTableWidgetI if (!groupName.isEmpty()) toolTip += QString(" [") + groupName + QString("]"); -// MESSAGE("Tooltip: " << toolTip.toStdString()); for (int col=0;colitem(row,col)->setToolTip(toolTip); @@ -966,7 +984,6 @@ This method adds in the tree widget an enforced mesh from mesh, submesh or group */ void HYBRIDPluginGUI_HypothesisCreator::addEnforcedMesh(std::string name, std::string entry, int elementType, std::string groupName) { - MESSAGE("addEnforcedMesh(\"" << name << ", \"" << entry << "\", " << elementType << ", \"" << groupName << "\")"); bool okToCreate = true; QString itemEntry = ""; int itemElementType = 0; @@ -974,23 +991,19 @@ void HYBRIDPluginGUI_HypothesisCreator::addEnforcedMesh(std::string name, std::s bool allColumns = true; for (int row = 0;row(myEnforcedMeshTableWidget->cellWidget(row, col)) == 0) { allColumns = false; - MESSAGE("allColumns = false"); break; } } else if (myEnforcedMeshTableWidget->item(row, col) == 0) { allColumns = false; - MESSAGE("allColumns = false"); break; } if (col == ENF_MESH_CONSTRAINT_COLUMN) { QComboBox* itemComboBox = qobject_cast(myEnforcedMeshTableWidget->cellWidget(row, col)); itemElementType = itemComboBox->currentIndex(); - MESSAGE("itemElementType: " << itemElementType); } else if (col == ENF_MESH_ENTRY_COLUMN) itemEntry = myEnforcedMeshTableWidget->item(row, col)->data(Qt::EditRole).toString(); @@ -1002,7 +1015,6 @@ void HYBRIDPluginGUI_HypothesisCreator::addEnforcedMesh(std::string name, std::s if (itemEntry == QString(entry.c_str()) && itemElementType == elementType) { // // update group name // if (itemGroupName.toStdString() != groupName) { -// MESSAGE("Group is updated from \"" << itemGroupName.toStdString() << "\" to \"" << groupName << "\""); // myEnforcedMeshTableWidget->item(row, ENF_MESH_GROUP_COLUMN)->setData( Qt::EditRole, QVariant(groupName.c_str())); // } okToCreate = false; @@ -1014,13 +1026,11 @@ void HYBRIDPluginGUI_HypothesisCreator::addEnforcedMesh(std::string name, std::s if (!okToCreate) return; - MESSAGE("Creation of enforced mesh"); myEnforcedMeshTableWidget->setRowCount(rowCount+1); myEnforcedMeshTableWidget->setSortingEnabled(false); for (int col=0;colpalette(); @@ -1029,7 +1039,6 @@ void HYBRIDPluginGUI_HypothesisCreator::addEnforcedMesh(std::string name, std::s comboBox->insertItems(0,myEnfMeshConstraintLabels); comboBox->setEditable(false); comboBox->setCurrentIndex(elementType); - MESSAGE("Add item in table at (" << rowCount << "," << col << "): " << comboBox->currentText().toStdString()); myEnforcedMeshTableWidget->setCellWidget(rowCount,col,comboBox); } else { @@ -1039,25 +1048,21 @@ void HYBRIDPluginGUI_HypothesisCreator::addEnforcedMesh(std::string name, std::s case ENF_MESH_NAME_COLUMN: item->setData( 0, name.c_str() ); item->setFlags( Qt::ItemIsSelectable | Qt::ItemIsEnabled); - MESSAGE("Add item in table at (" << rowCount << "," << col << "): " << item->text().toStdString()); myEnforcedMeshTableWidget->setItem(rowCount,col,item); break; case ENF_MESH_ENTRY_COLUMN: item->setData( 0, entry.c_str() ); item->setFlags( Qt::ItemIsSelectable | Qt::ItemIsEnabled); - MESSAGE("Add item in table at (" << rowCount << "," << col << "): " << item->text().toStdString()); myEnforcedMeshTableWidget->setItem(rowCount,col,item); break; case ENF_MESH_GROUP_COLUMN: item->setData( 0, groupName.c_str() ); - MESSAGE("Add item in table at (" << rowCount << "," << col << "): " << item->text().toStdString()); myEnforcedMeshTableWidget->setItem(rowCount,col,item); break; default: break; } } - MESSAGE("Done"); } // connect( myEnforcedMeshTableWidget,SIGNAL( itemChanged(QTableWidgetItem *)), this, SLOT( updateEnforcedVertexValues(QTableWidgetItem *) ) ); @@ -1073,7 +1078,6 @@ This method adds in the tree widget an enforced vertex with given size and coord */ void HYBRIDPluginGUI_HypothesisCreator::addEnforcedVertex(double x, double y, double z, double size, std::string vertexName, std::string geomEntry, std::string groupName, bool isCompound) { - MESSAGE("addEnforcedVertex(" << x << ", " << y << ", " << z << ", " << size << ", \"" << vertexName << ", \"" << geomEntry << "\", \"" << groupName << "\", " << isCompound << ")"); myEnforcedTableWidget->disconnect(SIGNAL( itemChanged(QTableWidgetItem *))); bool okToCreate = true; double itemX,itemY,itemZ,itemSize = 0; @@ -1127,12 +1131,10 @@ void HYBRIDPluginGUI_HypothesisCreator::addEnforcedVertex(double x, double y, do if (( !isCompound && ((itemX == x) && (itemY == y) && (itemZ == z))) || /*( (itemEntry.toStdString() != "") && */ (itemEntry.toStdString() == geomEntry)/*)*/) { // update size if (itemSize != size) { - MESSAGE("Size is updated from \"" << itemSize << "\" to \"" << size << "\""); myEnforcedTableWidget->item(row, ENF_VER_SIZE_COLUMN)->setData( Qt::EditRole, QVariant(size)); } // update group name if (itemGroupName.toStdString() != groupName) { - MESSAGE("Group is updated from \"" << itemGroupName.toStdString() << "\" to \"" << groupName << "\""); myEnforcedTableWidget->item(row, ENF_VER_GROUP_COLUMN)->setData( Qt::EditRole, QVariant(groupName.c_str())); } okToCreate = false; @@ -1141,19 +1143,15 @@ void HYBRIDPluginGUI_HypothesisCreator::addEnforcedVertex(double x, double y, do } // for if (!okToCreate) { if (geomEntry.empty()) { - MESSAGE("Vertex with coords " << x << ", " << y << ", " << z << " already exist: dont create again"); } else { - MESSAGE("Vertex with entry " << geomEntry << " already exist: dont create again"); } return; } if (geomEntry.empty()) { - MESSAGE("Vertex with coords " << x << ", " << y << ", " << z<< " is created"); } else { - MESSAGE("Vertex with geom entry " << geomEntry << " is created"); } int vertexIndex=0; @@ -1175,11 +1173,9 @@ void HYBRIDPluginGUI_HypothesisCreator::addEnforcedVertex(double x, double y, do } } - MESSAGE("myVertexName is \"" << myVertexName.toStdString() << "\""); myEnforcedTableWidget->setRowCount(rowCount+1); myEnforcedTableWidget->setSortingEnabled(false); for (int col=0;colsetFlags( Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled); switch (col) { @@ -1223,9 +1219,7 @@ void HYBRIDPluginGUI_HypothesisCreator::addEnforcedVertex(double x, double y, do break; } - MESSAGE("Add item in table at (" << rowCount << "," << col << "): " << item->text().toStdString()); myEnforcedTableWidget->setItem(rowCount,col,item); - MESSAGE("Done"); } connect( myEnforcedTableWidget,SIGNAL( itemChanged(QTableWidgetItem *)), this, SLOT( updateEnforcedVertexValues(QTableWidgetItem *) ) ); @@ -1240,7 +1234,6 @@ This method is called when a item is added into the enforced meshes tree widget */ void HYBRIDPluginGUI_HypothesisCreator::onAddEnforcedMesh() { - MESSAGE("HYBRIDPluginGUI_HypothesisCreator::onAddEnforcedMesh()"); HYBRIDPluginGUI_HypothesisCreator* that = (HYBRIDPluginGUI_HypothesisCreator*)this; @@ -1268,11 +1261,9 @@ void HYBRIDPluginGUI_HypothesisCreator::onAddEnforcedMesh() _PTR(Study) aStudy = SMESH::GetActiveStudyDocument(); _PTR(SObject) aSObj; //SMESH::SMESH_IDSource::_nil; QString meshEntry = myEnfMeshWdg->GetValue(); - MESSAGE("myEnfMeshWdg->GetValue()" << meshEntry.toStdString()); if (selEnfMeshes == 1) { - MESSAGE("1 SMESH object selected"); // myEnfMesh = myEnfMeshWdg->GetObject< SMESH::SMESH_IDSource >(); // std::string entry = myEnfMeshWdg->GetValue(); aSObj = aStudy->FindObjectID(meshEntry.toStdString().c_str()); @@ -1284,7 +1275,6 @@ void HYBRIDPluginGUI_HypothesisCreator::onAddEnforcedMesh() } else { - MESSAGE(selEnfMeshes << " SMESH objects selected"); QStringList meshEntries = meshEntry.split(" ", QString::SkipEmptyParts); QStringListIterator meshEntriesIt (meshEntries); while (meshEntriesIt.hasNext()) { @@ -1309,7 +1299,6 @@ This method is called when a item is added into the enforced vertices tree widge */ void HYBRIDPluginGUI_HypothesisCreator::onAddEnforcedVertex() { - MESSAGE("HYBRIDPluginGUI_HypothesisCreator::onAddEnforcedVertex()"); HYBRIDPluginGUI_HypothesisCreator* that = (HYBRIDPluginGUI_HypothesisCreator*)this; @@ -1336,7 +1325,6 @@ void HYBRIDPluginGUI_HypothesisCreator::onAddEnforcedVertex() if (selEnfVertex <= 1) { - MESSAGE("0 or 1 GEOM object selected"); double x = 0, y = 0, z=0; if (myXCoord->GetString() != "") { x = myXCoord->GetValue(); @@ -1344,7 +1332,6 @@ void HYBRIDPluginGUI_HypothesisCreator::onAddEnforcedVertex() z = myZCoord->GetValue(); } if (selEnfVertex == 1) { - MESSAGE("1 GEOM object selected"); myEnfVertex = myEnfVertexWdg->GetObject< GEOM::GEOM_Object >(); std::string entry = ""; if (myEnfVertex != GEOM::GEOM_Object::_nil()) @@ -1352,8 +1339,6 @@ void HYBRIDPluginGUI_HypothesisCreator::onAddEnforcedVertex() addEnforcedVertex(x, y, z, size, myEnfVertex->GetName(),entry, groupName, myEnfVertex->GetShapeType() == GEOM::COMPOUND); } else { - MESSAGE("0 GEOM object selected"); - MESSAGE("Coords: ("<removeRow(row ); } @@ -1435,7 +1419,6 @@ void HYBRIDPluginGUI_HypothesisCreator::onRemoveEnforcedVertex() it.toBack(); while ( it.hasPrevious() ) { row = it.previous(); - MESSAGE("delete row #"<< row); myEnforcedTableWidget->removeRow(row ); } @@ -1463,6 +1446,14 @@ void HYBRIDPluginGUI_HypothesisCreator::onDirBtnClicked() myAdvWidget->workingDirectoryLineEdit->setText( dir ); } +void HYBRIDPluginGUI_HypothesisCreator::onTabChanged( int ) +{ + myEnfVertexWdg->deactivateSelection(); + myEnfMeshWdg->deactivateSelection(); + myFaceSelector->ActivateSelection( false ); + myFaceSelector->ShowPreview( false ); +} + void HYBRIDPluginGUI_HypothesisCreator::updateWidgets() { //customs automatic set @@ -1485,12 +1476,12 @@ void HYBRIDPluginGUI_HypothesisCreator::updateWidgets() addEnfMeshButton->setEnabled(enabled); removeEnfMeshButton->setEnabled(enabled); myEnfMeshWdg->setEnabled(enabled); - //xxx->setEnabled(enabled); + if ( QTabWidget* tab = qobject_cast( myStdGroup->parentWidget()->parentWidget() )) + tab->setTabEnabled( FACE_SEL_TAB, enabled ); } bool HYBRIDPluginGUI_HypothesisCreator::checkParams(QString& msg) const { - MESSAGE("HYBRIDPluginGUI_HypothesisCreator::checkParams"); if ( !QFileInfo( myAdvWidget->workingDirectoryLineEdit->text().trimmed() ).isWritable() ) { SUIT_MessageBox::warning( dlg(), @@ -1504,7 +1495,6 @@ bool HYBRIDPluginGUI_HypothesisCreator::checkParams(QString& msg) const void HYBRIDPluginGUI_HypothesisCreator::retrieveParams() const { - MESSAGE("HYBRIDPluginGUI_HypothesisCreator::retrieveParams"); HYBRIDPluginGUI_HypothesisCreator* that = (HYBRIDPluginGUI_HypothesisCreator*)this; HYBRIDHypothesisData data; readParamsFromHypo( data ); @@ -1522,15 +1512,16 @@ void HYBRIDPluginGUI_HypothesisCreator::retrieveParams() const myAdvWidget->initialMemorySpin ->setValue ( qMax( data.myInitialMemory, myAdvWidget->initialMemorySpin->minimum() )); - myCollisionModeCombo ->setCurrentIndex( data.myCollisionMode ); - myBoundaryLayersGrowthCombo ->setCurrentIndex( data.myBoundaryLayersGrowth ); - myElementGenerationCombo ->setCurrentIndex( data.myElementGeneration ); - myAddMultinormalsCheck -> setChecked ( data.myAddMultinormals ); - mySmoothNormalsCheck -> setChecked ( data.mySmoothNormals ); - myHeightFirstLayerSpin -> setValue( data.myHeightFirstLayer ); - myNbOfBoundaryLayersSpin -> setValue( data.myNbOfBoundaryLayers ); + myCollisionModeCombo ->setCurrentIndex( data.myCollisionMode ); + myBoundaryLayersGrowthCombo ->setCurrentIndex( data.myBoundaryLayersGrowth ); + myElementGenerationCombo ->setCurrentIndex( data.myElementGeneration ); + myAddMultinormalsCheck -> setChecked ( data.myAddMultinormals ); + mySmoothNormalsCheck -> setChecked ( data.mySmoothNormals ); + myHeightFirstLayerSpin -> setValue( data.myHeightFirstLayer ); + myNbOfBoundaryLayersSpin -> setValue( data.myNbOfBoundaryLayers ); myBoundaryLayersProgressionSpin -> setValue( data.myBoundaryLayersProgression ); - myMultinormalsAngleSpin -> setValue( data.myMultinormalsAngle ); + myMultinormalsAngleSpin -> setValue( data.myMultinormalsAngle ); + myFaceSelector ->SetListOfIDs( data.myFaceWLIds ); myAdvWidget->workingDirectoryLineEdit ->setText ( data.myWorkingDir ); myAdvWidget->keepWorkingFilesCheck ->setChecked( data.myKeepFiles ); @@ -1540,7 +1531,7 @@ void HYBRIDPluginGUI_HypothesisCreator::retrieveParams() const myAdvWidget->boundaryRecoveryCheck ->setChecked( data.myBoundaryRecovery ); myAdvWidget->FEMCorrectionCheck ->setChecked( data.myFEMCorrection ); myAdvWidget->gradationSpinBox ->setValue ( data.myGradation ); - myAdvWidget->myAdvOptionsTable ->SetCustomOptions( data.myTextOption ); + myAdvWidget->myAdvOptionsTable ->SetCustomOptions( data.myTextOption ); myAdvWidget->logInFileCheck ->setChecked( !data.myLogInStandardOutput ); myAdvWidget->removeLogOnSuccessCheck ->setChecked( data.myRemoveLogOnSuccess ); @@ -1555,8 +1546,6 @@ void HYBRIDPluginGUI_HypothesisCreator::retrieveParams() const myEnforcedTableWidget->setRowCount(rowCount+1); for (int col=0;colisCompound: " << enfVertex->isCompound); QTableWidgetItem* item = new QTableWidgetItem(); item->setFlags( Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled); switch (col) { @@ -1568,50 +1557,41 @@ void HYBRIDPluginGUI_HypothesisCreator::retrieveParams() const else item->setIcon(QIcon(iconVertex.scaled(iconVertex.size()*0.7,Qt::KeepAspectRatio,Qt::SmoothTransformation))); - MESSAGE("Add item in table at (" << rowCount << "," << col << "): " << item->text().toStdString()); } break; case ENF_VER_X_COLUMN: if (!enfVertex->isCompound) { item->setData( 0, enfVertex->coords.at(0) ); - MESSAGE("Add item in table at (" << rowCount << "," << col << "): " << item->text().toStdString()); } break; case ENF_VER_Y_COLUMN: if (!enfVertex->isCompound) { item->setData( 0, enfVertex->coords.at(1) ); - MESSAGE("Add item in table at (" << rowCount << "," << col << "): " << item->text().toStdString()); } break; case ENF_VER_Z_COLUMN: if (!enfVertex->isCompound) { item->setData( 0, enfVertex->coords.at(2) ); - MESSAGE("Add item in table at (" << rowCount << "," << col << "): " << item->text().toStdString()); } break; case ENF_VER_SIZE_COLUMN: item->setData( 0, enfVertex->size ); - MESSAGE("Add item in table at (" << rowCount << "," << col << "): " << item->text().toStdString()); break; case ENF_VER_ENTRY_COLUMN: item->setData( 0, enfVertex->geomEntry.c_str() ); - MESSAGE("Add item in table at (" << rowCount << "," << col << "): " << item->text().toStdString()); break; case ENF_VER_COMPOUND_COLUMN: item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsUserCheckable); item->setData( Qt::CheckStateRole, enfVertex->isCompound ); - MESSAGE("Add item in table at (" << rowCount << "," << col << "): " << enfVertex->isCompound); break; case ENF_VER_GROUP_COLUMN: item->setData( 0, enfVertex->groupName.c_str() ); - MESSAGE("Add item in table at (" << rowCount << "," << col << "): " << item->text().toStdString()); break; default: break; } myEnforcedTableWidget->setItem(rowCount,col,item); - MESSAGE("Done"); } that->updateEnforcedVertexValues(myEnforcedTableWidget->item(rowCount,ENF_VER_NAME_COLUMN)); rowCount++; @@ -1635,7 +1615,6 @@ void HYBRIDPluginGUI_HypothesisCreator::retrieveParams() const myEnforcedMeshTableWidget->setRowCount(rowCount+1); for (int col=0;colpalette(); @@ -1644,7 +1623,6 @@ void HYBRIDPluginGUI_HypothesisCreator::retrieveParams() const comboBox->insertItems(0,myEnfMeshConstraintLabels); comboBox->setEditable(false); comboBox->setCurrentIndex(enfMesh->elementType); - MESSAGE("Add item in table at (" << rowCount << "," << col << "): " << comboBox->currentText().toStdString()); myEnforcedMeshTableWidget->setCellWidget(rowCount,col,comboBox); } else { @@ -1654,18 +1632,15 @@ void HYBRIDPluginGUI_HypothesisCreator::retrieveParams() const case ENF_MESH_NAME_COLUMN: item->setData( 0, enfMesh->name.c_str() ); item->setFlags( Qt::ItemIsSelectable | Qt::ItemIsEnabled); - MESSAGE("Add item in table at (" << rowCount << "," << col << "): " << item->text().toStdString()); myEnforcedMeshTableWidget->setItem(rowCount,col,item); break; case ENF_MESH_ENTRY_COLUMN: item->setData( 0, enfMesh->entry.c_str() ); item->setFlags( Qt::ItemIsSelectable | Qt::ItemIsEnabled); - MESSAGE("Add item in table at (" << rowCount << "," << col << "): " << item->text().toStdString()); myEnforcedMeshTableWidget->setItem(rowCount,col,item); break; case ENF_MESH_GROUP_COLUMN: item->setData( 0, enfMesh->groupName.c_str() ); - MESSAGE("Add item in table at (" << rowCount << "," << col << "): " << item->text().toStdString()); myEnforcedMeshTableWidget->setItem(rowCount,col,item); break; default: @@ -1674,7 +1649,6 @@ void HYBRIDPluginGUI_HypothesisCreator::retrieveParams() const } // myEnforcedMeshTableWidget->setItem(rowCount,col,item); - MESSAGE("Done"); } // that->updateEnforcedVertexValues(myEnforcedTableWidget->item(rowCount,ENF_VER_NAME_COLUMN)); rowCount++; @@ -1692,84 +1666,92 @@ void HYBRIDPluginGUI_HypothesisCreator::retrieveParams() const QString HYBRIDPluginGUI_HypothesisCreator::storeParams() const { - MESSAGE("HYBRIDPluginGUI_HypothesisCreator::storeParams"); - HYBRIDHypothesisData data; - readParamsFromWidgets( data ); - storeParamsToHypo( data ); - - QString valStr = ""; - - if ( !data.myBoundaryRecovery ) - valStr = "-c " + QString::number( !data.myToMeshHoles ); - - if ( data.myOptimizationLevel >= 0 && data.myOptimizationLevel < 5 && !data.myBoundaryRecovery) { - const char* level[] = { "none" , "light" , "standard" , "standard+" , "strong" }; - valStr += " -o "; - valStr += level[ data.myOptimizationLevel ]; - } - if ( data.myMaximumMemory > 0 ) { - valStr += " -m "; - valStr += QString::number( data.myMaximumMemory ); - } - if ( data.myInitialMemory > 0 && !data.myBoundaryRecovery ) { - valStr += " -M "; - valStr += QString::number( data.myInitialMemory ); - } - valStr += " -v "; - valStr += QString::number( data.myVerboseLevel ); - - if ( !data.myToCreateNewNodes ) - valStr += " -p0"; - - if ( data.myRemoveInitialCentralPoint ) - valStr += " -no_initial_central_point"; - - if ( data.myBoundaryRecovery ) - valStr += " -C"; - - if ( data.myFEMCorrection ) - valStr += " -FEM"; - - if ( data.myGradation != 1.05 ) { - valStr += " -Dcpropa="; - valStr += QString::number( data.myGradation ); - } - - valStr += " "; - valStr += data.myTextOption; - -// valStr += " #BEGIN ENFORCED VERTICES#"; -// // Add size map parameters storage -// for (int i=0 ; irowCount() ; i++) { -// valStr += " ("; -// double x = mySmpModel->data(mySmpModel->index(i,ENF_VER_X_COLUMN)).toDouble(); -// double y = mySmpModel->data(mySmpModel->index(i,ENF_VER_Y_COLUMN)).toDouble(); -// double z = mySmpModel->data(mySmpModel->index(i,ENF_VER_Z_COLUMN)).toDouble(); -// double size = mySmpModel->data(mySmpModel->index(i,ENF_VER_SIZE_COLUMN)).toDouble(); -// valStr += QString::number( x ); -// valStr += ","; -// valStr += QString::number( y ); -// valStr += ","; -// valStr += QString::number( z ); -// valStr += ")="; -// valStr += QString::number( size ); -// if (i!=mySmpModel->rowCount()-1) -// valStr += ";"; -// } -// valStr += " #END ENFORCED VERTICES#"; -// MESSAGE(valStr.toStdString()); + HYBRIDHypothesisData data; + readParamsFromWidgets( data ); + storeParamsToHypo( data ); + + QString valStr = ""; + + if ( !data.myBoundaryRecovery ) + valStr = "-c " + QString::number( !data.myToMeshHoles ); + + if ( data.myOptimizationLevel >= 0 && data.myOptimizationLevel < 5 && !data.myBoundaryRecovery) { + const char* level[] = { "none" , "light" , "standard" , "standard+" , "strong" }; + valStr += " -o "; + valStr += level[ data.myOptimizationLevel ]; + } + if ( data.myMaximumMemory > 0 ) { + valStr += " -m "; + valStr += QString::number( data.myMaximumMemory ); + } + if ( data.myInitialMemory > 0 && !data.myBoundaryRecovery ) { + valStr += " -M "; + valStr += QString::number( data.myInitialMemory ); + } + valStr += " -v "; + valStr += QString::number( data.myVerboseLevel ); + + if ( !data.myToCreateNewNodes ) + valStr += " -p0"; + + if ( data.myRemoveInitialCentralPoint ) + valStr += " -no_initial_central_point"; + + if ( data.myBoundaryRecovery ) + valStr += " -C"; + + if ( data.myFEMCorrection ) + valStr += " -FEM"; + + if ( data.myGradation != 1.05 ) { + valStr += " -Dcpropa="; + valStr += QString::number( data.myGradation ); + } + + valStr += " "; + valStr += data.myTextOption; + + // valStr += " #BEGIN ENFORCED VERTICES#"; + // // Add size map parameters storage + // for (int i=0 ; irowCount() ; i++) { + // valStr += " ("; + // double x = mySmpModel->data(mySmpModel->index(i,ENF_VER_X_COLUMN)).toDouble(); + // double y = mySmpModel->data(mySmpModel->index(i,ENF_VER_Y_COLUMN)).toDouble(); + // double z = mySmpModel->data(mySmpModel->index(i,ENF_VER_Z_COLUMN)).toDouble(); + // double size = mySmpModel->data(mySmpModel->index(i,ENF_VER_SIZE_COLUMN)).toDouble(); + // valStr += QString::number( x ); + // valStr += ","; + // valStr += QString::number( y ); + // valStr += ","; + // valStr += QString::number( z ); + // valStr += ")="; + // valStr += QString::number( size ); + // if (i!=mySmpModel->rowCount()-1) + // valStr += ";"; + // } + // valStr += " #END ENFORCED VERTICES#"; return valStr; } bool HYBRIDPluginGUI_HypothesisCreator::readParamsFromHypo( HYBRIDHypothesisData& h_data ) const { - MESSAGE("HYBRIDPluginGUI_HypothesisCreator::readParamsFromHypo"); HYBRIDPlugin::HYBRIDPlugin_Hypothesis_var h = HYBRIDPlugin::HYBRIDPlugin_Hypothesis::_narrow( initParamsHypothesis() ); HypothesisData* data = SMESH::GetHypothesisData( hypType() ); h_data.myName = isCreation() && data ? hypName() : ""; + h_data.myCollisionMode = h->GetCollisionMode(); + h_data.myBoundaryLayersGrowth = h->GetBoundaryLayersGrowth(); + h_data.myElementGeneration = h->GetElementGeneration(); + h_data.myAddMultinormals = h->GetAddMultinormals(); + h_data.mySmoothNormals = h->GetSmoothNormals(); + h_data.myHeightFirstLayer = h->GetHeightFirstLayer(); + h_data.myBoundaryLayersProgression = h->GetBoundaryLayersProgression(); + h_data.myMultinormalsAngle = h->GetMultinormalsAngle(); + h_data.myNbOfBoundaryLayers = h->GetNbOfBoundaryLayers(); + h_data.myFaceWLIds = h->GetFacesWithLayers(); + h_data.myLayersOnAllWrap = h->GetLayersOnAllWrap(); h_data.myToMeshHoles = h->GetToMeshHoles(); h_data.myToMakeGroupsOfDomains = /*h->GetToMeshHoles() &&*/ h->GetToMakeGroupsOfDomains(); @@ -1778,16 +1760,6 @@ bool HYBRIDPluginGUI_HypothesisCreator::readParamsFromHypo( HYBRIDHypothesisData h_data.myInitialMemory = h->GetInitialMemory(); h_data.myOptimizationLevel = h->GetOptimizationLevel(); - h_data.myCollisionMode = h->GetCollisionMode(); - h_data.myBoundaryLayersGrowth = h->GetBoundaryLayersGrowth(); - h_data.myElementGeneration = h->GetElementGeneration(); - h_data.myAddMultinormals = h->GetAddMultinormals(); - h_data.mySmoothNormals = h->GetSmoothNormals(); - h_data.myHeightFirstLayer = h->GetHeightFirstLayer(); - h_data.myBoundaryLayersProgression = h->GetBoundaryLayersProgression(); - h_data.myMultinormalsAngle = h->GetMultinormalsAngle(); - h_data.myNbOfBoundaryLayers = h->GetNbOfBoundaryLayers(); - h_data.myKeepFiles = h->GetKeepFiles(); h_data.myWorkingDir = h->GetWorkingDirectory(); h_data.myVerboseLevel = h->GetVerboseLevel(); @@ -1801,7 +1773,6 @@ bool HYBRIDPluginGUI_HypothesisCreator::readParamsFromHypo( HYBRIDHypothesisData h_data.myRemoveLogOnSuccess = h->GetRemoveLogOnSuccess(); HYBRIDPlugin::HYBRIDEnforcedVertexList_var vertices = h->GetEnforcedVertices(); - MESSAGE("vertices->length(): " << vertices->length()); h_data.myEnforcedVertices.clear(); for (CORBA::ULong i=0 ; ilength() ; i++) { TEnfVertex* myVertex = new TEnfVertex(); @@ -1813,13 +1784,11 @@ bool HYBRIDPluginGUI_HypothesisCreator::readParamsFromHypo( HYBRIDHypothesisData if (vertices[i].coords.length()) { for (CORBA::ULong c = 0; c < vertices[i].coords.length() ; c++) myVertex->coords.push_back(vertices[i].coords[c]); - MESSAGE("Add enforced vertex ("<< myVertex->coords.at(0) << ","<< myVertex->coords.at(1) << ","<< myVertex->coords.at(2) << ") ="<< myVertex->size); } h_data.myEnforcedVertices.insert(myVertex); } HYBRIDPlugin::HYBRIDEnforcedMeshList_var enfMeshes = h->GetEnforcedMeshes(); - MESSAGE("enfMeshes->length(): " << enfMeshes->length()); h_data.myEnforcedMeshes.clear(); for (CORBA::ULong i=0 ; ilength() ; i++) { TEnfMesh* myEnfMesh = new TEnfMesh(); @@ -1847,7 +1816,6 @@ bool HYBRIDPluginGUI_HypothesisCreator::readParamsFromHypo( HYBRIDHypothesisData bool HYBRIDPluginGUI_HypothesisCreator::storeParamsToHypo( const HYBRIDHypothesisData& h_data ) const { - MESSAGE("HYBRIDPluginGUI_HypothesisCreator::storeParamsToHypo"); HYBRIDPlugin::HYBRIDPlugin_Hypothesis_var h = HYBRIDPlugin::HYBRIDPlugin_Hypothesis::_narrow( hypothesis() ); @@ -1871,7 +1839,7 @@ bool HYBRIDPluginGUI_HypothesisCreator::storeParamsToHypo( const HYBRIDHypothesi h->SetInitialMemory ( h_data.myInitialMemory ); if ( h->GetOptimizationLevel() != h_data.myOptimizationLevel ) h->SetOptimizationLevel( h_data.myOptimizationLevel ); - + if ( h->GetCollisionMode() != h_data.myCollisionMode ) h->SetCollisionMode( h_data.myCollisionMode ); if ( h->GetBoundaryLayersGrowth() != h_data.myBoundaryLayersGrowth ) @@ -1891,7 +1859,8 @@ bool HYBRIDPluginGUI_HypothesisCreator::storeParamsToHypo( const HYBRIDHypothesi h->SetMultinormalsAngle ( h_data.myMultinormalsAngle ); if ( h->GetNbOfBoundaryLayers() != h_data.myNbOfBoundaryLayers ) h->SetNbOfBoundaryLayers ( h_data.myNbOfBoundaryLayers ); - + h->SetFacesWithLayers( h_data.myFaceWLIds ); + if ( h->GetKeepFiles() != h_data.myKeepFiles) h->SetKeepFiles ( h_data.myKeepFiles); if ( h->GetWorkingDirectory() != h_data.myWorkingDir ) @@ -1912,16 +1881,14 @@ bool HYBRIDPluginGUI_HypothesisCreator::storeParamsToHypo( const HYBRIDHypothesi h->SetAdvancedOption ( h_data.myTextOption.toLatin1().constData() ); if ( h->GetStandardOutputLog() != h_data.myLogInStandardOutput ) h->SetStandardOutputLog ( h_data.myLogInStandardOutput ); - if ( h->GetRemoveLogOnSuccess() != h_data.myRemoveLogOnSuccess ) + if ( h->GetRemoveLogOnSuccess() != h_data.myRemoveLogOnSuccess ) h->SetRemoveLogOnSuccess ( h_data.myRemoveLogOnSuccess ); // Enforced vertices - int nbVertex = (int) h_data.myEnforcedVertices.size(); + //int nbVertex = (int) h_data.myEnforcedVertices.size(); HYBRIDPlugin::HYBRIDEnforcedVertexList_var vertexHyp = h->GetEnforcedVertices(); int nbVertexHyp = vertexHyp->length(); - MESSAGE("Store params for size maps: " << nbVertex << " enforced vertices"); - MESSAGE("h->GetEnforcedVertices()->length(): " << nbVertexHyp); // 1. Clear all enforced vertices in hypothesis // 2. Add new enforced vertex according to h_data @@ -1942,12 +1909,10 @@ bool HYBRIDPluginGUI_HypothesisCreator::storeParamsToHypo( const HYBRIDHypothesi } // for // Enforced Meshes - int nbEnfMeshes = (int) h_data.myEnforcedMeshes.size(); + //int nbEnfMeshes = (int) h_data.myEnforcedMeshes.size(); HYBRIDPlugin::HYBRIDEnforcedMeshList_var enfMeshListHyp = h->GetEnforcedMeshes(); int nbEnfMeshListHyp = enfMeshListHyp->length(); - MESSAGE("Store params for size maps: " << nbEnfMeshes << " enforced meshes"); - MESSAGE("h->GetEnforcedMeshes()->length(): " << nbEnfMeshListHyp); // 1. Clear all enforced vertices in hypothesis // 2. Add new enforced vertex according to h_data @@ -1964,7 +1929,6 @@ bool HYBRIDPluginGUI_HypothesisCreator::storeParamsToHypo( const HYBRIDHypothesi _PTR(SObject) aSObj = aStudy->FindObjectID(enfMesh->entry.c_str()); SMESH::SMESH_IDSource_var theSource = SMESH::SObjectToInterface( aSObj ); - MESSAGE("enfMesh->elementType: " << enfMesh->elementType); SMESH::ElementType elementType; switch(enfMesh->elementType) { case 0: @@ -1998,7 +1962,6 @@ bool HYBRIDPluginGUI_HypothesisCreator::storeParamsToHypo( const HYBRIDHypothesi bool HYBRIDPluginGUI_HypothesisCreator::readParamsFromWidgets( HYBRIDHypothesisData& h_data ) const { - MESSAGE("HYBRIDPluginGUI_HypothesisCreator::readParamsFromWidgets"); h_data.myName = myName ? myName->text() : ""; h_data.myLayersOnAllWrap = myLayersOnAllWrapCheck->isChecked(); h_data.myToMeshHoles = myToMeshHolesCheck->isChecked(); @@ -2006,18 +1969,19 @@ bool HYBRIDPluginGUI_HypothesisCreator::readParamsFromWidgets( HYBRIDHypothesisD h_data.myMaximumMemory = myAdvWidget->maxMemoryCheck->isChecked() ? myAdvWidget->maxMemorySpin->value() : -1; h_data.myInitialMemory = myAdvWidget->initialMemoryCheck->isChecked() ? myAdvWidget->initialMemorySpin->value() : -1; h_data.myOptimizationLevel = myOptimizationLevelCombo->currentIndex(); - - h_data.myCollisionMode = myCollisionModeCombo->currentIndex(); - h_data.myBoundaryLayersGrowth = myBoundaryLayersGrowthCombo->currentIndex(); - h_data.myElementGeneration = myElementGenerationCombo->currentIndex(); - h_data.myAddMultinormals = myAddMultinormalsCheck->isChecked(); - h_data.mySmoothNormals = mySmoothNormalsCheck->isChecked(); - - h_data.myHeightFirstLayer = myHeightFirstLayerSpin -> value(); - h_data.myNbOfBoundaryLayers = myNbOfBoundaryLayersSpin -> value(); - h_data.myBoundaryLayersProgression = myBoundaryLayersProgressionSpin -> value(); - h_data.myMultinormalsAngle = myMultinormalsAngleSpin -> value(); - + + h_data.myCollisionMode = myCollisionModeCombo->currentIndex(); + h_data.myBoundaryLayersGrowth = myBoundaryLayersGrowthCombo->currentIndex(); + h_data.myElementGeneration = myElementGenerationCombo->currentIndex(); + h_data.myAddMultinormals = myAddMultinormalsCheck->isChecked(); + h_data.mySmoothNormals = mySmoothNormalsCheck->isChecked(); + + h_data.myHeightFirstLayer = myHeightFirstLayerSpin -> value(); + h_data.myNbOfBoundaryLayers = myNbOfBoundaryLayersSpin -> value(); + h_data.myBoundaryLayersProgression = myBoundaryLayersProgressionSpin -> value(); + h_data.myMultinormalsAngle = myMultinormalsAngleSpin -> value(); + h_data.myFaceWLIds = myFaceSelector->GetListOfIDs(); + h_data.myKeepFiles = myAdvWidget->keepWorkingFilesCheck->isChecked(); h_data.myWorkingDir = myAdvWidget->workingDirectoryLineEdit->text().trimmed(); h_data.myVerboseLevel = myAdvWidget->verboseLevelSpin->value(); @@ -2029,7 +1993,7 @@ bool HYBRIDPluginGUI_HypothesisCreator::readParamsFromWidgets( HYBRIDHypothesisD h_data.myTextOption = myAdvWidget->myAdvOptionsTable->GetCustomOptions(); h_data.myLogInStandardOutput = !myAdvWidget->logInFileCheck->isChecked(); h_data.myRemoveLogOnSuccess = myAdvWidget->removeLogOnSuccessCheck->isChecked(); - + // Enforced vertices h_data.myEnforcedVertices.clear(); QVariant valueX, valueY, valueZ; @@ -2037,13 +2001,10 @@ bool HYBRIDPluginGUI_HypothesisCreator::readParamsFromWidgets( HYBRIDHypothesisD TEnfVertex *myVertex = new TEnfVertex(); myVertex->name = myEnforcedTableWidget->item(row,ENF_VER_NAME_COLUMN)->data(Qt::EditRole).toString().toStdString(); - MESSAGE("Add new enforced vertex \"" << myVertex->name << "\"" ); myVertex->geomEntry = myEnforcedTableWidget->item(row,ENF_VER_ENTRY_COLUMN)->data(Qt::EditRole).toString().toStdString(); if (myVertex->geomEntry.size()) - MESSAGE("Geom entry is \"" << myVertex->geomEntry << "\"" ); myVertex->groupName = myEnforcedTableWidget->item(row,ENF_VER_GROUP_COLUMN)->data(Qt::EditRole).toString().toStdString(); if (myVertex->groupName.size()) - MESSAGE("Group name is \"" << myVertex->groupName << "\"" ); valueX = myEnforcedTableWidget->item(row,ENF_VER_X_COLUMN)->data(Qt::EditRole); valueY = myEnforcedTableWidget->item(row,ENF_VER_Y_COLUMN)->data(Qt::EditRole); valueZ = myEnforcedTableWidget->item(row,ENF_VER_Z_COLUMN)->data(Qt::EditRole); @@ -2051,14 +2012,9 @@ bool HYBRIDPluginGUI_HypothesisCreator::readParamsFromWidgets( HYBRIDHypothesisD myVertex->coords.push_back(valueX.toDouble()); myVertex->coords.push_back(valueY.toDouble()); myVertex->coords.push_back(valueZ.toDouble()); - MESSAGE("Coords are (" << myVertex->coords.at(0) << ", " - << myVertex->coords.at(1) << ", " - << myVertex->coords.at(2) << ")"); } myVertex->size = myEnforcedTableWidget->item(row,ENF_VER_SIZE_COLUMN)->data(Qt::EditRole).toDouble(); - MESSAGE("Size is " << myVertex->size); myVertex->isCompound = myEnforcedTableWidget->item(row,ENF_VER_COMPOUND_COLUMN)->data(Qt::CheckStateRole).toBool(); - MESSAGE("Is compound ? " << myVertex->isCompound); h_data.myEnforcedVertices.insert(myVertex); } @@ -2069,14 +2025,10 @@ bool HYBRIDPluginGUI_HypothesisCreator::readParamsFromWidgets( HYBRIDHypothesisD TEnfMesh *myEnfMesh = new TEnfMesh(); myEnfMesh->name = myEnforcedMeshTableWidget->item(row,ENF_MESH_NAME_COLUMN)->data(Qt::EditRole).toString().toStdString(); - MESSAGE("Add new enforced mesh \"" << myEnfMesh->name << "\"" ); myEnfMesh->entry = myEnforcedMeshTableWidget->item(row,ENF_MESH_ENTRY_COLUMN)->data(Qt::EditRole).toString().toStdString(); - MESSAGE("Entry is \"" << myEnfMesh->entry << "\"" ); myEnfMesh->groupName = myEnforcedMeshTableWidget->item(row,ENF_MESH_GROUP_COLUMN)->data(Qt::EditRole).toString().toStdString(); - MESSAGE("Group name is \"" << myEnfMesh->groupName << "\"" ); QComboBox* combo = qobject_cast(myEnforcedMeshTableWidget->cellWidget(row,ENF_MESH_CONSTRAINT_COLUMN)); myEnfMesh->elementType = combo->currentIndex(); - MESSAGE("Element type: " << myEnfMesh->elementType); h_data.myEnforcedMeshes.insert(myEnfMesh); std::cout << "h_data.myEnforcedMeshes.size(): " << h_data.myEnforcedMeshes.size() << std::endl; } diff --git a/src/GUI/HYBRIDPluginGUI_HypothesisCreator.h b/src/GUI/HYBRIDPluginGUI_HypothesisCreator.h index c4458ee..0726311 100644 --- a/src/GUI/HYBRIDPluginGUI_HypothesisCreator.h +++ b/src/GUI/HYBRIDPluginGUI_HypothesisCreator.h @@ -48,20 +48,21 @@ #include CORBA_SERVER_HEADER(SMESH_Gen) #include CORBA_SERVER_HEADER(SMESH_Mesh) -class QWidget; -class QComboBox; class QCheckBox; +class QComboBox; +class QHeaderView; class QLineEdit; class QSpinBox; class QTableWidget; class QTableWidgetItem; -class QHeaderView; +class QWidget; -class SMESHGUI_SpinBox; -class StdMeshersGUI_ObjectReferenceParamWdg; +class HYBRIDPluginGUI_AdvWidget; class LightApp_SelectionMgr; +class SMESHGUI_SpinBox; class SUIT_SelectionFilter; -class HYBRIDPluginGUI_AdvWidget; +class StdMeshersGUI_ObjectReferenceParamWdg; +class StdMeshersGUI_SubShapeSelectorWdg; class QTEnfVertex { @@ -162,6 +163,8 @@ typedef struct myBoundaryLayersProgression, myMultinormalsAngle; short myNbOfBoundaryLayers; + SMESH::long_array_var myFaceWLIds; + } HYBRIDHypothesisData; /*! @@ -210,6 +213,7 @@ protected slots: void onRemoveEnforcedMesh(); //void synchronizeEnforcedMesh(); void checkEnfMeshIsDefined(); + void onTabChanged( int ); signals: void vertexDefined(bool); @@ -271,6 +275,7 @@ private: SMESHGUI_SpinBox* myMultinormalsAngleSpin; QCheckBox* mySmoothNormalsCheck; + StdMeshersGUI_SubShapeSelectorWdg* myFaceSelector; }; class EnforcedVertexTableWidgetDelegate : public QItemDelegate diff --git a/src/GUI/HYBRIDPlugin_msg_en.ts b/src/GUI/HYBRIDPlugin_msg_en.ts index 61daaac..bf8f942 100644 --- a/src/GUI/HYBRIDPlugin_msg_en.ts +++ b/src/GUI/HYBRIDPlugin_msg_en.ts @@ -310,5 +310,13 @@ downward means inward and upward means outward ... HYBRID_ENF_MESH_INFO <b>Warning</b>: Enforced meshes are currently only taken into account for meshes w/o associated geometry. + + HYBRID_FACES_TAB + Faces with layers + + + HYBRID_FACE_IDS + Face IDs + diff --git a/src/HYBRIDPlugin/HYBRIDPluginBuilder.py b/src/HYBRIDPlugin/HYBRIDPluginBuilder.py index 7a66586..a84a91b 100644 --- a/src/HYBRIDPlugin/HYBRIDPluginBuilder.py +++ b/src/HYBRIDPlugin/HYBRIDPluginBuilder.py @@ -97,6 +97,29 @@ class HYBRID_Algorithm(Mesh_Algorithm): self.Parameters().SetLayersOnAllWrap(toMesh) pass + ## To mesh "holes" in a solid or not. Default is to mesh. + # @param faceIDs faces or face IDs to construct boundary layers on + def SetFacesWithLayers(self, faceIDs): + import GEOM + ids = [] + if not isinstance( faceIDs, list ) and not isinstance( faceIDs, tuple ): + faceIDs = [ faceIDs ] + for fid in faceIDs: + if isinstance( fid, int ): + ids.append( fid ) + elif isinstance( fid, GEOM._objref_GEOM_Object): + faces = self.mesh.geompyD.SubShapeAll( fid, self.mesh.geompyD.ShapeType["FACE"]) + for f in faces: + ids.append( self.mesh.geompyD.GetSubShapeID( self.mesh.geom, f )) + else: + raise TypeError, \ + "Face should be either ID or GEOM_Object, not %s" % type(fid) + pass + self.Parameters().SetFacesWithLayers(ids) + if ids: + self.SetLayersOnAllWrap( False ) + pass + """ obsolete ## To mesh "holes" in a solid or not. Default is to mesh. diff --git a/src/HYBRIDPlugin/HYBRIDPlugin_HYBRID.cxx b/src/HYBRIDPlugin/HYBRIDPlugin_HYBRID.cxx index 90fe559..30fdd6b 100644 --- a/src/HYBRIDPlugin/HYBRIDPlugin_HYBRID.cxx +++ b/src/HYBRIDPlugin/HYBRIDPlugin_HYBRID.cxx @@ -41,8 +41,6 @@ #include #include #include -// #include -// #include #include #include @@ -87,13 +85,13 @@ typedef const std::list TTriaList; static const char theDomainGroupNamePrefix[] = "Domain_"; -static void removeFile( const TCollection_AsciiString& fileName ) +static void removeFile( const std::string& fileName ) { try { - SMESH_File( fileName.ToCString() ).remove(); + SMESH_File( fileName ).remove(); } catch ( ... ) { - MESSAGE("Can't remove file: " << fileName.ToCString() << " ; file does not exist or permission denied"); + MESSAGE("Can't remove file: " << fileName << " ; file does not exist or permission denied"); } } @@ -106,26 +104,20 @@ static void removeFile( const TCollection_AsciiString& fileName ) HYBRIDPlugin_HYBRID::HYBRIDPlugin_HYBRID(int hypId, int studyId, SMESH_Gen* gen) : SMESH_3D_Algo(hypId, studyId, gen) { - MESSAGE("HYBRIDPlugin_HYBRID::HYBRIDPlugin_HYBRID"); _name = Name(); _shapeType = (1 << TopAbs_SHELL) | (1 << TopAbs_SOLID);// 1 bit /shape type _onlyUnaryInput = true; // Compute() will be called on each solid _iShape=0; _nbShape=0; _compatibleHypothesis.push_back( HYBRIDPlugin_Hypothesis::GetHypType()); - //_compatibleHypothesis.push_back( StdMeshers_ViscousLayers::GetHypType() ); _requireShape = false; // can work without shape_studyId smeshGen_i = SMESH_Gen_i::GetSMESHGen(); CORBA::Object_var anObject = smeshGen_i->GetNS()->Resolve("/myStudyManager"); SALOMEDS::StudyManager_var aStudyMgr = SALOMEDS::StudyManager::_narrow(anObject); - MESSAGE("studyid = " << _studyId); - myStudy = NULL; myStudy = aStudyMgr->GetStudyByID(_studyId); - if (!myStudy->_is_nil()) - MESSAGE("myStudy->StudyId() = " << myStudy->StudyId()); _computeCanceled = false; } @@ -138,7 +130,6 @@ HYBRIDPlugin_HYBRID::HYBRIDPlugin_HYBRID(int hypId, int studyId, SMESH_Gen* gen) HYBRIDPlugin_HYBRID::~HYBRIDPlugin_HYBRID() { - MESSAGE("HYBRIDPlugin_HYBRID::~HYBRIDPlugin_HYBRID"); } //============================================================================= @@ -154,7 +145,6 @@ bool HYBRIDPlugin_HYBRID::CheckHypothesis ( SMESH_Mesh& aMesh, aStatus = SMESH_Hypothesis::HYP_OK; _hyp = 0; - //_viscousLayersHyp = 0; _keepFiles = false; _removeLogOnSuccess = true; _logInStandardOutput = false; @@ -166,8 +156,6 @@ bool HYBRIDPlugin_HYBRID::CheckHypothesis ( SMESH_Mesh& aMesh, { if ( !_hyp ) _hyp = dynamic_cast< const HYBRIDPlugin_Hypothesis*> ( *h ); - // if ( !_viscousLayersHyp ) - // _viscousLayersHyp = dynamic_cast< const StdMeshers_ViscousLayers*> ( *h ); } if ( _hyp ) { @@ -187,7 +175,6 @@ bool HYBRIDPlugin_HYBRID::CheckHypothesis ( SMESH_Mesh& aMesh, TopoDS_Shape HYBRIDPlugin_HYBRID::entryToShape(std::string entry) { - MESSAGE("HYBRIDPlugin_HYBRID::entryToShape "<_is_nil() ) throw SALOME_Exception("MG-HYBRID plugin can't work w/o publishing in the study"); GEOM::GEOM_Object_var aGeomObj; @@ -203,260 +190,6 @@ TopoDS_Shape HYBRIDPlugin_HYBRID::entryToShape(std::string entry) return S; } -//======================================================================= -//function : findShape -//purpose : -//======================================================================= - -// static TopoDS_Shape findShape(const SMDS_MeshNode *aNode[], -// TopoDS_Shape aShape, -// const TopoDS_Shape shape[], -// double** box, -// const int nShape, -// TopAbs_State * state = 0) -// { -// gp_XYZ aPnt(0,0,0); -// int j, iShape, nbNode = 4; - -// for ( j=0; jX(), aNode[j]->Y(), aNode[j]->Z() ); -// if ( aNode[j]->GetPosition()->GetTypeOfPosition() == SMDS_TOP_3DSPACE ) { -// aPnt = p; -// break; -// } -// aPnt += p / nbNode; -// } - -// BRepClass3d_SolidClassifier SC (aShape, aPnt, Precision::Confusion()); -// if (state) *state = SC.State(); -// if ( SC.State() != TopAbs_IN || aShape.IsNull() || aShape.ShapeType() != TopAbs_SOLID) { -// for (iShape = 0; iShape < nShape; iShape++) { -// aShape = shape[iShape]; -// if ( !( aPnt.X() < box[iShape][0] || box[iShape][1] < aPnt.X() || -// aPnt.Y() < box[iShape][2] || box[iShape][3] < aPnt.Y() || -// aPnt.Z() < box[iShape][4] || box[iShape][5] < aPnt.Z()) ) { -// BRepClass3d_SolidClassifier SC (aShape, aPnt, Precision::Confusion()); -// if (state) *state = SC.State(); -// if (SC.State() == TopAbs_IN) -// break; -// } -// } -// } -// return aShape; -// } - -//======================================================================= -//function : readMapIntLine -//purpose : -//======================================================================= - -// static char* readMapIntLine(char* ptr, int tab[]) { -// long int intVal; -// std::cout << std::endl; - -// for ( int i=0; i<17; i++ ) { -// intVal = strtol(ptr, &ptr, 10); -// if ( i < 3 ) -// tab[i] = intVal; -// } -// return ptr; -// } - -//================================================================================ -/*! - * \brief returns true if a triangle defined by the nodes is a temporary face on a - * side facet of pyramid and defines sub-domain inside the pyramid - */ -//================================================================================ - -// static bool isTmpFace(const SMDS_MeshNode* node1, -// const SMDS_MeshNode* node2, -// const SMDS_MeshNode* node3) -// { -// // find a pyramid sharing the 3 nodes -// //const SMDS_MeshElement* pyram = 0; -// SMDS_ElemIteratorPtr vIt1 = node1->GetInverseElementIterator(SMDSAbs_Volume); -// while ( vIt1->more() ) -// { -// const SMDS_MeshElement* pyram = vIt1->next(); -// if ( pyram->NbCornerNodes() != 5 ) continue; -// int i2, i3; -// if ( (i2 = pyram->GetNodeIndex( node2 )) >= 0 && -// (i3 = pyram->GetNodeIndex( node3 )) >= 0 ) -// { -// // Triangle defines sub-domian inside the pyramid if it's -// // normal points out of the pyram - -// // make i2 and i3 hold indices of base nodes of the pyram while -// // keeping the nodes order in the triangle -// const int iApex = 4; -// if ( i2 == iApex ) -// i2 = i3, i3 = pyram->GetNodeIndex( node1 ); -// else if ( i3 == iApex ) -// i3 = i2, i2 = pyram->GetNodeIndex( node1 ); - -// int i3base = (i2+1) % 4; // next index after i2 within the pyramid base -// return ( i3base != i3 ); -// } -// } -// return false; -// } - -//======================================================================= -//function : findShapeID -//purpose : find the solid corresponding to HYBRID sub-domain following -// the technique proposed in GHS3D manual (available within -// ghs3d installation) in chapter "B.4 Subdomain (sub-region) assignment". -// In brief: normal of the triangle defined by the given nodes -// points out of the domain it is associated to -//======================================================================= - -// static int findShapeID(SMESH_Mesh& mesh, -// const SMDS_MeshNode* node1, -// const SMDS_MeshNode* node2, -// const SMDS_MeshNode* node3, -// const bool toMeshHoles) -// { -// const int invalidID = 0; -// SMESHDS_Mesh* meshDS = mesh.GetMeshDS(); - -// // face the nodes belong to -// std::vector nodes(3); -// nodes[0] = node1; -// nodes[1] = node2; -// nodes[2] = node3; -// const SMDS_MeshElement * face = meshDS->FindElement( nodes, SMDSAbs_Face, /*noMedium=*/true); -// if ( !face ) -// return isTmpFace(node1, node2, node3) ? HOLE_ID : invalidID; -// #ifdef _DEBUG_ -// std::cout << "bnd face " << face->GetID() << " - "; -// #endif -// // geom face the face assigned to -// SMESH_MeshEditor editor(&mesh); -// int geomFaceID = editor.FindShape( face ); -// if ( !geomFaceID ) -// return isTmpFace(node1, node2, node3) ? HOLE_ID : invalidID; -// TopoDS_Shape shape = meshDS->IndexToShape( geomFaceID ); -// if ( shape.IsNull() || shape.ShapeType() != TopAbs_FACE ) -// return invalidID; -// TopoDS_Face geomFace = TopoDS::Face( shape ); - -// // solids bounded by geom face -// TopTools_IndexedMapOfShape solids, shells; -// TopTools_ListIteratorOfListOfShape ansIt = mesh.GetAncestors(geomFace); -// for ( ; ansIt.More(); ansIt.Next() ) { -// switch ( ansIt.Value().ShapeType() ) { -// case TopAbs_SOLID: -// solids.Add( ansIt.Value() ); break; -// case TopAbs_SHELL: -// shells.Add( ansIt.Value() ); break; -// default:; -// } -// } -// // analyse found solids -// if ( solids.Extent() == 0 || shells.Extent() == 0) -// return invalidID; - -// const TopoDS_Solid& solid1 = TopoDS::Solid( solids(1) ); -// if ( solids.Extent() == 1 ) -// { -// if ( toMeshHoles ) -// return meshDS->ShapeToIndex( solid1 ); - -// // - Are we at a hole boundary face? -// if ( shells(1).IsSame( BRepClass3d::OuterShell( solid1 )) ) -// { // - No, but maybe a hole is bound by two shapes? Does shells(1) touches another shell? -// bool touch = false; -// TopExp_Explorer eExp( shells(1), TopAbs_EDGE ); -// // check if any edge of shells(1) belongs to another shell -// for ( ; eExp.More() && !touch; eExp.Next() ) { -// ansIt = mesh.GetAncestors( eExp.Current() ); -// for ( ; ansIt.More() && !touch; ansIt.Next() ) { -// if ( ansIt.Value().ShapeType() == TopAbs_SHELL ) -// touch = ( !ansIt.Value().IsSame( shells(1) )); -// } -// } -// if (!touch) -// return meshDS->ShapeToIndex( solid1 ); -// } -// } -// // find orientation of geom face within the first solid -// TopExp_Explorer fExp( solid1, TopAbs_FACE ); -// for ( ; fExp.More(); fExp.Next() ) -// if ( geomFace.IsSame( fExp.Current() )) { -// geomFace = TopoDS::Face( fExp.Current() ); -// break; -// } -// if ( !fExp.More() ) -// return invalidID; // face not found - -// // normale to triangle -// gp_Pnt node1Pnt ( node1->X(), node1->Y(), node1->Z() ); -// gp_Pnt node2Pnt ( node2->X(), node2->Y(), node2->Z() ); -// gp_Pnt node3Pnt ( node3->X(), node3->Y(), node3->Z() ); -// gp_Vec vec12( node1Pnt, node2Pnt ); -// gp_Vec vec13( node1Pnt, node3Pnt ); -// gp_Vec meshNormal = vec12 ^ vec13; -// if ( meshNormal.SquareMagnitude() < DBL_MIN ) -// return invalidID; - -// // get normale to geomFace at any node -// bool geomNormalOK = false; -// gp_Vec geomNormal; -// SMESH_MesherHelper helper( mesh ); helper.SetSubShape( geomFace ); -// for ( int i = 0; !geomNormalOK && i < 3; ++i ) -// { -// // find UV of i-th node on geomFace -// const SMDS_MeshNode* nNotOnSeamEdge = 0; -// if ( helper.IsSeamShape( nodes[i]->getshapeId() )) { -// if ( helper.IsSeamShape( nodes[(i+1)%3]->getshapeId() )) -// nNotOnSeamEdge = nodes[(i+2)%3]; -// else -// nNotOnSeamEdge = nodes[(i+1)%3]; -// } -// bool uvOK; -// gp_XY uv = helper.GetNodeUV( geomFace, nodes[i], nNotOnSeamEdge, &uvOK ); -// // check that uv is correct -// if (uvOK) { -// double tol = 1e-6; -// TopoDS_Shape nodeShape = helper.GetSubShapeByNode( nodes[i], meshDS ); -// if ( !nodeShape.IsNull() ) -// switch ( nodeShape.ShapeType() ) -// { -// case TopAbs_FACE: tol = BRep_Tool::Tolerance( TopoDS::Face( nodeShape )); break; -// case TopAbs_EDGE: tol = BRep_Tool::Tolerance( TopoDS::Edge( nodeShape )); break; -// case TopAbs_VERTEX: tol = BRep_Tool::Tolerance( TopoDS::Vertex( nodeShape )); break; -// default:; -// } -// gp_Pnt nodePnt ( nodes[i]->X(), nodes[i]->Y(), nodes[i]->Z() ); -// BRepAdaptor_Surface surface( geomFace ); -// uvOK = ( nodePnt.Distance( surface.Value( uv.X(), uv.Y() )) < 2 * tol ); -// if ( uvOK ) { -// // normale to geomFace at UV -// gp_Vec du, dv; -// surface.D1( uv.X(), uv.Y(), nodePnt, du, dv ); -// geomNormal = du ^ dv; -// if ( geomFace.Orientation() == TopAbs_REVERSED ) -// geomNormal.Reverse(); -// geomNormalOK = ( geomNormal.SquareMagnitude() > DBL_MIN * 1e3 ); -// } -// } -// } -// if ( !geomNormalOK) -// return invalidID; - -// // compare normals -// bool isReverse = ( meshNormal * geomNormal ) < 0; -// if ( !isReverse ) -// return meshDS->ShapeToIndex( solid1 ); - -// if ( solids.Extent() == 1 ) -// return HOLE_ID; // we are inside a hole - -// return meshDS->ShapeToIndex( solids(2) ); -// } - - //======================================================================= //function : addElemInMeshGroup //purpose : Update or create groups in mesh @@ -480,7 +213,6 @@ static void addElemInMeshGroup(SMESH_Mesh* theMesh, SMESHDS_Group* aGroupDS = static_cast( groupDS ); aGroupDS->SMDSGroup().Add(anElem); groupDone = true; -// MESSAGE("Successfully added enforced element to existing group " << groupName); break; } } @@ -492,7 +224,6 @@ static void addElemInMeshGroup(SMESH_Mesh* theMesh, aGroup->SetName( groupName.c_str() ); SMESHDS_Group* aGroupDS = static_cast( aGroup->GetGroupDS() ); aGroupDS->SMDSGroup().Add(anElem); -// MESSAGE("Successfully created enforced vertex group " << groupName); groupDone = true; } if (!groupDone) @@ -516,7 +247,6 @@ static void updateMeshGroups(SMESH_Mesh* theMesh, std::set groupsTo std::string currentGroupName = (std::string)group->GetName(); if (groupDS->IsEmpty() && groupsToRemove.find(currentGroupName) != groupsToRemove.end()) { // Previous group created by enforced elements - MESSAGE("Delete previous group created by removed enforced elements: " << group->GetName()) theMesh->RemoveGroup(groupDS->GetID()); } } @@ -563,11 +293,6 @@ static void removeEmptyGroupsOfDomains(SMESH_Mesh* mesh, static void makeDomainGroups( std::vector< std::vector< const SMDS_MeshElement* > >& elemsOfDomain, SMESH_MesherHelper* theHelper) { - // int nbDomains = 0; - // for ( size_t i = 0; i < elemsOfDomain.size(); ++i ) - // nbDomains += ( elemsOfDomain[i].size() > 0 ); - - // if ( nbDomains > 1 ) for ( size_t iDomain = 0; iDomain < elemsOfDomain.size(); ++iDomain ) { std::vector< const SMDS_MeshElement* > & elems = elemsOfDomain[ iDomain ]; @@ -608,19 +333,19 @@ static void makeDomainGroups( std::vector< std::vector< const SMDS_MeshElement* //purpose : read GMF file w/o geometry associated to mesh //======================================================================= -static bool readGMFFile(MG_HYBRID_API* MGOutput, - const char* theFile, - HYBRIDPlugin_HYBRID* theAlgo, - SMESH_MesherHelper* theHelper, +static bool readGMFFile(MG_HYBRID_API* MGOutput, + const char* theFile, + HYBRIDPlugin_HYBRID* theAlgo, + SMESH_MesherHelper* theHelper, std::vector & theNodeByHybridId, std::vector & theFaceByHybridId, - std::map & theNodeToHybridIdMap, - std::vector & aNodeGroupByHybridId, - std::vector & anEdgeGroupByHybridId, - std::vector & aFaceGroupByHybridId, - std::set & groupsToRemove, - bool toMakeGroupsOfDomains=false, - bool toMeshHoles=true) + std::map & theNodeToHybridIdMap, + std::vector & aNodeGroupByHybridId, + std::vector & anEdgeGroupByHybridId, + std::vector & aFaceGroupByHybridId, + std::set & groupsToRemove, + bool toMakeGroupsOfDomains=false, + bool toMeshHoles=true) { std::string tmpStr; SMESHDS_Mesh* theMeshDS = theHelper->GetMeshDS(); @@ -666,11 +391,9 @@ static bool readGMFFile(MG_HYBRID_API* MGOutput, tabRef[GmfHexahedra] = 8; int ver, dim; - MESSAGE("Read " << theFile << " file"); int InpMsh = MGOutput->GmfOpenMesh(theFile, GmfRead, &ver, &dim); if (!InpMsh) return false; - MESSAGE("Done "); // Hybrid is not multi-domain => We can't (and don't need to) read ids of domains in ouput file like in GHS3DPlugin // We just need to get the id of the one and only solid @@ -789,7 +512,6 @@ static bool readGMFFile(MG_HYBRID_API* MGOutput, MGOutput->GmfGetLin(InpMsh, token, &id[iElem*tabRef[token]], &id[iElem*tabRef[token]+1], &id[iElem*tabRef[token]+2], &id[iElem*tabRef[token]+3], &domainID[iElem]); #ifdef _DEBUG_ subdomainId2tetraId[dummy].insert(iElem+1); -// MESSAGE("subdomainId2tetraId["< >::const_iterator subdomainIt = subdomainId2tetraId.begin(); - TCollection_AsciiString aSubdomainFileName = theFile; + std::string aSubdomainFileName = theFile; aSubdomainFileName = aSubdomainFileName + ".subdomain"; - ofstream aSubdomainFile ( aSubdomainFileName.ToCString() , ios::out); + ofstream aSubdomainFile ( aSubdomainFileName , ios::out); aSubdomainFile << "Nb subdomains " << subdomainId2tetraId.size() << std::endl; for(;subdomainIt != subdomainId2tetraId.end() ; ++subdomainIt) { int subdomainId = subdomainIt->first; std::set tetraIds = subdomainIt->second; - MESSAGE("Subdomain #"<::const_iterator tetraIdsIt = tetraIds.begin(); aSubdomainFile << subdomainId << std::endl; for(;tetraIdsIt != tetraIds.end() ; ++tetraIdsIt) { @@ -1088,8 +808,6 @@ static bool writeGMFFile(MG_HYBRID_API* MGInput std::map, std::string> & enfVerticesWithGroup, HYBRIDPlugin_Hypothesis::THYBRIDEnforcedVertexCoordsValues & theEnforcedVertices) { - //MESSAGE("writeGMFFile w/o geometry"); - std::cout << "!!!!!!!!!!!writeGMFFile w/o geometry for HYBRIDPLUGIN..." << std::endl; std::string tmpStr; int idx, idxRequired = 0, idxSol = 0; //tabg each dummyint @@ -1098,8 +816,8 @@ static bool writeGMFFile(MG_HYBRID_API* MGInput const int dummyint2 = 2; const int dummyint3 = 3; const int dummyint4 = 4; - const int dummyint5 = 5; - const int dummyint6 = 6; //are interesting for layers + const int enforcedTag = HYBRIDPlugin_Hypothesis::EnforcedTag(); + //const int dummyint6 = 6; //are interesting for layers HYBRIDPlugin_Hypothesis::THYBRIDEnforcedVertexCoordsValues::const_iterator vertexIt; std::vector enfVertexSizes; const SMDS_MeshElement* elem; @@ -1349,22 +1067,6 @@ static bool writeGMFFile(MG_HYBRID_API* MGInput continue; } -// gp_Pnt myPoint(node->X(),node->Y(),node->Z()); -// nbFoundElems = pntCls->FindElementsByPoint(myPoint, SMDSAbs_Node, foundElems); -// if (nbFoundElems ==0) { -// std::cout << " not found" << std::endl; -// if ((*aNodeToTopAbs_StateMap.find(node)).second == TopAbs_IN) { -// nodesCoords.insert(coords); -// theOrderedNodes.push_back(node); -// } -// } -// else { -// std::cout << " found in initial mesh" << std::endl; -// const SMDS_MeshNode* existingNode = (SMDS_MeshNode*) foundElems.at(0); -// nodesCoords.insert(coords); -// theOrderedNodes.push_back(existingNode); -// } - #ifdef _DEBUG_ std::cout << " not found" << std::endl; #endif @@ -1415,29 +1117,6 @@ static bool writeGMFFile(MG_HYBRID_API* MGInput continue; } -// nbFoundElems = pntCls->FindElementsByPoint(myPoint, SMDSAbs_Node, foundElems); -// if (nbFoundElems ==0) { -// std::cout << " not found" << std::endl; -// if (result == TopAbs_IN) { -// nodesCoords.insert(coords); -// theRequiredNodes.push_back(node); -// } -// } -// else { -// std::cout << " found in initial mesh" << std::endl; -// const SMDS_MeshNode* existingNode = (SMDS_MeshNode*) foundElems.at(0); -// // nodesCoords.insert(coords); -// theRequiredNodes.push_back(existingNode); -// } -// -// -// -// if (pntCls->FindElementsByPoint(myPoint, SMDSAbs_Node, foundElems) == 0) -// continue; - -// if ( result != TopAbs_IN ) -// continue; - #ifdef _DEBUG_ std::cout << " not found" << std::endl; #endif @@ -1450,7 +1129,6 @@ static bool writeGMFFile(MG_HYBRID_API* MGInput int solSize = 0; std::vector > ReqVerTab; if (nbEnforcedVertices) { -// ReqVerTab.clear(); (nbEnforcedVertices <= 1) ? tmpStr = " node" : " nodes"; std::cout << nbEnforcedVertices << tmpStr << " from enforced vertices ..." << std::endl; // Iterate over the enforced vertices @@ -1463,11 +1141,6 @@ static bool writeGMFFile(MG_HYBRID_API* MGInput TopAbs_State result = pntCls->GetPointState( myPoint ); if ( result == TopAbs_OUT ) continue; - //if (pntCls->FindElementsByPoint(myPoint, SMDSAbs_Node, foundElems) == 0) - //continue; - -// if ( result != TopAbs_IN ) -// continue; std::vector coords; coords.push_back(x); coords.push_back(y); @@ -1482,7 +1155,7 @@ static bool writeGMFFile(MG_HYBRID_API* MGInput // GmfVertices std::cout << "Begin writing required nodes in GmfVertices" << std::endl; std::cout << "Nb vertices: " << theOrderedNodes.size() << std::endl; - MGInput->GmfSetKwd(idx, GmfVertices, theOrderedNodes.size()); //theOrderedNodes.size()+solSize) + MGInput->GmfSetKwd(idx, GmfVertices, theOrderedNodes.size()); for (hybridNodeIt = theOrderedNodes.begin();hybridNodeIt != theOrderedNodes.end();++hybridNodeIt) { MGInput->GmfSetLin(idx, GmfVertices, (*hybridNodeIt)->X(), (*hybridNodeIt)->Y(), (*hybridNodeIt)->Z(), dummyint1); } @@ -1508,8 +1181,6 @@ static bool writeGMFFile(MG_HYBRID_API* MGInput double ValTab[] = {0.0}; MGInput->GmfSetKwd(idxRequired, GmfVertices, requiredNodes + solSize); MGInput->GmfSetKwd(idxSol, GmfSolAtVertices, requiredNodes + solSize, 1, TypTab); -// int usedEnforcedNodes = 0; -// std::string gn = ""; for (hybridNodeIt = theRequiredNodes.begin();hybridNodeIt != theRequiredNodes.end();++hybridNodeIt) { MGInput->GmfSetLin(idxRequired, GmfVertices, (*hybridNodeIt)->X(), (*hybridNodeIt)->Y(), (*hybridNodeIt)->Z(), dummyint2); MGInput->GmfSetLin(idxSol, GmfSolAtVertices, ValTab); @@ -1542,11 +1213,7 @@ static bool writeGMFFile(MG_HYBRID_API* MGInput int usedEnforcedEdges = 0; if (theKeptEnforcedEdges.size()) { anEdgeGroupByHybridId.resize( theKeptEnforcedEdges.size() ); -// idxRequired = MGInput->GmfOpenMesh(theRequiredFileName, GmfWrite, GMFVERSION, GMFDIMENSION); -// if (!idxRequired) -// return false; MGInput->GmfSetKwd(idx, GmfEdges, theKeptEnforcedEdges.size()); -// MGInput->GmfSetKwd(idxRequired, GmfEdges, theKeptEnforcedEdges.size()); for(elemSetIt = theKeptEnforcedEdges.begin() ; elemSetIt != theKeptEnforcedEdges.end() ; ++elemSetIt) { elem = (*elemSetIt); nodeIt = elem->nodesIterator(); @@ -1565,10 +1232,8 @@ static bool writeGMFFile(MG_HYBRID_API* MGInput } MGInput->GmfSetLin(idx, GmfEdges, nedge[0], nedge[1], dummyint4); anEdgeGroupByHybridId[usedEnforcedEdges] = theEnforcedEdges.find(elem)->second; -// MGInput->GmfSetLin(idxRequired, GmfEdges, nedge[0], nedge[1], dummyint); usedEnforcedEdges++; } -// MGInput->GmfCloseMesh(idxRequired); } @@ -1581,16 +1246,19 @@ static bool writeGMFFile(MG_HYBRID_API* MGInput // GmfTriangles int usedEnforcedTriangles = 0; - if (anElemSetTri.size()+theKeptEnforcedTriangles.size()) { + if (anElemSetTri.size()+theKeptEnforcedTriangles.size()) + { aFaceGroupByHybridId.resize( anElemSetTri.size()+theKeptEnforcedTriangles.size() ); MGInput->GmfSetKwd(idx, GmfTriangles, anElemSetTri.size()+theKeptEnforcedTriangles.size()); int k=0; - for(elemSetIt = anElemSetTri.begin() ; elemSetIt != anElemSetTri.end() ; ++elemSetIt,++k) { + for(elemSetIt = anElemSetTri.begin() ; elemSetIt != anElemSetTri.end() ; ++elemSetIt,++k) + { elem = (*elemSetIt); theFaceByHybridId.push_back( elem ); nodeIt = elem->nodesIterator(); int index=0; - for ( int j = 0; j < 3; ++j ) { + for ( int j = 0; j < 3; ++j ) + { // find HYBRID ID const SMDS_MeshNode* node = castToNode( nodeIt->next() ); std::map< const SMDS_MeshNode*,int >::iterator it = aNodeToHybridIdMap.find(node); @@ -1599,22 +1267,26 @@ static bool writeGMFFile(MG_HYBRID_API* MGInput ntri[index] = it->second; index++; } - MGInput->GmfSetLin(idx, GmfTriangles, ntri[0], ntri[1], ntri[2], dummyint5); + MGInput->GmfSetLin(idx, GmfTriangles, ntri[0], ntri[1], ntri[2], /*tag=*/elem->getshapeId() ); aFaceGroupByHybridId[k] = ""; } if ( !theHelper.GetMesh()->HasShapeToMesh() ) SMESHUtils::FreeVector( theFaceByHybridId ); std::cout << "Enforced triangles size " << theKeptEnforcedTriangles.size() << std::endl; - if (theKeptEnforcedTriangles.size()) { - for(elemSetIt = theKeptEnforcedTriangles.begin() ; elemSetIt != theKeptEnforcedTriangles.end() ; ++elemSetIt,++k) { + if (theKeptEnforcedTriangles.size()) + { + for(elemSetIt = theKeptEnforcedTriangles.begin() ; elemSetIt != theKeptEnforcedTriangles.end() ; ++elemSetIt,++k) + { elem = (*elemSetIt); nodeIt = elem->nodesIterator(); int index=0; - for ( int j = 0; j < 3; ++j ) { + for ( int j = 0; j < 3; ++j ) + { // find HYBRID ID const SMDS_MeshNode* node = castToNode( nodeIt->next() ); std::map< const SMDS_MeshNode*,int >::iterator it = anEnforcedNodeToHybridIdMap.find(node); - if (it == anEnforcedNodeToHybridIdMap.end()) { + if (it == anEnforcedNodeToHybridIdMap.end()) + { it = anExistingEnforcedNodeToHybridIdMap.find(node); if (it == anEnforcedNodeToHybridIdMap.end()) throw "Node not found"; @@ -1622,7 +1294,7 @@ static bool writeGMFFile(MG_HYBRID_API* MGInput ntri[index] = it->second; index++; } - MGInput->GmfSetLin(idx, GmfTriangles, ntri[0], ntri[1], ntri[2], dummyint6); + MGInput->GmfSetLin(idx, GmfTriangles, ntri[0], ntri[1], ntri[2], enforcedTag); aFaceGroupByHybridId[k] = theEnforcedTriangles.find(elem)->second; usedEnforcedTriangles++; } @@ -1630,21 +1302,25 @@ static bool writeGMFFile(MG_HYBRID_API* MGInput } - if (usedEnforcedTriangles) { + if (usedEnforcedTriangles) + { MGInput->GmfSetKwd(idx, GmfRequiredTriangles, usedEnforcedTriangles); for (int enfID=1;enfID<=usedEnforcedTriangles;enfID++) MGInput->GmfSetLin(idx, GmfRequiredTriangles, anElemSetTri.size()+enfID); } - if (anElemSetQuad.size()) { + if (anElemSetQuad.size()) + { MGInput->GmfSetKwd(idx, GmfQuadrilaterals, anElemSetQuad.size()); int k=0; - for(elemSetIt = anElemSetQuad.begin() ; elemSetIt != anElemSetQuad.end() ; ++elemSetIt,++k) { + for(elemSetIt = anElemSetQuad.begin() ; elemSetIt != anElemSetQuad.end() ; ++elemSetIt,++k) + { elem = (*elemSetIt); theFaceByHybridId.push_back( elem ); nodeIt = elem->nodesIterator(); int index=0; - for ( int j = 0; j < 4; ++j ) { + for ( int j = 0; j < 4; ++j ) + { // find HYBRID ID const SMDS_MeshNode* node = castToNode( nodeIt->next() ); std::map< const SMDS_MeshNode*,int >::iterator it = aNodeToHybridIdMap.find(node); @@ -1653,7 +1329,8 @@ static bool writeGMFFile(MG_HYBRID_API* MGInput nquad[index] = it->second; index++; } - MGInput->GmfSetLin(idx, GmfQuadrilaterals, nquad[0], nquad[1], nquad[2], nquad[3], dummyint5); + MGInput->GmfSetLin(idx, GmfQuadrilaterals, nquad[0], nquad[1], nquad[2], nquad[3], + /*tag=*/elem->getshapeId() ); // _CEA_cbo what is it for??? //aFaceGroupByHybridId[k] = ""; } @@ -1669,1217 +1346,6 @@ static bool writeGMFFile(MG_HYBRID_API* MGInput } -// static bool writeGMFFile(const char* theMeshFileName, -// const char* theRequiredFileName, -// const char* theSolFileName, -// SMESH_MesherHelper& theHelper, -// const SMESH_ProxyMesh& theProxyMesh, -// std::map & theNodeId2NodeIndexMap, -// std::map & theSmdsToHybridIdMap, -// std::map & theHybridIdToNodeMap, -// TIDSortedNodeSet & theEnforcedNodes, -// TIDSortedElemSet & theEnforcedEdges, -// TIDSortedElemSet & theEnforcedTriangles, -// // TIDSortedElemSet & theEnforcedQuadrangles, -// HYBRIDPlugin_Hypothesis::THYBRIDEnforcedVertexCoordsValues & theEnforcedVertices) -// { -// MESSAGE("writeGMFFile with geometry"); -// int idx, idxRequired, idxSol; -// int nbv, nbev, nben, aHybridID = 0; -// const int dummyint = 0; -// HYBRIDPlugin_Hypothesis::THYBRIDEnforcedVertexCoordsValues::const_iterator vertexIt; -// std::vector enfVertexSizes; -// TIDSortedNodeSet::const_iterator enfNodeIt; -// const SMDS_MeshNode* node; -// SMDS_NodeIteratorPtr nodeIt; -// -// idx = GmfOpenMesh(theMeshFileName, GmfWrite, GMFVERSION, GMFDIMENSION); -// if (!idx) -// return false; -// -// SMESHDS_Mesh * theMeshDS = theHelper.GetMeshDS(); -// -// /* ========================== NODES ========================== */ -// // NB_NODES -// nbv = theMeshDS->NbNodes(); -// if ( nbv == 0 ) -// return false; -// nbev = theEnforcedVertices.size(); -// nben = theEnforcedNodes.size(); -// -// // Issue 020674: EDF 870 SMESH: Mesh generated by Netgen not usable by HYBRID -// // The problem is in nodes on degenerated edges, we need to skip nodes which are free -// // and replace not-free nodes on edges by the node on vertex -// TNodeNodeMap n2nDegen; // map a node on degenerated edge to a node on vertex -// TNodeNodeMap::iterator n2nDegenIt; -// if ( theHelper.HasDegeneratedEdges() ) -// { -// set checkedSM; -// for (TopExp_Explorer e(theMeshDS->ShapeToMesh(), TopAbs_EDGE ); e.More(); e.Next()) -// { -// SMESH_subMesh* sm = theHelper.GetMesh()->GetSubMesh( e.Current() ); -// if ( checkedSM.insert( sm->GetId() ).second && theHelper.IsDegenShape(sm->GetId() )) -// { -// if ( SMESHDS_SubMesh* smDS = sm->GetSubMeshDS() ) -// { -// TopoDS_Shape vertex = TopoDS_Iterator( e.Current() ).Value(); -// const SMDS_MeshNode* vNode = SMESH_Algo::VertexNode( TopoDS::Vertex( vertex ), theMeshDS); -// { -// SMDS_NodeIteratorPtr nIt = smDS->GetNodes(); -// while ( nIt->more() ) -// n2nDegen.insert( std::make_pair( nIt->next(), vNode )); -// } -// } -// } -// } -// } -// -// const bool isQuadMesh = -// theHelper.GetMesh()->NbEdges( ORDER_QUADRATIC ) || -// theHelper.GetMesh()->NbFaces( ORDER_QUADRATIC ) || -// theHelper.GetMesh()->NbVolumes( ORDER_QUADRATIC ); -// -// std::vector > VerTab; -// std::set > VerMap; -// VerTab.clear(); -// std::vector aVerTab; -// // Loop from 1 to NB_NODES -// -// nodeIt = theMeshDS->nodesIterator(); -// -// while ( nodeIt->more() ) -// { -// node = nodeIt->next(); -// if ( isQuadMesh && theHelper.IsMedium( node )) // Issue 0021238 -// continue; -// if ( n2nDegen.count( node ) ) // Issue 0020674 -// continue; -// -// std::vector coords; -// coords.push_back(node->X()); -// coords.push_back(node->Y()); -// coords.push_back(node->Z()); -// if (VerMap.find(coords) != VerMap.end()) { -// aHybridID = theSmdsToHybridIdMap[node->GetID()]; -// theHybridIdToNodeMap[theSmdsToHybridIdMap[node->GetID()]] = node; -// continue; -// } -// VerTab.push_back(coords); -// VerMap.insert(coords); -// aHybridID++; -// theSmdsToHybridIdMap.insert( std::make_pair( node->GetID(), aHybridID )); -// theHybridIdToNodeMap.insert( std::make_pair( aHybridID, node )); -// } -// -// -// /* ENFORCED NODES ========================== */ -// if (nben) { -// std::cout << "Add " << nben << " enforced nodes to input .mesh file" << std::endl; -// for(enfNodeIt = theEnforcedNodes.begin() ; enfNodeIt != theEnforcedNodes.end() ; ++enfNodeIt) { -// double x = (*enfNodeIt)->X(); -// double y = (*enfNodeIt)->Y(); -// double z = (*enfNodeIt)->Z(); -// // Test if point is inside shape to mesh -// gp_Pnt myPoint(x,y,z); -// BRepClass3d_SolidClassifier scl(theMeshDS->ShapeToMesh()); -// scl.Perform(myPoint, 1e-7); -// TopAbs_State result = scl.State(); -// if ( result != TopAbs_IN ) -// continue; -// std::vector coords; -// coords.push_back(x); -// coords.push_back(y); -// coords.push_back(z); -// if (theEnforcedVertices.find(coords) != theEnforcedVertices.end()) -// continue; -// if (VerMap.find(coords) != VerMap.end()) -// continue; -// VerTab.push_back(coords); -// VerMap.insert(coords); -// aHybridID++; -// theNodeId2NodeIndexMap.insert( std::make_pair( (*enfNodeIt)->GetID(), aHybridID )); -// } -// } -// -// -// /* ENFORCED VERTICES ========================== */ -// int solSize = 0; -// std::vector > ReqVerTab; -// ReqVerTab.clear(); -// if (nbev) { -// std::cout << "Add " << nbev << " enforced vertices to input .mesh file" << std::endl; -// for(vertexIt = theEnforcedVertices.begin() ; vertexIt != theEnforcedVertices.end() ; ++vertexIt) { -// double x = vertexIt->first[0]; -// double y = vertexIt->first[1]; -// double z = vertexIt->first[2]; -// // Test if point is inside shape to mesh -// gp_Pnt myPoint(x,y,z); -// BRepClass3d_SolidClassifier scl(theMeshDS->ShapeToMesh()); -// scl.Perform(myPoint, 1e-7); -// TopAbs_State result = scl.State(); -// if ( result != TopAbs_IN ) -// continue; -// enfVertexSizes.push_back(vertexIt->second); -// std::vector coords; -// coords.push_back(x); -// coords.push_back(y); -// coords.push_back(z); -// if (VerMap.find(coords) != VerMap.end()) -// continue; -// ReqVerTab.push_back(coords); -// VerMap.insert(coords); -// solSize++; -// } -// } -// -// -// /* ========================== FACES ========================== */ -// -// int nbTriangles = 0/*, nbQuadrangles = 0*/, aSmdsID; -// TopTools_IndexedMapOfShape facesMap, trianglesMap/*, quadranglesMap*/; -// TIDSortedElemSet::const_iterator elemIt; -// const SMESHDS_SubMesh* theSubMesh; -// TopoDS_Shape aShape; -// SMDS_ElemIteratorPtr itOnSubMesh, itOnSubFace; -// const SMDS_MeshElement* aFace; -// map::const_iterator itOnMap; -// std::vector > tt, qt,et; -// tt.clear(); -// qt.clear(); -// et.clear(); -// std::vector att, aqt, aet; -// -// TopExp::MapShapes( theMeshDS->ShapeToMesh(), TopAbs_FACE, facesMap ); -// -// for ( int i = 1; i <= facesMap.Extent(); ++i ) -// if (( theSubMesh = theProxyMesh.GetSubMesh( facesMap(i)))) -// { -// SMDS_ElemIteratorPtr it = theSubMesh->GetElements(); -// while (it->more()) -// { -// const SMDS_MeshElement *elem = it->next(); -// int nbCornerNodes = elem->NbCornerNodes(); -// if (nbCornerNodes == 3) -// { -// trianglesMap.Add(facesMap(i)); -// nbTriangles ++; -// } -// // else if (nbCornerNodes == 4) -// // { -// // quadranglesMap.Add(facesMap(i)); -// // nbQuadrangles ++; -// // } -// } -// } -// -// /* TRIANGLES ========================== */ -// if (nbTriangles) { -// for ( int i = 1; i <= trianglesMap.Extent(); i++ ) -// { -// aShape = trianglesMap(i); -// theSubMesh = theProxyMesh.GetSubMesh(aShape); -// if ( !theSubMesh ) continue; -// itOnSubMesh = theSubMesh->GetElements(); -// while ( itOnSubMesh->more() ) -// { -// aFace = itOnSubMesh->next(); -// itOnSubFace = aFace->nodesIterator(); -// att.clear(); -// for ( int j = 0; j < 3; ++j ) { -// // find HYBRID ID -// node = castToNode( itOnSubFace->next() ); -// if (( n2nDegenIt = n2nDegen.find( node )) != n2nDegen.end() ) -// node = n2nDegenIt->second; -// aSmdsID = node->GetID(); -// itOnMap = theSmdsToHybridIdMap.find( aSmdsID ); -// ASSERT( itOnMap != theSmdsToHybridIdMap.end() ); -// att.push_back((*itOnMap).second); -// } -// tt.push_back(att); -// } -// } -// } -// -// if (theEnforcedTriangles.size()) { -// std::cout << "Add " << theEnforcedTriangles.size() << " enforced triangles to input .mesh file" << std::endl; -// // Iterate over the enforced triangles -// for(elemIt = theEnforcedTriangles.begin() ; elemIt != theEnforcedTriangles.end() ; ++elemIt) { -// aFace = (*elemIt); -// itOnSubFace = aFace->nodesIterator(); -// bool isOK = true; -// att.clear(); -// -// for ( int j = 0; j < 3; ++j ) { -// node = castToNode( itOnSubFace->next() ); -// if (( n2nDegenIt = n2nDegen.find( node )) != n2nDegen.end() ) -// node = n2nDegenIt->second; -// // std::cout << node; -// double x = node->X(); -// double y = node->Y(); -// double z = node->Z(); -// // Test if point is inside shape to mesh -// gp_Pnt myPoint(x,y,z); -// BRepClass3d_SolidClassifier scl(theMeshDS->ShapeToMesh()); -// scl.Perform(myPoint, 1e-7); -// TopAbs_State result = scl.State(); -// if ( result != TopAbs_IN ) { -// isOK = false; -// theEnforcedTriangles.erase(elemIt); -// continue; -// } -// std::vector coords; -// coords.push_back(x); -// coords.push_back(y); -// coords.push_back(z); -// if (VerMap.find(coords) != VerMap.end()) { -// att.push_back(theNodeId2NodeIndexMap[node->GetID()]); -// continue; -// } -// VerTab.push_back(coords); -// VerMap.insert(coords); -// aHybridID++; -// theNodeId2NodeIndexMap.insert( std::make_pair( node->GetID(), aHybridID )); -// att.push_back(aHybridID); -// } -// if (isOK) -// tt.push_back(att); -// } -// } -// -// -// /* ========================== EDGES ========================== */ -// -// if (theEnforcedEdges.size()) { -// // Iterate over the enforced edges -// std::cout << "Add " << theEnforcedEdges.size() << " enforced edges to input .mesh file" << std::endl; -// for(elemIt = theEnforcedEdges.begin() ; elemIt != theEnforcedEdges.end() ; ++elemIt) { -// aFace = (*elemIt); -// bool isOK = true; -// itOnSubFace = aFace->nodesIterator(); -// aet.clear(); -// for ( int j = 0; j < 2; ++j ) { -// node = castToNode( itOnSubFace->next() ); -// if (( n2nDegenIt = n2nDegen.find( node )) != n2nDegen.end() ) -// node = n2nDegenIt->second; -// double x = node->X(); -// double y = node->Y(); -// double z = node->Z(); -// // Test if point is inside shape to mesh -// gp_Pnt myPoint(x,y,z); -// BRepClass3d_SolidClassifier scl(theMeshDS->ShapeToMesh()); -// scl.Perform(myPoint, 1e-7); -// TopAbs_State result = scl.State(); -// if ( result != TopAbs_IN ) { -// isOK = false; -// theEnforcedEdges.erase(elemIt); -// continue; -// } -// std::vector coords; -// coords.push_back(x); -// coords.push_back(y); -// coords.push_back(z); -// if (VerMap.find(coords) != VerMap.end()) { -// aet.push_back(theNodeId2NodeIndexMap[node->GetID()]); -// continue; -// } -// VerTab.push_back(coords); -// VerMap.insert(coords); -// -// aHybridID++; -// theNodeId2NodeIndexMap.insert( std::make_pair( node->GetID(), aHybridID )); -// aet.push_back(aHybridID); -// } -// if (isOK) -// et.push_back(aet); -// } -// } -// -// -// /* Write vertices number */ -// MESSAGE("Number of vertices: "<GetElements(); -// // for ( int j = 0; j < 4; ++j ) -// // { -// // aFace = itOnSubMesh->next(); -// // itOnSubFace = aFace->nodesIterator(); -// // aqt.clear(); -// // while ( itOnSubFace->more() ) { -// // // find HYBRID ID -// // aSmdsID = itOnSubFace->next()->GetID(); -// // itOnMap = theSmdsToHybridIdMap.find( aSmdsID ); -// // ASSERT( itOnMap != theSmdsToHybridIdMap.end() ); -// // aqt.push_back((*itOnMap).second); -// // } -// // qt.push_back(aqt); -// // } -// // } -// // } -// // -// // if (theEnforcedQuadrangles.size()) { -// // // Iterate over the enforced triangles -// // for(elemIt = theEnforcedQuadrangles.begin() ; elemIt != theEnforcedQuadrangles.end() ; ++elemIt) { -// // aFace = (*elemIt); -// // bool isOK = true; -// // itOnSubFace = aFace->nodesIterator(); -// // aqt.clear(); -// // for ( int j = 0; j < 4; ++j ) { -// // int aNodeID = itOnSubFace->next()->GetID(); -// // itOnMap = theNodeId2NodeIndexMap.find(aNodeID); -// // if (itOnMap != theNodeId2NodeIndexMap.end()) -// // aqt.push_back((*itOnMap).second); -// // else { -// // isOK = false; -// // theEnforcedQuadrangles.erase(elemIt); -// // break; -// // } -// // } -// // if (isOK) -// // qt.push_back(aqt); -// // } -// // } -// // -// -// // /* Write quadrilaterals number */ -// // if (qt.size()) { -// // GmfSetKwd(idx, GmfQuadrilaterals, qt.size()); -// // for (int i=0;i & theSmdsToHybridIdMap, -// const std::map & theEnforcedNodeIdToHybridIdMap, -// HYBRIDPlugin_Hypothesis::TIDSortedElemGroupMap & theEnforcedEdges, -// HYBRIDPlugin_Hypothesis::TIDSortedElemGroupMap & theEnforcedTriangles) -// { -// // record structure: -// // -// // NB_ELEMS DUMMY_INT -// // Loop from 1 to NB_ELEMS -// // NB_NODES NODE_NB_1 NODE_NB_2 ... (NB_NODES + 1) times: DUMMY_INT - -// TopoDS_Shape aShape; -// const SMESHDS_SubMesh* theSubMesh; -// const SMDS_MeshElement* aFace; -// const char* space = " "; -// const int dummyint = 0; -// std::map::const_iterator itOnMap; -// SMDS_ElemIteratorPtr itOnSubMesh, itOnSubFace; -// int nbNodes, aSmdsID; - -// TIDSortedElemSet::const_iterator elemIt; -// int nbEnforcedEdges = theEnforcedEdges.size(); -// int nbEnforcedTriangles = theEnforcedTriangles.size(); - -// // count triangles bound to geometry -// int nbTriangles = 0; - -// TopTools_IndexedMapOfShape facesMap, trianglesMap; -// TopExp::MapShapes( theShape, TopAbs_FACE, facesMap ); - -// int nbFaces = facesMap.Extent(); - -// for ( int i = 1; i <= nbFaces; ++i ) -// if (( theSubMesh = theMesh.GetSubMesh( facesMap(i)))) -// nbTriangles += theSubMesh->NbElements(); -// std::string tmpStr; -// (nbFaces == 0 || nbFaces == 1) ? tmpStr = " shape " : tmpStr = " shapes " ; -// std::cout << " " << nbFaces << tmpStr << "of 2D dimension"; -// int nbEnforcedElements = nbEnforcedEdges+nbEnforcedTriangles; -// if (nbEnforcedElements > 0) { -// (nbEnforcedElements == 1) ? tmpStr = "shape:" : tmpStr = "shapes:"; -// std::cout << " and" << std::endl; -// std::cout << " " << nbEnforcedElements -// << " enforced " << tmpStr << std::endl; -// } -// else -// std::cout << std::endl; -// if (nbEnforcedEdges) { -// (nbEnforcedEdges == 1) ? tmpStr = "edge" : tmpStr = "edges"; -// std::cout << " " << nbEnforcedEdges << " enforced " << tmpStr << std::endl; -// } -// if (nbEnforcedTriangles) { -// (nbEnforcedTriangles == 1) ? tmpStr = "triangle" : tmpStr = "triangles"; -// std::cout << " " << nbEnforcedTriangles << " enforced " << tmpStr << std::endl; -// } -// std::cout << std::endl; - -// // theFile << space << nbTriangles << space << dummyint << std::endl; -// std::ostringstream globalStream, localStream, aStream; - -// for ( int i = 1; i <= facesMap.Extent(); i++ ) -// { -// aShape = facesMap(i); -// theSubMesh = theMesh.GetSubMesh(aShape); -// if ( !theSubMesh ) continue; -// itOnSubMesh = theSubMesh->GetElements(); -// while ( itOnSubMesh->more() ) -// { -// aFace = itOnSubMesh->next(); -// nbNodes = aFace->NbCornerNodes(); - -// localStream << nbNodes << space; - -// itOnSubFace = aFace->nodesIterator(); -// for ( int j = 0; j < 3; ++j ) { -// // find HYBRID ID -// aSmdsID = itOnSubFace->next()->GetID(); -// itOnMap = theSmdsToHybridIdMap.find( aSmdsID ); -// // if ( itOnMap == theSmdsToHybridIdMap.end() ) { -// // cout << "not found node: " << aSmdsID << endl; -// // return false; -// // } -// ASSERT( itOnMap != theSmdsToHybridIdMap.end() ); - -// localStream << (*itOnMap).second << space ; -// } - -// // (NB_NODES + 1) times: DUMMY_INT -// for ( int j=0; j<=nbNodes; j++) -// localStream << dummyint << space ; - -// localStream << std::endl; -// } -// } - -// globalStream << localStream.str(); -// localStream.str(""); - -// // -// // FACES : END -// // - -// // // -// // // ENFORCED EDGES : BEGIN -// // // -// // -// // // Iterate over the enforced edges -// // int usedEnforcedEdges = 0; -// // bool isOK; -// // for(elemIt = theEnforcedEdges.begin() ; elemIt != theEnforcedEdges.end() ; ++elemIt) { -// // aFace = (*elemIt); -// // isOK = true; -// // itOnSubFace = aFace->nodesIterator(); -// // aStream.str(""); -// // aStream << "2" << space ; -// // for ( int j = 0; j < 2; ++j ) { -// // aSmdsID = itOnSubFace->next()->GetID(); -// // itOnMap = theEnforcedNodeIdToHybridIdMap.find(aSmdsID); -// // if (itOnMap != theEnforcedNodeIdToHybridIdMap.end()) -// // aStream << (*itOnMap).second << space; -// // else { -// // isOK = false; -// // break; -// // } -// // } -// // if (isOK) { -// // for ( int j=0; j<=2; j++) -// // aStream << dummyint << space ; -// // // aStream << dummyint << space << dummyint; -// // localStream << aStream.str() << std::endl; -// // usedEnforcedEdges++; -// // } -// // } -// // -// // if (usedEnforcedEdges) { -// // globalStream << localStream.str(); -// // localStream.str(""); -// // } -// // -// // // -// // // ENFORCED EDGES : END -// // // -// // // -// // -// // // -// // // ENFORCED TRIANGLES : BEGIN -// // // -// // // Iterate over the enforced triangles -// // int usedEnforcedTriangles = 0; -// // for(elemIt = theEnforcedTriangles.begin() ; elemIt != theEnforcedTriangles.end() ; ++elemIt) { -// // aFace = (*elemIt); -// // nbNodes = aFace->NbCornerNodes(); -// // isOK = true; -// // itOnSubFace = aFace->nodesIterator(); -// // aStream.str(""); -// // aStream << nbNodes << space ; -// // for ( int j = 0; j < 3; ++j ) { -// // aSmdsID = itOnSubFace->next()->GetID(); -// // itOnMap = theEnforcedNodeIdToHybridIdMap.find(aSmdsID); -// // if (itOnMap != theEnforcedNodeIdToHybridIdMap.end()) -// // aStream << (*itOnMap).second << space; -// // else { -// // isOK = false; -// // break; -// // } -// // } -// // if (isOK) { -// // for ( int j=0; j<=3; j++) -// // aStream << dummyint << space ; -// // localStream << aStream.str() << std::endl; -// // usedEnforcedTriangles++; -// // } -// // } -// // -// // if (usedEnforcedTriangles) { -// // globalStream << localStream.str(); -// // localStream.str(""); -// // } -// // -// // // -// // // ENFORCED TRIANGLES : END -// // // - -// theFile -// << nbTriangles/*+usedEnforcedTriangles+usedEnforcedEdges*/ -// << " 0" << std::endl -// << globalStream.str(); - -// return true; -// } - -//======================================================================= -//function : writePoints -//purpose : -//======================================================================= - -// static bool writePoints (ofstream & theFile, -// SMESH_MesherHelper& theHelper, -// std::map & theSmdsToHybridIdMap, -// std::map & theEnforcedNodeIdToHybridIdMap, -// std::map & theHybridIdToNodeMap, -// HYBRIDPlugin_Hypothesis::TID2SizeMap & theNodeIDToSizeMap, -// HYBRIDPlugin_Hypothesis::THYBRIDEnforcedVertexCoordsValues & theEnforcedVertices, -// HYBRIDPlugin_Hypothesis::TIDSortedNodeGroupMap & theEnforcedNodes, -// HYBRIDPlugin_Hypothesis::TIDSortedElemGroupMap & theEnforcedEdges, -// HYBRIDPlugin_Hypothesis::TIDSortedElemGroupMap & theEnforcedTriangles) -// { -// // record structure: -// // -// // NB_NODES -// // Loop from 1 to NB_NODES -// // X Y Z DUMMY_INT - -// SMESHDS_Mesh * theMeshDS = theHelper.GetMeshDS(); -// int nbNodes = theMeshDS->NbNodes(); -// if ( nbNodes == 0 ) -// return false; - -// int nbEnforcedVertices = theEnforcedVertices.size(); -// int nbEnforcedNodes = theEnforcedNodes.size(); - -// const TopoDS_Shape shapeToMesh = theMeshDS->ShapeToMesh(); - -// int aHybridID = 1; -// SMDS_NodeIteratorPtr nodeIt = theMeshDS->nodesIterator(); -// const SMDS_MeshNode* node; - -// // Issue 020674: EDF 870 SMESH: Mesh generated by Netgen not usable by HYBRID -// // The problem is in nodes on degenerated edges, we need to skip nodes which are free -// // and replace not-free nodes on degenerated edges by the node on vertex -// TNodeNodeMap n2nDegen; // map a node on degenerated edge to a node on vertex -// TNodeNodeMap::iterator n2nDegenIt; -// if ( theHelper.HasDegeneratedEdges() ) -// { -// std::set checkedSM; -// for (TopExp_Explorer e(theMeshDS->ShapeToMesh(), TopAbs_EDGE ); e.More(); e.Next()) -// { -// SMESH_subMesh* sm = theHelper.GetMesh()->GetSubMesh( e.Current() ); -// if ( checkedSM.insert( sm->GetId() ).second && theHelper.IsDegenShape(sm->GetId() )) -// { -// if ( SMESHDS_SubMesh* smDS = sm->GetSubMeshDS() ) -// { -// TopoDS_Shape vertex = TopoDS_Iterator( e.Current() ).Value(); -// const SMDS_MeshNode* vNode = SMESH_Algo::VertexNode( TopoDS::Vertex( vertex ), theMeshDS); -// { -// SMDS_NodeIteratorPtr nIt = smDS->GetNodes(); -// while ( nIt->more() ) -// n2nDegen.insert( std::make_pair( nIt->next(), vNode )); -// } -// } -// } -// } -// nbNodes -= n2nDegen.size(); -// } - -// const bool isQuadMesh = -// theHelper.GetMesh()->NbEdges( ORDER_QUADRATIC ) || -// theHelper.GetMesh()->NbFaces( ORDER_QUADRATIC ) || -// theHelper.GetMesh()->NbVolumes( ORDER_QUADRATIC ); -// if ( isQuadMesh ) -// { -// // descrease nbNodes by nb of medium nodes -// while ( nodeIt->more() ) -// { -// node = nodeIt->next(); -// if ( !theHelper.IsDegenShape( node->getshapeId() )) -// nbNodes -= int( theHelper.IsMedium( node )); -// } -// nodeIt = theMeshDS->nodesIterator(); -// } - -// const char* space = " "; -// const int dummyint = 0; - -// std::string tmpStr; -// (nbNodes == 0 || nbNodes == 1) ? tmpStr = " node" : tmpStr = " nodes"; -// // NB_NODES -// std::cout << std::endl; -// std::cout << "The initial 2D mesh contains :" << std::endl; -// std::cout << " " << nbNodes << tmpStr << std::endl; -// if (nbEnforcedVertices > 0) { -// (nbEnforcedVertices == 1) ? tmpStr = "vertex" : tmpStr = "vertices"; -// std::cout << " " << nbEnforcedVertices << " enforced " << tmpStr << std::endl; -// } -// if (nbEnforcedNodes > 0) { -// (nbEnforcedNodes == 1) ? tmpStr = "node" : tmpStr = "nodes"; -// std::cout << " " << nbEnforcedNodes << " enforced " << tmpStr << std::endl; -// } -// std::cout << std::endl; -// std::cout << "Start writing in 'points' file ..." << std::endl; - -// theFile << nbNodes << std::endl; - -// // Loop from 1 to NB_NODES - -// while ( nodeIt->more() ) -// { -// node = nodeIt->next(); -// if ( isQuadMesh && theHelper.IsMedium( node )) // Issue 0021238 -// continue; -// if ( n2nDegen.count( node ) ) // Issue 0020674 -// continue; - -// theSmdsToHybridIdMap.insert( std::make_pair( node->GetID(), aHybridID )); -// theHybridIdToNodeMap.insert( std::make_pair( aHybridID, node )); -// aHybridID++; - -// // X Y Z DUMMY_INT -// theFile -// << node->X() << space -// << node->Y() << space -// << node->Z() << space -// << dummyint; - -// theFile << std::endl; - -// } - -// // Iterate over the enforced nodes -// std::map enfVertexIndexSizeMap; -// if (nbEnforcedNodes) { -// HYBRIDPlugin_Hypothesis::TIDSortedNodeGroupMap::const_iterator nodeIt = theEnforcedNodes.begin(); -// for( ; nodeIt != theEnforcedNodes.end() ; ++nodeIt) { -// double x = nodeIt->first->X(); -// double y = nodeIt->first->Y(); -// double z = nodeIt->first->Z(); -// // Test if point is inside shape to mesh -// gp_Pnt myPoint(x,y,z); -// BRepClass3d_SolidClassifier scl(shapeToMesh); -// scl.Perform(myPoint, 1e-7); -// TopAbs_State result = scl.State(); -// if ( result != TopAbs_IN ) -// continue; -// std::vector coords; -// coords.push_back(x); -// coords.push_back(y); -// coords.push_back(z); -// if (theEnforcedVertices.find(coords) != theEnforcedVertices.end()) -// continue; - -// // double size = theNodeIDToSizeMap.find(nodeIt->first->GetID())->second; -// // theHybridIdToNodeMap.insert( std::make_pair( nbNodes + i, (*nodeIt) )); -// // MESSAGE("Adding enforced node (" << x << "," << y <<"," << z << ")"); -// // X Y Z PHY_SIZE DUMMY_INT -// theFile -// << x << space -// << y << space -// << z << space -// << -1 << space -// << dummyint << space; -// theFile << std::endl; -// theEnforcedNodeIdToHybridIdMap.insert( std::make_pair( nodeIt->first->GetID(), aHybridID )); -// enfVertexIndexSizeMap[aHybridID] = -1; -// aHybridID++; -// // else -// // MESSAGE("Enforced vertex (" << x << "," << y <<"," << z << ") is not inside the geometry: it was not added "); -// } -// } - -// if (nbEnforcedVertices) { -// // Iterate over the enforced vertices -// HYBRIDPlugin_Hypothesis::THYBRIDEnforcedVertexCoordsValues::const_iterator vertexIt = theEnforcedVertices.begin(); -// for( ; vertexIt != theEnforcedVertices.end() ; ++vertexIt) { -// double x = vertexIt->first[0]; -// double y = vertexIt->first[1]; -// double z = vertexIt->first[2]; -// // Test if point is inside shape to mesh -// gp_Pnt myPoint(x,y,z); -// BRepClass3d_SolidClassifier scl(shapeToMesh); -// scl.Perform(myPoint, 1e-7); -// TopAbs_State result = scl.State(); -// if ( result != TopAbs_IN ) -// continue; -// MESSAGE("Adding enforced vertex (" << x << "," << y <<"," << z << ") = " << vertexIt->second); -// // X Y Z PHY_SIZE DUMMY_INT -// theFile -// << x << space -// << y << space -// << z << space -// << vertexIt->second << space -// << dummyint << space; -// theFile << std::endl; -// enfVertexIndexSizeMap[aHybridID] = vertexIt->second; -// aHybridID++; -// } -// } - - -// std::cout << std::endl; -// std::cout << "End writing in 'points' file." << std::endl; - -// return true; -// } - -//======================================================================= -//function : readResultFile -//purpose : readResultFile with geometry -//======================================================================= - -// static bool readResultFile(const int fileOpen, -// #ifdef WIN32 -// const char* fileName, -// #endif -// HYBRIDPlugin_HYBRID* theAlgo, -// SMESH_MesherHelper& theHelper, -// TopoDS_Shape tabShape[], -// double** tabBox, -// const int nbShape, -// std::map & theHybridIdToNodeMap, -// std::map & theNodeId2NodeIndexMap, -// bool toMeshHoles, -// int nbEnforcedVertices, -// int nbEnforcedNodes, -// HYBRIDPlugin_Hypothesis::TIDSortedElemGroupMap & theEnforcedEdges, -// HYBRIDPlugin_Hypothesis::TIDSortedElemGroupMap & theEnforcedTriangles, -// bool toMakeGroupsOfDomains) -// { -// MESSAGE("HYBRIDPlugin_HYBRID::readResultFile()"); -// Kernel_Utils::Localizer loc; -// struct stat status; -// size_t length; - -// std::string tmpStr; - -// char *ptr, *mapPtr; -// char *tetraPtr; -// char *shapePtr; - -// SMESHDS_Mesh* theMeshDS = theHelper.GetMeshDS(); - -// int nbElems, nbNodes, nbInputNodes; -// int nbTriangle; -// int ID, shapeID, hybridShapeID; -// int IdShapeRef = 1; -// int compoundID = -// nbShape ? theMeshDS->ShapeToIndex( tabShape[0] ) : theMeshDS->ShapeToIndex( theMeshDS->ShapeToMesh() ); - -// int *tab, *tabID, *nodeID, *nodeAssigne; -// double *coord; -// const SMDS_MeshNode **node; - -// tab = new int[3]; -// nodeID = new int[4]; -// coord = new double[3]; -// node = new const SMDS_MeshNode*[4]; - -// TopoDS_Shape aSolid; -// SMDS_MeshNode * aNewNode; -// std::map ::iterator itOnNode; -// SMDS_MeshElement* aTet; -// #ifdef _DEBUG_ -// std::set shapeIDs; -// #endif - -// // Read the file state -// fstat(fileOpen, &status); -// length = status.st_size; - -// // Mapping the result file into memory -// #ifdef WIN32 -// HANDLE fd = CreateFile(fileName, GENERIC_READ, FILE_SHARE_READ, -// NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); -// HANDLE hMapObject = CreateFileMapping(fd, NULL, PAGE_READONLY, -// 0, (DWORD)length, NULL); -// ptr = ( char* ) MapViewOfFile(hMapObject, FILE_MAP_READ, 0, 0, 0 ); -// #else -// ptr = (char *) mmap(0,length,PROT_READ,MAP_PRIVATE,fileOpen,0); -// #endif -// mapPtr = ptr; - -// ptr = readMapIntLine(ptr, tab); -// tetraPtr = ptr; - -// nbElems = tab[0]; -// nbNodes = tab[1]; -// nbInputNodes = tab[2]; - -// nodeAssigne = new int[ nbNodes+1 ]; - -// if (nbShape > 0) -// aSolid = tabShape[0]; - -// // Reading the nodeId -// for (int i=0; i < 4*nbElems; i++) -// strtol(ptr, &ptr, 10); - -// MESSAGE("nbInputNodes: "<computeCanceled()) -// return false; -// for (int iCoor=0; iCoor < 3; iCoor++) -// coord[ iCoor ] = strtod(ptr, &ptr); -// nodeAssigne[ iNode ] = 1; -// if ( iNode > (nbInputNodes-(nbEnforcedVertices+nbEnforcedNodes)) ) { -// // Creating SMESH nodes -// // - for enforced vertices -// // - for vertices of forced edges -// // - for hybrid nodes -// nodeAssigne[ iNode ] = 0; -// aNewNode = theMeshDS->AddNode( coord[0],coord[1],coord[2] ); -// theHybridIdToNodeMap.insert(theHybridIdToNodeMap.end(), std::make_pair( iNode, aNewNode )); -// } -// } - -// // Reading the number of triangles which corresponds to the number of sub-domains -// nbTriangle = strtol(ptr, &ptr, 10); - -// tabID = new int[nbTriangle]; -// for (int i=0; i < nbTriangle; i++) { -// if(theAlgo->computeCanceled()) -// return false; -// tabID[i] = 0; -// // find the solid corresponding to HYBRID sub-domain following -// // the technique proposed in HYBRID manual in chapter -// // "B.4 Subdomain (sub-region) assignment" -// int nodeId1 = strtol(ptr, &ptr, 10); -// int nodeId2 = strtol(ptr, &ptr, 10); -// int nodeId3 = strtol(ptr, &ptr, 10); -// if ( nbTriangle > 1 ) { -// const SMDS_MeshNode* n1 = theHybridIdToNodeMap[ nodeId1 ]; -// const SMDS_MeshNode* n2 = theHybridIdToNodeMap[ nodeId2 ]; -// const SMDS_MeshNode* n3 = theHybridIdToNodeMap[ nodeId3 ]; -// if (!n1 || !n2 || !n3) { -// tabID[i] = HOLE_ID; -// continue; -// } -// try { -// OCC_CATCH_SIGNALS; -// // tabID[i] = findShapeID( theHelper, n1, n2, n3, toMeshHoles ); -// tabID[i] = findShapeID( *theHelper.GetMesh(), n1, n2, n3, toMeshHoles ); -// // -- 0020330: Pb with hybrid as a submesh -// // check that found shape is to be meshed -// if ( tabID[i] > 0 ) { -// const TopoDS_Shape& foundShape = theMeshDS->IndexToShape( tabID[i] ); -// bool isToBeMeshed = false; -// for ( int iS = 0; !isToBeMeshed && iS < nbShape; ++iS ) -// isToBeMeshed = foundShape.IsSame( tabShape[ iS ]); -// if ( !isToBeMeshed ) -// tabID[i] = HOLE_ID; -// } -// // END -- 0020330: Pb with hybrid as a submesh -// #ifdef _DEBUG_ -// std::cout << i+1 << " subdomain: findShapeID() returns " << tabID[i] << std::endl; -// #endif -// } -// catch ( Standard_Failure & ex) -// { -// #ifdef _DEBUG_ -// std::cout << i+1 << " subdomain: Exception caugt: " << ex.GetMessageString() << std::endl; -// #endif -// } -// catch (...) { -// #ifdef _DEBUG_ -// std::cout << i+1 << " subdomain: unknown exception caught " << std::endl; -// #endif -// } -// } -// } - -// shapePtr = ptr; - -// if ( nbTriangle <= nbShape ) // no holes -// toMeshHoles = true; // not avoid creating tetras in holes - -// // IMP 0022172: [CEA 790] create the groups corresponding to domains -// std::vector< std::vector< const SMDS_MeshElement* > > elemsOfDomain( Max( nbTriangle, nbShape )); - -// // Associating the tetrahedrons to the shapes -// shapeID = compoundID; -// for (int iElem = 0; iElem < nbElems; iElem++) { -// if(theAlgo->computeCanceled()) -// return false; -// for (int iNode = 0; iNode < 4; iNode++) { -// ID = strtol(tetraPtr, &tetraPtr, 10); -// itOnNode = theHybridIdToNodeMap.find(ID); -// node[ iNode ] = itOnNode->second; -// nodeID[ iNode ] = ID; -// } -// // We always run HYBRID with "to mesh holes"==TRUE but we must not create -// // tetras within holes depending on hypo option, -// // so we first check if aTet is inside a hole and then create it -// //aTet = theMeshDS->AddVolume( node[1], node[0], node[2], node[3] ); -// hybridShapeID = 0; // domain ID -// if ( nbTriangle > 1 ) { -// shapeID = HOLE_ID; // negative shapeID means not to create tetras if !toMeshHoles -// hybridShapeID = strtol(shapePtr, &shapePtr, 10) - IdShapeRef; -// if ( tabID[ hybridShapeID ] == 0 ) { -// TopAbs_State state; -// aSolid = findShape(node, aSolid, tabShape, tabBox, nbShape, &state); -// if ( toMeshHoles || state == TopAbs_IN ) -// shapeID = theMeshDS->ShapeToIndex( aSolid ); -// tabID[ hybridShapeID ] = shapeID; -// } -// else -// shapeID = tabID[ hybridShapeID ]; -// } -// else if ( nbShape > 1 ) { -// // Case where nbTriangle == 1 while nbShape == 2 encountered -// // with compound of 2 boxes and "To mesh holes"==False, -// // so there are no subdomains specified for each tetrahedron. -// // Try to guess a solid by a node already bound to shape -// shapeID = 0; -// for ( int i=0; i<4 && shapeID==0; i++ ) { -// if ( nodeAssigne[ nodeID[i] ] == 1 && -// node[i]->GetPosition()->GetTypeOfPosition() == SMDS_TOP_3DSPACE && -// node[i]->getshapeId() > 1 ) -// { -// shapeID = node[i]->getshapeId(); -// } -// } -// if ( shapeID==0 ) { -// aSolid = findShape(node, aSolid, tabShape, tabBox, nbShape); -// shapeID = theMeshDS->ShapeToIndex( aSolid ); -// } -// } -// // set new nodes and tetrahedron onto the shape -// for ( int i=0; i<4; i++ ) { -// if ( nodeAssigne[ nodeID[i] ] == 0 ) { -// if ( shapeID != HOLE_ID ) -// theMeshDS->SetNodeInVolume( node[i], shapeID ); -// nodeAssigne[ nodeID[i] ] = shapeID; -// } -// } -// if ( toMeshHoles || shapeID != HOLE_ID ) { -// aTet = theHelper.AddVolume( node[1], node[0], node[2], node[3], -// /*id=*/0, /*force3d=*/false); -// theMeshDS->SetMeshElementOnShape( aTet, shapeID ); -// if ( toMakeGroupsOfDomains ) -// { -// if ( int( elemsOfDomain.size() ) < hybridShapeID+1 ) -// elemsOfDomain.resize( hybridShapeID+1 ); -// elemsOfDomain[ hybridShapeID ].push_back( aTet ); -// } -// } -// #ifdef _DEBUG_ -// shapeIDs.insert( shapeID ); -// #endif -// } -// if ( toMakeGroupsOfDomains ) -// makeDomainGroups( elemsOfDomain, &theHelper ); - -// // Add enforced elements -// HYBRIDPlugin_Hypothesis::TIDSortedElemGroupMap::const_iterator elemIt; -// const SMDS_MeshElement* anElem; -// SMDS_ElemIteratorPtr itOnEnfElem; -// std::map::const_iterator itOnMap; -// shapeID = compoundID; -// // Enforced edges -// if (theEnforcedEdges.size()) { -// (theEnforcedEdges.size() <= 1) ? tmpStr = " enforced edge" : " enforced edges"; -// std::cout << "Add " << theEnforcedEdges.size() << tmpStr << std::endl; -// std::vector< const SMDS_MeshNode* > node( 2 ); -// // Iterate over the enforced edges -// for(elemIt = theEnforcedEdges.begin() ; elemIt != theEnforcedEdges.end() ; ++elemIt) { -// anElem = elemIt->first; -// bool addElem = true; -// itOnEnfElem = anElem->nodesIterator(); -// for ( int j = 0; j < 2; ++j ) { -// int aNodeID = itOnEnfElem->next()->GetID(); -// itOnMap = theNodeId2NodeIndexMap.find(aNodeID); -// if (itOnMap != theNodeId2NodeIndexMap.end()) { -// itOnNode = theHybridIdToNodeMap.find((*itOnMap).second); -// if (itOnNode != theHybridIdToNodeMap.end()) { -// node.push_back((*itOnNode).second); -// // shapeID =(*itOnNode).second->getshapeId(); -// } -// else -// addElem = false; -// } -// else -// addElem = false; -// } -// if (addElem) { -// aTet = theHelper.AddEdge( node[0], node[1], 0, false); -// theMeshDS->SetMeshElementOnShape( aTet, shapeID ); -// } -// } -// } -// // Enforced faces -// if (theEnforcedTriangles.size()) { -// (theEnforcedTriangles.size() <= 1) ? tmpStr = " enforced triangle" : " enforced triangles"; -// std::cout << "Add " << theEnforcedTriangles.size() << " enforced triangles" << std::endl; -// std::vector< const SMDS_MeshNode* > node( 3 ); -// // Iterate over the enforced triangles -// for(elemIt = theEnforcedTriangles.begin() ; elemIt != theEnforcedTriangles.end() ; ++elemIt) { -// anElem = elemIt->first; -// bool addElem = true; -// itOnEnfElem = anElem->nodesIterator(); -// for ( int j = 0; j < 3; ++j ) { -// int aNodeID = itOnEnfElem->next()->GetID(); -// itOnMap = theNodeId2NodeIndexMap.find(aNodeID); -// if (itOnMap != theNodeId2NodeIndexMap.end()) { -// itOnNode = theHybridIdToNodeMap.find((*itOnMap).second); -// if (itOnNode != theHybridIdToNodeMap.end()) { -// node.push_back((*itOnNode).second); -// // shapeID =(*itOnNode).second->getshapeId(); -// } -// else -// addElem = false; -// } -// else -// addElem = false; -// } -// if (addElem) { -// aTet = theHelper.AddFace( node[0], node[1], node[2], 0, false); -// theMeshDS->SetMeshElementOnShape( aTet, shapeID ); -// } -// } -// } - -// // Remove nodes of tetras inside holes if !toMeshHoles -// if ( !toMeshHoles ) { -// itOnNode = theHybridIdToNodeMap.find( nbInputNodes ); -// for ( ; itOnNode != theHybridIdToNodeMap.end(); ++itOnNode) { -// ID = itOnNode->first; -// if ( nodeAssigne[ ID ] == HOLE_ID ) -// theMeshDS->RemoveFreeNode( itOnNode->second, 0 ); -// } -// } - - -// if ( nbElems ) { -// (nbElems <= 1) ? tmpStr = " tetrahedra" : " tetrahedrons"; -// cout << nbElems << tmpStr << " have been associated to " << nbShape; -// (nbShape <= 1) ? tmpStr = " shape" : " shapes"; -// cout << tmpStr << endl; -// } -// #ifdef WIN32 -// UnmapViewOfFile(mapPtr); -// CloseHandle(hMapObject); -// CloseHandle(fd); -// #else -// munmap(mapPtr, length); -// #endif -// close(fileOpen); - -// delete [] tab; -// delete [] tabID; -// delete [] nodeID; -// delete [] coord; -// delete [] node; -// delete [] nodeAssigne; - -// #ifdef _DEBUG_ -// shapeIDs.erase(-1); -// if ((int) shapeIDs.size() != nbShape ) { -// (shapeIDs.size() <= 1) ? tmpStr = " solid" : " solids"; -// std::cout << "Only " << shapeIDs.size() << tmpStr << " of " << nbShape << " found" << std::endl; -// for (int i=0; iShapeToIndex( tabShape[i] ); -// if ( shapeIDs.find( shapeID ) == shapeIDs.end() ) -// std::cout << " Solid #" << shapeID << " not found" << std::endl; -// } -// } -// #endif - -// return true; -// } - - //============================================================================= /*! *Here we are going to use the HYBRID mesher with geometry @@ -2894,35 +1360,26 @@ bool HYBRIDPlugin_HYBRID::Compute(SMESH_Mesh& theMesh, // a unique working file name // to avoid access to the same files by eg different users _genericName = HYBRIDPlugin_Hypothesis::GetFileName(_hyp); - TCollection_AsciiString aGenericName((char*) _genericName.c_str() ); - TCollection_AsciiString aGenericNameRequired = aGenericName + "_required"; + std::string aGenericName = _genericName; + std::string aGenericNameRequired = aGenericName + "_required"; - TCollection_AsciiString aLogFileName = aGenericName + ".log"; // log - TCollection_AsciiString aResultFileName; + std::string aLogFileName = aGenericName + ".log"; // log + std::string aResultFileName; - TCollection_AsciiString aGMFFileName, aRequiredVerticesFileName, aSolFileName, aResSolFileName; -//#ifdef _DEBUG_ + std::string aGMFFileName, aRequiredVerticesFileName, aSolFileName, aResSolFileName; aGMFFileName = aGenericName + ".mesh"; // GMF mesh file aResultFileName = aGenericName + "Vol.mesh"; // GMF mesh file aResSolFileName = aGenericName + "Vol.sol"; // GMF mesh file aRequiredVerticesFileName = aGenericNameRequired + ".mesh"; // GMF required vertices mesh file aSolFileName = aGenericNameRequired + ".sol"; // GMF solution file -//#else -// aGMFFileName = aGenericName + ".meshb"; // GMF mesh file -// aResultFileName = aGenericName + "Vol.meshb"; // GMF mesh file -// aRequiredVerticesFileName = aGenericNameRequired + ".meshb"; // GMF required vertices mesh file -// aSolFileName = aGenericNameRequired + ".solb"; // GMF solution file -//#endif std::map aNodeId2NodeIndexMap, aSmdsToHybridIdMap, anEnforcedNodeIdToHybridIdMap; - //std::map aHybridIdToNodeMap; std::map nodeID2nodeIndexMap; std::map, std::string> enfVerticesWithGroup; HYBRIDPlugin_Hypothesis::THYBRIDEnforcedVertexCoordsValues coordsSizeMap = HYBRIDPlugin_Hypothesis::GetEnforcedVerticesCoordsSize(_hyp); HYBRIDPlugin_Hypothesis::TIDSortedNodeGroupMap enforcedNodes = HYBRIDPlugin_Hypothesis::GetEnforcedNodes(_hyp); HYBRIDPlugin_Hypothesis::TIDSortedElemGroupMap enforcedEdges = HYBRIDPlugin_Hypothesis::GetEnforcedEdges(_hyp); HYBRIDPlugin_Hypothesis::TIDSortedElemGroupMap enforcedTriangles = HYBRIDPlugin_Hypothesis::GetEnforcedTriangles(_hyp); -// TIDSortedElemSet enforcedQuadrangles = HYBRIDPlugin_Hypothesis::GetEnforcedQuadrangles(_hyp); HYBRIDPlugin_Hypothesis::TID2SizeMap nodeIDToSizeMap = HYBRIDPlugin_Hypothesis::GetNodeIDToSizeMap(_hyp); HYBRIDPlugin_Hypothesis::THYBRIDEnforcedVertexList enfVertices = HYBRIDPlugin_Hypothesis::GetEnforcedVertices(_hyp); @@ -2932,53 +1389,30 @@ bool HYBRIDPlugin_HYBRID::Compute(SMESH_Mesh& theMesh, for ( ; enfVerIt != enfVertices.end() ; ++enfVerIt) { HYBRIDPlugin_Hypothesis::THYBRIDEnforcedVertex* enfVertex = (*enfVerIt); -// if (enfVertex->geomEntry.empty() && enfVertex->coords.size()) { if (enfVertex->coords.size()) { coordsSizeMap.insert(std::make_pair(enfVertex->coords,enfVertex->size)); enfVerticesWithGroup.insert(std::make_pair(enfVertex->coords,enfVertex->groupName)); -// MESSAGE("enfVerticesWithGroup.insert(std::make_pair(("<coords[0]<<","<coords[1]<<","<coords[2]<<"),\""<groupName<<"\"))"); } else { -// if (!enfVertex->geomEntry.empty()) { TopoDS_Shape GeomShape = entryToShape(enfVertex->geomEntry); -// GeomType = GeomShape.ShapeType(); - -// if (!enfVertex->isCompound) { -// // if (GeomType == TopAbs_VERTEX) { -// coords.clear(); -// aPnt = BRep_Tool::Pnt(TopoDS::Vertex(GeomShape)); -// coords.push_back(aPnt.X()); -// coords.push_back(aPnt.Y()); -// coords.push_back(aPnt.Z()); -// if (coordsSizeMap.find(coords) == coordsSizeMap.end()) { -// coordsSizeMap.insert(std::make_pair(coords,enfVertex->size)); -// enfVerticesWithGroup.insert(std::make_pair(coords,enfVertex->groupName)); -// } -// } -// -// // Group Management -// else { -// if (GeomType == TopAbs_COMPOUND){ - for (TopoDS_Iterator it (GeomShape); it.More(); it.Next()){ - coords.clear(); - if (it.Value().ShapeType() == TopAbs_VERTEX){ - gp_Pnt aPnt = BRep_Tool::Pnt(TopoDS::Vertex(it.Value())); - coords.push_back(aPnt.X()); - coords.push_back(aPnt.Y()); - coords.push_back(aPnt.Z()); - if (coordsSizeMap.find(coords) == coordsSizeMap.end()) { - coordsSizeMap.insert(std::make_pair(coords,enfVertex->size)); - enfVerticesWithGroup.insert(std::make_pair(coords,enfVertex->groupName)); -// MESSAGE("enfVerticesWithGroup.insert(std::make_pair(("<groupName<<"\"))"); - } + for (TopoDS_Iterator it (GeomShape); it.More(); it.Next()){ + coords.clear(); + if (it.Value().ShapeType() == TopAbs_VERTEX){ + gp_Pnt aPnt = BRep_Tool::Pnt(TopoDS::Vertex(it.Value())); + coords.push_back(aPnt.X()); + coords.push_back(aPnt.Y()); + coords.push_back(aPnt.Z()); + if (coordsSizeMap.find(coords) == coordsSizeMap.end()) { + coordsSizeMap.insert(std::make_pair(coords,enfVertex->size)); + enfVerticesWithGroup.insert(std::make_pair(coords,enfVertex->groupName)); } } -// } + } } } int nbEnforcedVertices = coordsSizeMap.size(); int nbEnforcedNodes = enforcedNodes.size(); - + std::string tmpStr; (nbEnforcedNodes <= 1) ? tmpStr = "node" : "nodes"; std::cout << nbEnforcedNodes << " enforced " << tmpStr << " from hypo" << std::endl; @@ -2998,9 +1432,9 @@ bool HYBRIDPlugin_HYBRID::Compute(SMESH_Mesh& theMesh, MG_HYBRID_API mgHybrid( _computeCanceled, _progress ); Ok = writeGMFFile(&mgHybrid, - aGMFFileName.ToCString(), - aRequiredVerticesFileName.ToCString(), - aSolFileName.ToCString(), + aGMFFileName.c_str(), + aRequiredVerticesFileName.c_str(), + aSolFileName.c_str(), *proxyMesh, helper, aNodeByHybridId, aFaceByHybridId, aNodeToHybridIdMap, aNodeGroupByHybridId, anEdgeGroupByHybridId, aFaceGroupByHybridId, @@ -3008,9 +1442,9 @@ bool HYBRIDPlugin_HYBRID::Compute(SMESH_Mesh& theMesh, enfVerticesWithGroup, coordsSizeMap); // Write aSmdsToHybridIdMap to temp file - TCollection_AsciiString aSmdsToHybridIdMapFileName; + std::string aSmdsToHybridIdMapFileName; aSmdsToHybridIdMapFileName = aGenericName + ".ids"; // ids relation - ofstream aIdsFile ( aSmdsToHybridIdMapFileName.ToCString() , ios::out); + ofstream aIdsFile ( aSmdsToHybridIdMapFileName , ios::out); Ok = aIdsFile.rdbuf()->is_open(); if (!Ok) { INFOS( "Can't write into " << aSmdsToHybridIdMapFileName); @@ -3040,23 +1474,21 @@ bool HYBRIDPlugin_HYBRID::Compute(SMESH_Mesh& theMesh, // run hybrid mesher // ----------------- - TCollection_AsciiString cmd( (char*)HYBRIDPlugin_Hypothesis::CommandToRun( _hyp ).c_str() ); + std::string cmd = HYBRIDPlugin_Hypothesis::CommandToRun( _hyp, theMesh ); if ( mgHybrid.IsExecutable() ) { - cmd += TCollection_AsciiString(" --in ") + aGMFFileName; - //if ( nbEnforcedVertices + nbEnforcedNodes) - // cmd += TCollection_AsciiString(" --required_vertices ") + aGenericNameRequired; - cmd += TCollection_AsciiString(" --out ") + aResultFileName; + cmd += " --in " + aGMFFileName; + cmd += " --out " + aResultFileName; } std::cout << std::endl; std::cout << "Hybrid execution with geometry..." << std::endl; std::cout << cmd; if ( !_logInStandardOutput ) { - mgHybrid.SetLogFile( aLogFileName.ToCString() ); + mgHybrid.SetLogFile( aLogFileName ); if ( mgHybrid.IsExecutable() ) - cmd += TCollection_AsciiString(" 1>" ) + aLogFileName; // dump into file + cmd += " 1>" + aLogFileName; // dump into file std::cout << " 1> " << aLogFileName; } std::cout << std::endl; @@ -3064,7 +1496,7 @@ bool HYBRIDPlugin_HYBRID::Compute(SMESH_Mesh& theMesh, _computeCanceled = false; std::string errStr; - Ok = mgHybrid.Compute( cmd.ToCString(), errStr ); // run + Ok = mgHybrid.Compute( cmd, errStr ); // run if ( _logInStandardOutput && mgHybrid.IsLibrary() ) std::cout << std::endl << mgHybrid.GetLog() << std::endl; @@ -3077,22 +1509,21 @@ bool HYBRIDPlugin_HYBRID::Compute(SMESH_Mesh& theMesh, // Mapping the result file - HYBRIDPlugin_Hypothesis::TSetStrings groupsToRemove = HYBRIDPlugin_Hypothesis::GetGroupsToRemove(_hyp); - bool toMeshHoles = - _hyp ? _hyp->GetToMeshHoles(true) : HYBRIDPlugin_Hypothesis::DefaultMeshHoles(); - const bool toMakeGroupsOfDomains = HYBRIDPlugin_Hypothesis::GetToMakeGroupsOfDomains( _hyp ); + HYBRIDPlugin_Hypothesis::TSetStrings groupsToRemove = HYBRIDPlugin_Hypothesis::GetGroupsToRemove(_hyp); + bool toMeshHoles = + _hyp ? _hyp->GetToMeshHoles(true) : HYBRIDPlugin_Hypothesis::DefaultMeshHoles(); + const bool toMakeGroupsOfDomains = HYBRIDPlugin_Hypothesis::GetToMakeGroupsOfDomains( _hyp ); - helper.IsQuadraticSubMesh( theShape ); - helper.SetElementsOnShape( false ); - - Ok = readGMFFile(&mgHybrid, aResultFileName.ToCString(), - this, - &helper, aNodeByHybridId, aFaceByHybridId, aNodeToHybridIdMap, - aNodeGroupByHybridId, anEdgeGroupByHybridId, aFaceGroupByHybridId, - groupsToRemove, toMakeGroupsOfDomains, toMeshHoles); + helper.IsQuadraticSubMesh( theShape ); + helper.SetElementsOnShape( false ); - removeEmptyGroupsOfDomains( helper.GetMesh(), !toMakeGroupsOfDomains ); + Ok = readGMFFile(&mgHybrid, aResultFileName.c_str(), + this, + &helper, aNodeByHybridId, aFaceByHybridId, aNodeToHybridIdMap, + aNodeGroupByHybridId, anEdgeGroupByHybridId, aFaceGroupByHybridId, + groupsToRemove, toMakeGroupsOfDomains, toMeshHoles); + removeEmptyGroupsOfDomains( helper.GetMesh(), !toMakeGroupsOfDomains ); @@ -3104,15 +1535,12 @@ bool HYBRIDPlugin_HYBRID::Compute(SMESH_Mesh& theMesh, { if ( _removeLogOnSuccess ) removeFile( aLogFileName ); - - // if ( _hyp && _hyp->GetToMakeGroupsOfDomains() ) - // error( COMPERR_WARNING, "'toMakeGroupsOfDomains' is ignored since the mesh is on shape" ); } else if ( mgHybrid.HasLog() ) { // get problem description from the log file _Ghs2smdsConvertor conv( aNodeByHybridId ); - storeErrorDescription( _logInStandardOutput ? 0 : aLogFileName.ToCString(), + storeErrorDescription( _logInStandardOutput ? 0 : aLogFileName.c_str(), mgHybrid.GetLog(), conv ); } else if ( !errStr.empty() ) @@ -3135,7 +1563,7 @@ bool HYBRIDPlugin_HYBRID::Compute(SMESH_Mesh& theMesh, } if ( mgHybrid.IsExecutable() ) { - std::cout << "<" << aResultFileName.ToCString() << "> HYBRID output file "; + std::cout << "<" << aResultFileName << "> HYBRID output file "; if ( !Ok ) std::cout << "not "; std::cout << "treated !" << std::endl; @@ -3157,39 +1585,29 @@ bool HYBRIDPlugin_HYBRID::Compute(SMESH_Mesh& theMesh, bool HYBRIDPlugin_HYBRID::Compute(SMESH_Mesh& theMesh, SMESH_MesherHelper* theHelper) { - MESSAGE("HYBRIDPlugin_HYBRID::Compute()"); - theHelper->IsQuadraticSubMesh( theHelper->GetSubShape() ); // a unique working file name // to avoid access to the same files by eg different users _genericName = HYBRIDPlugin_Hypothesis::GetFileName(_hyp); - TCollection_AsciiString aGenericName((char*) _genericName.c_str() ); - TCollection_AsciiString aGenericNameRequired = aGenericName + "_required"; + std::string aGenericName((char*) _genericName.c_str() ); + std::string aGenericNameRequired = aGenericName + "_required"; - TCollection_AsciiString aLogFileName = aGenericName + ".log"; // log - TCollection_AsciiString aResultFileName; + std::string aLogFileName = aGenericName + ".log"; // log + std::string aResultFileName; bool Ok; - TCollection_AsciiString aGMFFileName, aRequiredVerticesFileName, aSolFileName, aResSolFileName; -//#ifdef _DEBUG_ + std::string aGMFFileName, aRequiredVerticesFileName, aSolFileName, aResSolFileName; aGMFFileName = aGenericName + ".mesh"; // GMF mesh file aResultFileName = aGenericName + "Vol.mesh"; // GMF mesh file aResSolFileName = aGenericName + "Vol.sol"; // GMF mesh file aRequiredVerticesFileName = aGenericNameRequired + ".mesh"; // GMF required vertices mesh file aSolFileName = aGenericNameRequired + ".sol"; // GMF solution file -//#else -// aGMFFileName = aGenericName + ".meshb"; // GMF mesh file -// aResultFileName = aGenericName + "Vol.meshb"; // GMF mesh file -// aRequiredVerticesFileName = aGenericNameRequired + ".meshb"; // GMF required vertices mesh file -// aSolFileName = aGenericNameRequired + ".solb"; // GMF solution file -//#endif std::map nodeID2nodeIndexMap; std::map, std::string> enfVerticesWithGroup; HYBRIDPlugin_Hypothesis::THYBRIDEnforcedVertexCoordsValues coordsSizeMap; TopoDS_Shape GeomShape; -// TopAbs_ShapeEnum GeomType; std::vector coords; gp_Pnt aPnt; HYBRIDPlugin_Hypothesis::THYBRIDEnforcedVertex* enfVertex; @@ -3200,69 +1618,31 @@ bool HYBRIDPlugin_HYBRID::Compute(SMESH_Mesh& theMesh, for ( ; enfVerIt != enfVertices.end() ; ++enfVerIt) { enfVertex = (*enfVerIt); -// if (enfVertex->geomEntry.empty() && enfVertex->coords.size()) { if (enfVertex->coords.size()) { coordsSizeMap.insert(std::make_pair(enfVertex->coords,enfVertex->size)); enfVerticesWithGroup.insert(std::make_pair(enfVertex->coords,enfVertex->groupName)); -// MESSAGE("enfVerticesWithGroup.insert(std::make_pair(("<coords[0]<<","<coords[1]<<","<coords[2]<<"),\""<groupName<<"\"))"); } else { -// if (!enfVertex->geomEntry.empty()) { GeomShape = entryToShape(enfVertex->geomEntry); -// GeomType = GeomShape.ShapeType(); - -// if (!enfVertex->isCompound) { -// // if (GeomType == TopAbs_VERTEX) { -// coords.clear(); -// aPnt = BRep_Tool::Pnt(TopoDS::Vertex(GeomShape)); -// coords.push_back(aPnt.X()); -// coords.push_back(aPnt.Y()); -// coords.push_back(aPnt.Z()); -// if (coordsSizeMap.find(coords) == coordsSizeMap.end()) { -// coordsSizeMap.insert(std::make_pair(coords,enfVertex->size)); -// enfVerticesWithGroup.insert(std::make_pair(coords,enfVertex->groupName)); -// } -// } -// -// // Group Management -// else { -// if (GeomType == TopAbs_COMPOUND){ - for (TopoDS_Iterator it (GeomShape); it.More(); it.Next()){ - coords.clear(); - if (it.Value().ShapeType() == TopAbs_VERTEX){ - aPnt = BRep_Tool::Pnt(TopoDS::Vertex(it.Value())); - coords.push_back(aPnt.X()); - coords.push_back(aPnt.Y()); - coords.push_back(aPnt.Z()); - if (coordsSizeMap.find(coords) == coordsSizeMap.end()) { - coordsSizeMap.insert(std::make_pair(coords,enfVertex->size)); - enfVerticesWithGroup.insert(std::make_pair(coords,enfVertex->groupName)); -// MESSAGE("enfVerticesWithGroup.insert(std::make_pair(("<groupName<<"\"))"); - } + for (TopoDS_Iterator it (GeomShape); it.More(); it.Next()){ + coords.clear(); + if (it.Value().ShapeType() == TopAbs_VERTEX){ + aPnt = BRep_Tool::Pnt(TopoDS::Vertex(it.Value())); + coords.push_back(aPnt.X()); + coords.push_back(aPnt.Y()); + coords.push_back(aPnt.Z()); + if (coordsSizeMap.find(coords) == coordsSizeMap.end()) { + coordsSizeMap.insert(std::make_pair(coords,enfVertex->size)); + enfVerticesWithGroup.insert(std::make_pair(coords,enfVertex->groupName)); } } -// } + } } } -// const SMDS_MeshNode* enfNode; HYBRIDPlugin_Hypothesis::TIDSortedNodeGroupMap enforcedNodes = HYBRIDPlugin_Hypothesis::GetEnforcedNodes(_hyp); -// HYBRIDPlugin_Hypothesis::TIDSortedNodeGroupMap::const_iterator enfNodeIt = enforcedNodes.begin(); -// for ( ; enfNodeIt != enforcedNodes.end() ; ++enfNodeIt) -// { -// enfNode = enfNodeIt->first; -// coords.clear(); -// coords.push_back(enfNode->X()); -// coords.push_back(enfNode->Y()); -// coords.push_back(enfNode->Z()); -// if (enfVerticesWithGro -// enfVerticesWithGroup.insert(std::make_pair(coords,enfNodeIt->second)); -// } - - HYBRIDPlugin_Hypothesis::TIDSortedElemGroupMap enforcedEdges = HYBRIDPlugin_Hypothesis::GetEnforcedEdges(_hyp); HYBRIDPlugin_Hypothesis::TIDSortedElemGroupMap enforcedTriangles = HYBRIDPlugin_Hypothesis::GetEnforcedTriangles(_hyp); -// TIDSortedElemSet enforcedQuadrangles = HYBRIDPlugin_Hypothesis::GetEnforcedQuadrangles(_hyp); HYBRIDPlugin_Hypothesis::TID2SizeMap nodeIDToSizeMap = HYBRIDPlugin_Hypothesis::GetNodeIDToSizeMap(_hyp); std::string tmpStr; @@ -3284,8 +1664,8 @@ bool HYBRIDPlugin_HYBRID::Compute(SMESH_Mesh& theMesh, MG_HYBRID_API mgHybrid( _computeCanceled, _progress ); Ok = writeGMFFile(&mgHybrid, - aGMFFileName.ToCString(), - aRequiredVerticesFileName.ToCString(), aSolFileName.ToCString(), + aGMFFileName.c_str(), + aRequiredVerticesFileName.c_str(), aSolFileName.c_str(), *proxyMesh, *theHelper, aNodeByHybridId, aFaceByHybridId, aNodeToHybridIdMap, aNodeGroupByHybridId, anEdgeGroupByHybridId, aFaceGroupByHybridId, @@ -3296,19 +1676,17 @@ bool HYBRIDPlugin_HYBRID::Compute(SMESH_Mesh& theMesh, // run hybrid mesher // ----------------- - TCollection_AsciiString cmd = HYBRIDPlugin_Hypothesis::CommandToRun( _hyp, false ).c_str(); + std::string cmd = HYBRIDPlugin_Hypothesis::CommandToRun( _hyp, theMesh ); if ( mgHybrid.IsExecutable() ) { - cmd += TCollection_AsciiString(" --in ") + aGMFFileName; - //if ( nbEnforcedVertices + nbEnforcedNodes) - // cmd += TCollection_AsciiString(" --required_vertices ") + aGenericNameRequired; - cmd += TCollection_AsciiString(" --out ") + aResultFileName; + cmd += " --in " + aGMFFileName; + cmd += " --out " + aResultFileName; } if ( !_logInStandardOutput ) { - cmd += TCollection_AsciiString(" 1> " ) + aLogFileName; // dump into file - mgHybrid.SetLogFile( aLogFileName.ToCString() ); + cmd += " 1> " + aLogFileName; // dump into file + mgHybrid.SetLogFile( aLogFileName ); } std::cout << std::endl; std::cout << "Hybrid execution w/o geometry..." << std::endl; @@ -3317,7 +1695,7 @@ bool HYBRIDPlugin_HYBRID::Compute(SMESH_Mesh& theMesh, _computeCanceled = false; std::string errStr; - Ok = mgHybrid.Compute( cmd.ToCString(), errStr ); // run + Ok = mgHybrid.Compute( cmd, errStr ); // run if ( _logInStandardOutput && mgHybrid.IsLibrary() ) std::cout << std::endl << mgHybrid.GetLog() << std::endl; @@ -3331,14 +1709,13 @@ bool HYBRIDPlugin_HYBRID::Compute(SMESH_Mesh& theMesh, const bool toMakeGroupsOfDomains = HYBRIDPlugin_Hypothesis::GetToMakeGroupsOfDomains( _hyp ); Ok = Ok && readGMFFile(&mgHybrid, - aResultFileName.ToCString(), + aResultFileName.c_str(), this, theHelper, aNodeByHybridId, aFaceByHybridId, aNodeToHybridIdMap, aNodeGroupByHybridId, anEdgeGroupByHybridId, aFaceGroupByHybridId, groupsToRemove, toMakeGroupsOfDomains); updateMeshGroups(theHelper->GetMesh(), groupsToRemove); - //removeEmptyGroupsOfDomains( theHelper->GetMesh(), notEmptyAsWell ); removeEmptyGroupsOfDomains( theHelper->GetMesh(), !toMakeGroupsOfDomains ); if ( Ok ) { @@ -3354,21 +1731,18 @@ bool HYBRIDPlugin_HYBRID::Compute(SMESH_Mesh& theMesh, { if ( _removeLogOnSuccess ) removeFile( aLogFileName ); - - //if ( !toMakeGroupsOfDomains && _hyp && _hyp->GetToMakeGroupsOfDomains() ) - //error( COMPERR_WARNING, "'toMakeGroupsOfDomains' is ignored since 'toMeshHoles' is OFF." ); } else if ( mgHybrid.HasLog() ) { // get problem description from the log file _Ghs2smdsConvertor conv( aNodeByHybridId ); - storeErrorDescription( _logInStandardOutput ? 0 : aLogFileName.ToCString(), + storeErrorDescription( _logInStandardOutput ? 0 : aLogFileName.c_str(), mgHybrid.GetLog(), conv ); } else { // the log file is empty removeFile( aLogFileName ); - INFOS( "HYBRID Error, command '" << cmd.ToCString() << "' failed" ); + INFOS( "HYBRID Error, command '" << cmd << "' failed" ); error(COMPERR_ALGO_FAILED, "hybrid: command not found" ); } diff --git a/src/HYBRIDPlugin/HYBRIDPlugin_HYBRID_i.cxx b/src/HYBRIDPlugin/HYBRIDPlugin_HYBRID_i.cxx index 80cd00a..0c67197 100644 --- a/src/HYBRIDPlugin/HYBRIDPlugin_HYBRID_i.cxx +++ b/src/HYBRIDPlugin/HYBRIDPlugin_HYBRID_i.cxx @@ -48,7 +48,6 @@ HYBRIDPlugin_HYBRID_i::HYBRIDPlugin_HYBRID_i (PortableServer::POA_ptr thePOA, SMESH_Algo_i( thePOA ), SMESH_3D_Algo_i( thePOA ) { - MESSAGE( "HYBRIDPlugin_HYBRID_i::HYBRIDPlugin_HYBRID_i" ); myBaseImpl = new ::HYBRIDPlugin_HYBRID (theGenImpl->GetANewId(), theStudyId, theGenImpl ); @@ -64,7 +63,6 @@ HYBRIDPlugin_HYBRID_i::HYBRIDPlugin_HYBRID_i (PortableServer::POA_ptr thePOA, HYBRIDPlugin_HYBRID_i::~HYBRIDPlugin_HYBRID_i() { - MESSAGE( "HYBRIDPlugin_HYBRID_i::~HYBRIDPlugin_HYBRID_i" ); } //============================================================================= @@ -77,7 +75,6 @@ HYBRIDPlugin_HYBRID_i::~HYBRIDPlugin_HYBRID_i() ::HYBRIDPlugin_HYBRID* HYBRIDPlugin_HYBRID_i::GetImpl() { - MESSAGE( "HYBRIDPlugin_HYBRID_i::GetImpl" ); return ( ::HYBRIDPlugin_HYBRID* )myBaseImpl; } @@ -91,7 +88,6 @@ HYBRIDPlugin_HYBRID_i::~HYBRIDPlugin_HYBRID_i() SMESH::SMESH_Mesh_ptr HYBRIDPlugin_HYBRID_i::importGMFMesh(const char* theGMFFileName) { - MESSAGE( "HYBRIDPlugin_HYBRID_i::importGMFMesh" ); SMESH_Gen_i* smeshGen = SMESH_Gen_i::GetSMESHGen(); SMESH::SMESH_Mesh_ptr theMesh = smeshGen->CreateEmptyMesh(); smeshGen->RemoveLastFromPythonScript(smeshGen->GetCurrentStudy()->StudyId()); diff --git a/src/HYBRIDPlugin/HYBRIDPlugin_Hypothesis.cxx b/src/HYBRIDPlugin/HYBRIDPlugin_Hypothesis.cxx index 9d929ab..56de2c8 100644 --- a/src/HYBRIDPlugin/HYBRIDPlugin_Hypothesis.cxx +++ b/src/HYBRIDPlugin/HYBRIDPlugin_Hypothesis.cxx @@ -27,7 +27,7 @@ #include -#include +#include #ifdef WIN32 #include @@ -102,6 +102,32 @@ bool HYBRIDPlugin_Hypothesis::GetLayersOnAllWrap(bool checkFreeOption) const return myLayersOnAllWrap; } +//======================================================================= +//function : SetFacesWithLayers +//purpose : Set IDs of faces to grow the layers on +//======================================================================= + +bool HYBRIDPlugin_Hypothesis::SetFacesWithLayers(const std::vector& theVal) +{ + if ( myFacesWithLayers != theVal ) + { + myFacesWithLayers = theVal; + NotifySubMeshesHypothesisModification(); + return true; + } + return false; +} + +//======================================================================= +//function : GetFacesWithLayers +//purpose : Return IDs of faces to grow the layers on +//======================================================================= + +const std::vector& HYBRIDPlugin_Hypothesis::GetFacesWithLayers() const +{ + return myFacesWithLayers; +} + //======================================================================= //function : SetToMeshHoles //======================================================================= @@ -649,9 +675,6 @@ bool HYBRIDPlugin_Hypothesis::GetRemoveLogOnSuccess() const bool HYBRIDPlugin_Hypothesis::SetEnforcedVertex(std::string theName, std::string theEntry, std::string theGroupName, double size, double x, double y, double z, bool isCompound) { - MESSAGE("HYBRIDPlugin_Hypothesis::SetEnforcedVertex(\""<< theName << "\", \""<< theEntry << "\", \"" << theGroupName << "\", " - << size << ", " << x << ", " << y << ", " << z << ", "<< isCompound << ")"); - bool toNotify = false; bool toCreate = true; @@ -675,19 +698,15 @@ bool HYBRIDPlugin_Hypothesis::SetEnforcedVertex(std::string theName, std::string if (it != _enfVertexList.end()) { toCreate = false; oldEnVertex = (*it); - MESSAGE("Enforced Vertex was found => Update"); if (oldEnVertex->name != theName) { - MESSAGE("Update name from \"" << oldEnVertex->name << "\" to \"" << theName << "\""); oldEnVertex->name = theName; toNotify = true; } if (oldEnVertex->groupName != theGroupName) { - MESSAGE("Update group name from \"" << oldEnVertex->groupName << "\" to \"" << theGroupName << "\""); oldEnVertex->groupName = theGroupName; toNotify = true; } if (oldEnVertex->size != size) { - MESSAGE("Update size from \"" << oldEnVertex->size << "\" to \"" << size << "\""); oldEnVertex->size = size; toNotify = true; } @@ -709,7 +728,6 @@ bool HYBRIDPlugin_Hypothesis::SetEnforcedVertex(std::string theName, std::string // //////// CREATE //////////// if (toCreate) { toNotify = true; - MESSAGE("Creating new enforced vertex"); _enfVertexList.insert(newEnfVertex); if (theEntry == "") { _coordsEnfVertexMap[newEnfVertex->coords] = newEnfVertex; @@ -724,7 +742,6 @@ bool HYBRIDPlugin_Hypothesis::SetEnforcedVertex(std::string theName, std::string if (toNotify) NotifySubMeshesHypothesisModification(); - MESSAGE("HYBRIDPlugin_Hypothesis::SetEnforcedVertex END"); return toNotify; } @@ -738,7 +755,6 @@ bool HYBRIDPlugin_Hypothesis::SetEnforcedMesh(SMESH_Mesh& theMesh, SMESH::Elemen SMDS_ElemIteratorPtr eIt = theMesh.GetMeshDS()->elementsIterator(SMDSAbs_ElementType(elementType)); while ( eIt->more() ) theElemSet.insert( eIt->next() ); - MESSAGE("Add "<length() == 0 ){MESSAGE("The source group is empty");} for ( CORBA::ULong i = 0; i < theIDs->length(); i++) { @@ -788,7 +803,6 @@ bool HYBRIDPlugin_Hypothesis::SetEnforcedGroup(const SMESHDS_Mesh* theMeshDS, SM // while ( it->more() ) // theElemSet.insert( it->next() ); - MESSAGE("Add "<X()<<","<Y()<<","<Z()<< ") with ID " << node->GetID() <<" added ? " << msg); } else { SMDS_ElemIteratorPtr nodeIt = elem->nodesIterator(); @@ -932,28 +944,23 @@ bool HYBRIDPlugin_Hypothesis::RemoveEnforcedVertex(double x, double y, double z, TGeomEntryHYBRIDEnforcedVertexMap::iterator it_enfVertexEntry = _geomEntryEnfVertexMap.find(theEntry); if (it_enfVertexEntry != _geomEntryEnfVertexMap.end()) { // Success - MESSAGE("Found enforced vertex with geom entry " << theEntry); oldEnfVertex = it_enfVertexEntry->second; _geomEntryEnfVertexMap.erase(it_enfVertexEntry); } else { // Fail - MESSAGE("Enforced vertex with geom entry " << theEntry << " not found"); // check that enf vertex with given coords exists TCoordsHYBRIDEnforcedVertexMap::iterator it_coords_enf = _coordsEnfVertexMap.find(coords); if (it_coords_enf != _coordsEnfVertexMap.end()) { // Success - MESSAGE("Found enforced vertex with coords " << x << ", " << y << ", " << z); oldEnfVertex = it_coords_enf->second; _coordsEnfVertexMap.erase(it_coords_enf); _enfVertexCoordsSizeList.erase(_enfVertexCoordsSizeList.find(coords)); } else { // Fail - MESSAGE("Enforced vertex with coords " << x << ", " << y << ", " << z << " not found"); throw std::invalid_argument(msg.str()); } } - MESSAGE("Remove enf vertex from _enfVertexList"); // update _enfVertexList THYBRIDEnforcedVertexList::iterator it = _enfVertexList.find(oldEnfVertex); @@ -962,7 +969,6 @@ bool HYBRIDPlugin_Hypothesis::RemoveEnforcedVertex(double x, double y, double z, _groupsToRemove.insert((*it)->groupName); _enfVertexList.erase(it); toNotify = true; - MESSAGE("Done"); } if (toNotify) @@ -1148,7 +1154,7 @@ short HYBRIDPlugin_Hypothesis::DefaultOptimizationLevel() std::string HYBRIDPlugin_Hypothesis::DefaultWorkingDirectory() { - TCollection_AsciiString aTmpDir; + std::string aTmpDir; char *Tmp_dir = getenv("SALOME_TMP_DIR"); if(Tmp_dir != NULL) { @@ -1156,12 +1162,12 @@ std::string HYBRIDPlugin_Hypothesis::DefaultWorkingDirectory() } else { #ifdef WIN32 - aTmpDir = TCollection_AsciiString("C:\\"); + aTmpDir = "C:\\"; #else - aTmpDir = TCollection_AsciiString("/tmp/"); + aTmpDir = "/tmp/"; #endif } - return aTmpDir.ToCString(); + return aTmpDir; } //======================================================================= @@ -1328,7 +1334,7 @@ std::ostream & HYBRIDPlugin_Hypothesis::SaveTo(std::ostream & save) save << myTextOption << " "; save << "__OPTIONS_END__ "; } - + THYBRIDEnforcedVertexList::iterator it = _enfVertexList.begin(); if (it != _enfVertexList.end()) { @@ -1397,6 +1403,11 @@ std::ostream & HYBRIDPlugin_Hypothesis::SaveTo(std::ostream & save) } save << " " << "__ENFORCED_MESHES_END__ "; } + + save << " " << myFacesWithLayers.size(); + for ( size_t i = 0; i < myFacesWithLayers.size(); ++i ) + save << " " << myFacesWithLayers[i]; + return save; } @@ -1584,7 +1595,6 @@ std::istream & HYBRIDPlugin_Hypothesis::LoadFrom(std::istream & load) name += txt; } } - MESSAGE("name: " <(load >> txt); // __END_ENTRY__ if (txt != "__END_ENTRY__") throw std::exception(); - MESSAGE("entry: " << entry); } if (txt == "__BEGIN_GROUP__") { // __BEGIN_GROUP__ @@ -1605,7 +1614,6 @@ std::istream & HYBRIDPlugin_Hypothesis::LoadFrom(std::istream & load) groupName += txt; } } - MESSAGE("groupName: " << groupName); } if (txt == "__BEGIN_COORDS__") { // __BEGIN_COORDS__ @@ -1614,7 +1622,6 @@ std::istream & HYBRIDPlugin_Hypothesis::LoadFrom(std::istream & load) isOK = static_cast(load >> txt); // __END_COORDS__ if (txt != "__END_COORDS__") throw std::exception(); - MESSAGE("coords: " << coords[0] <<","<< coords[1] <<","<< coords[2]); } if (txt == "__BEGIN_SIZE__") { // __BEGIN_ENTRY__ @@ -1623,7 +1630,6 @@ std::istream & HYBRIDPlugin_Hypothesis::LoadFrom(std::istream & load) if (txt != "__END_SIZE__") { throw std::exception(); } - MESSAGE("size: " << size); } } isOK = static_cast(load >> txt); // __BEGIN_VERTEX__ @@ -1675,7 +1681,6 @@ std::istream & HYBRIDPlugin_Hypothesis::LoadFrom(std::istream & load) name += txt; } } - MESSAGE("name: " <(load >> txt); // __END_ENTRY__ if (txt != "__END_ENTRY__") throw std::exception(); - MESSAGE("entry: " << entry); } if (txt == "__BEGIN_ELEM_TYPE__") { // __BEGIN_ELEM_TYPE__ @@ -1691,7 +1695,6 @@ std::istream & HYBRIDPlugin_Hypothesis::LoadFrom(std::istream & load) isOK = static_cast(load >> txt); // __END_ELEM_TYPE__ if (txt != "__END_ELEM_TYPE__") throw std::exception(); - MESSAGE("elementType: " << elementType); } if (txt == "__BEGIN_GROUP__") { // __BEGIN_GROUP__ @@ -1703,12 +1706,10 @@ std::istream & HYBRIDPlugin_Hypothesis::LoadFrom(std::istream & load) groupName += txt; } } // while - MESSAGE("groupName: " << groupName); } // if if (txt == "__PERSIST_ID__") { isOK = static_cast(load >> persistID); - MESSAGE("persistID: " << persistID); } std::cout << "isOK: " << isOK << std::endl; } // while @@ -1717,6 +1718,21 @@ std::istream & HYBRIDPlugin_Hypothesis::LoadFrom(std::istream & load) } // while } // if + if ( hasEnforcedMeshes ) + isOK = static_cast(load >> separator); + + if ( isOK ) + { + i = atoi( separator.c_str() ); + isOK = ( i >= 0 ); + if ( isOK ) + { + myFacesWithLayers.reserve( i ); + while (( myFacesWithLayers.size() < myFacesWithLayers.capacity() ) && + ( isOK = static_cast(load >> i)) ) + myFacesWithLayers.push_back( i ); + } + } return load; } @@ -1750,26 +1766,26 @@ bool HYBRIDPlugin_Hypothesis::SetParametersByDefaults(const TDefaults& dflts, //================================================================================ std::string HYBRIDPlugin_Hypothesis::CommandToRun(const HYBRIDPlugin_Hypothesis* hyp, - const bool hasShapeToMesh) + SMESH_Mesh& mesh) { - TCollection_AsciiString cmd = GetExeName().c_str(); + SMESH_Comment cmd = GetExeName(); // check if any option is overridden by hyp->myTextOption - bool p_h = ( hyp && hyp->myTextOption.find("-h") != std::string::npos ); - bool p_v = ( hyp && hyp->myTextOption.find("-v ") != std::string::npos ); - bool p_i = ( hyp && hyp->myTextOption.find("-i") != std::string::npos ); - bool p_o = ( hyp && hyp->myTextOption.find("-o") != std::string::npos ); - bool p_mnot = ( hyp && hyp->myTextOption.find("--max_number_of_threads ") != std::string::npos ); - bool p_blsi = ( hyp && hyp->myTextOption.find("--boundary_layer_surface_tags ") != std::string::npos ); - bool p_blii = ( hyp && hyp->myTextOption.find("--boundary_layer_imprint_tags ") != std::string::npos ); - bool p_blsd = ( hyp && hyp->myTextOption.find("--normal_direction ") != std::string::npos ); - bool p_hotfl = ( hyp && hyp->myTextOption.find("--boundary_layer_global_initial_height ") != std::string::npos ); - bool p_nobl = ( hyp && hyp->myTextOption.find("--number_of_boundary_layers ") != std::string::npos ); - bool p_blgp = ( hyp && hyp->myTextOption.find("--boundary_layer_geometric_progression ") != std::string::npos ); - bool p_eg = ( hyp && hyp->myTextOption.find("--element_generation ") != std::string::npos ); - bool p_cm = ( hyp && hyp->myTextOption.find("--collision_mode ") != std::string::npos ); - bool p_am = ( hyp && hyp->myTextOption.find("--add_multinormals ") != std::string::npos ); - bool p_mat = ( hyp && hyp->myTextOption.find("--multinormal_angle_threshold ") != std::string::npos ); - bool p_sn = ( hyp && hyp->myTextOption.find("--smooth_normals ") != std::string::npos ); + bool p_h = ( hyp && hyp->myTextOption.find("-h") != std::string::npos ); + bool p_v = ( hyp && hyp->myTextOption.find("-v") != std::string::npos ); + bool p_i = ( hyp && hyp->myTextOption.find("-i") != std::string::npos ); + bool p_o = ( hyp && hyp->myTextOption.find("-o") != std::string::npos ); + bool p_mnot = ( hyp && hyp->myTextOption.find("--max_number_of_threads ") != std::string::npos ); + bool p_blsi = ( hyp && hyp->myTextOption.find("--boundary_layer_surface_tags ") != std::string::npos ); + bool p_blii = ( hyp && hyp->myTextOption.find("--boundary_layer_imprint_tags ") != std::string::npos ); + bool p_blsd = ( hyp && hyp->myTextOption.find("--normal_direction ") != std::string::npos ); + bool p_hotfl = ( hyp && hyp->myTextOption.find("--boundary_layer_global_initial_height ") != std::string::npos ); + bool p_nobl = ( hyp && hyp->myTextOption.find("--number_of_boundary_layers ") != std::string::npos ); + bool p_blgp = ( hyp && hyp->myTextOption.find("--boundary_layer_geometric_progression ") != std::string::npos ); + bool p_eg = ( hyp && hyp->myTextOption.find("--element_generation ") != std::string::npos ); + bool p_cm = ( hyp && hyp->myTextOption.find("--collision_mode ") != std::string::npos ); + bool p_am = ( hyp && hyp->myTextOption.find("--add_multinormals ") != std::string::npos ); + bool p_mat = ( hyp && hyp->myTextOption.find("--multinormal_angle_threshold ") != std::string::npos ); + bool p_sn = ( hyp && hyp->myTextOption.find("--smooth_normals ") != std::string::npos ); //missing options : //- global_physical_size @@ -1782,34 +1798,20 @@ std::string HYBRIDPlugin_Hypothesis::CommandToRun(const HYBRIDPlugin_Hypothesis* //help mode if ( p_h ) { - cmd += " --help "; + cmd << " --help "; #ifdef WIN32 - cmd += " < NUL"; + cmd << " < NUL"; #endif - std::cout << "!!!!! CommandToRun help only !!!! " << cmd.ToCString() << std::endl; - return cmd.ToCString(); + std::cout << "!!!!! CommandToRun help only !!!! " << cmd << std::endl; + return cmd; } - if ( !p_v && hyp ) { - cmd += " --verbose "; - cmd += hyp->myVerboseLevel; - } + if ( !p_v && hyp ) + cmd << " --verbose " << hyp->myVerboseLevel; + + if ( !p_mnot && hyp ) + cmd << " --max_number_of_threads " << 8; //TODO getenv NB CPU - if ( !p_mnot && hyp ) { - cmd += " --max_number_of_threads "; - cmd += 8; //TODO getenv NB CPU - } - - //if ( !p_blsi && hyp ) { - // cmd += " --boundary_layers_surface_ids "; - // cmd += 0; //TODO hyp->my; - //} - - //if ( !p_blii && hyp ) { - // cmd += " --boundary_layers_imprint_ids "; - // cmd += 0; //TODO hyp->my; - //} - //no layers? if ( !p_nobl && hyp ) { if ( hyp->myNbOfBoundaryLayers < 1 ) nolayers = true; @@ -1820,81 +1822,81 @@ std::string HYBRIDPlugin_Hypothesis::CommandToRun(const HYBRIDPlugin_Hypothesis* if ( !p_blsd && hyp ) { if ( hyp->myBoundaryLayersGrowth >= 0 && hyp->myBoundaryLayersGrowth <= 1 ) { - const char* value[] = { "1" , "-1" }; - cmd += " --normal_direction "; - cmd += value[ hyp->myBoundaryLayersGrowth ]; + const char* value[] = { "-1" , "1" }; // -1 == inside + cmd << " --normal_direction " << value[ hyp->myBoundaryLayersGrowth ]; } } if ( !p_hotfl && hyp ) { - cmd += " --boundary_layer_global_initial_height "; - cmd += hyp->myHeightFirstLayer; + cmd << " --boundary_layer_global_initial_height " << hyp->myHeightFirstLayer; } if ( !p_nobl && hyp ) { - cmd += " --number_of_boundary_layers "; - if ( nolayers ) - cmd += 0; - else - cmd += hyp->myNbOfBoundaryLayers; + cmd << " --number_of_boundary_layers " << ( nolayers ? 0 : hyp->myNbOfBoundaryLayers ); } - + if ( !p_blgp && hyp ) { - cmd += " --boundary_layer_geometric_progression "; - cmd += hyp->myBoundaryLayersProgression; + cmd << " --boundary_layer_geometric_progression " << hyp->myBoundaryLayersProgression; } - //--boundary_layers_surface_ids 5 #for all wrap shell - //--boundary_layers_surface_ids 6 #for all enfMeshList - //TODO? if ( !nolayers ) cmd += " --boundary_layers_surface_ids 5,6 "; //as all wrap shell and triangles of enforced mesh - if ( !nolayers ) { - if (layersOnAllWrap) - cmd += " --boundary_layer_surface_tags 5 "; //as triangles of all wrap + if ( !nolayers && hyp ) + { + cmd << " --boundary_layer_size_mode " << ( layersOnAllWrap ? "global" : "local" ); + cmd << " --boundary_layer_surface_tags "; + if ( layersOnAllWrap ) + { + cmd << " 3 "; + } else - cmd += " --boundary_layer_surface_tags 6 "; //as triangles of enforced mesh + { + const std::vector& faceIDs = hyp->GetFacesWithLayers(); + const bool hasEnforcedTria = !HYBRIDPlugin_Hypothesis::GetEnforcedTriangles(hyp).empty(); + for ( size_t i = 0; i < faceIDs.size(); ++i ) + cmd << faceIDs[i] << ","; + if ( hasEnforcedTria ) + cmd << EnforcedTag(); + cmd << " --boundary_layer_initial_height_on_surface_tags "; + for ( size_t i = 0; i < faceIDs.size() + hasEnforcedTria; ++i ) + cmd << hyp->myHeightFirstLayer << ","; + } } if ( !p_eg && hyp ) { if ( hyp->myElementGeneration >= 0 && hyp->myElementGeneration <= 1 ) { const char* value[] = { "tetra-dominant" , "hexa-dominant" }; - cmd += " --element_generation "; - cmd += value[ hyp->myElementGeneration ]; + cmd << " --element_generation " << value[ hyp->myElementGeneration ]; } } if ( !p_cm && hyp ) { if ( hyp->myCollisionMode >= 0 && hyp->myCollisionMode <= 1 ) { const char* value[] = { "decrease" , "stop" }; - cmd += " --collision_mode "; - cmd += value[ hyp->myCollisionMode ]; + cmd << " --collision_mode " << value[ hyp->myCollisionMode ]; } } if ( !p_am && hyp ) { int res = hyp->myAddMultinormals ? 0 : 1 ; const char* value[] = { "yes" , "no" }; - cmd += " --add_multinormals "; - cmd += value[ res ]; + cmd << " --add_multinormals " << value[ res ]; } if ( !p_mat && hyp ) { - cmd += " --multinormal_angle_threshold "; - cmd += hyp->myMultinormalsAngle; + cmd << " --multinormal_angle_threshold " << hyp->myMultinormalsAngle; } if ( !p_sn && hyp ) { int res = hyp->mySmoothNormals ? 0 : 1 ; const char* value[] = { "yes" , "no" }; - cmd += " --smooth_normals "; - cmd += value[ res ]; + cmd << " --smooth_normals " << value[ res ]; } #ifdef WIN32 - cmd += " < NUL"; + cmd << " < NUL"; #endif - //std::cout << "!!!!!CommandToRun end " << cmd.ToCString() << std::endl; + //std::cout << "!!!!!CommandToRun end " << cmd << std::endl; - return cmd.ToCString(); + return cmd; } //================================================================================ @@ -1908,18 +1910,18 @@ std::string HYBRIDPlugin_Hypothesis::GetFileName(const HYBRIDPlugin_Hypothesis* std::string aTmpDir = hyp ? hyp->GetWorkingDirectory() : DefaultWorkingDirectory(); const char lastChar = *aTmpDir.rbegin(); #ifdef WIN32 - if(lastChar != '\\') aTmpDir+='\\'; + if(lastChar != '\\') aTmpDir+='\\'; #else - if(lastChar != '/') aTmpDir+='/'; + if(lastChar != '/') aTmpDir+='/'; #endif - TCollection_AsciiString aGenericName = (char*)aTmpDir.c_str(); - aGenericName += "HYBRID_"; - aGenericName += getpid(); - aGenericName += "_"; - aGenericName += Abs((Standard_Integer)(long) aGenericName.ToCString()); + SMESH_Comment aGenericName = aTmpDir; + aGenericName << "HYBRID_"; + aGenericName << getpid(); + aGenericName << "_"; + aGenericName << Abs((Standard_Integer)(long) aGenericName.c_str()); - return aGenericName.ToCString(); + return aGenericName; } //================================================================================ diff --git a/src/HYBRIDPlugin/HYBRIDPlugin_Hypothesis.hxx b/src/HYBRIDPlugin/HYBRIDPlugin_Hypothesis.hxx index 779eee5..0bbd718 100644 --- a/src/HYBRIDPlugin/HYBRIDPlugin_Hypothesis.hxx +++ b/src/HYBRIDPlugin/HYBRIDPlugin_Hypothesis.hxx @@ -129,6 +129,11 @@ public: */ void SetLayersOnAllWrap(bool toMesh); bool GetLayersOnAllWrap(bool checkFreeOption = false) const; + /*! + * IDs of faces to grow the layers on + */ + bool SetFacesWithLayers(const std::vector& theVal); + const std::vector& GetFacesWithLayers() const; /*! * To make groups of volumes of different domains when mesh is generated from skin. * Default is to make groups. @@ -288,8 +293,7 @@ public: /*! * \brief Return command to run hybrid mesher excluding file prefix (-f) */ - static std::string CommandToRun(const HYBRIDPlugin_Hypothesis* hyp, - const bool hasShapeToMesh=true); + static std::string CommandToRun(const HYBRIDPlugin_Hypothesis* hyp, SMESH_Mesh& mesh); /*! * \brief Return a unique file name */ @@ -298,6 +302,10 @@ public: * \brief Return the name of executable */ static std::string GetExeName(); + /*! + * \brief Return a tag of enforced triangles + */ + static int EnforcedTag() { return -5; } /*! * To set an enforced vertex @@ -408,33 +416,34 @@ public: private: - bool myToMeshHoles; - bool myLayersOnAllWrap; - bool myToMakeGroupsOfDomains; - double myMaximumMemory; - double myInitialMemory; - short myOptimizationLevel; - short myCollisionMode; - short myBoundaryLayersGrowth; - short myElementGeneration; - bool myKeepFiles; - std::string myWorkingDirectory; - short myVerboseLevel; - bool myToCreateNewNodes; - bool myToUseBoundaryRecoveryVersion; - bool myToUseFemCorrection; - bool myToRemoveCentralPoint; - bool myLogInStandardOutput; - bool myRemoveLogOnSuccess; - std::string myTextOption; - double myGradation; + bool myToMeshHoles; + bool myLayersOnAllWrap; + std::vector myFacesWithLayers; + bool myToMakeGroupsOfDomains; + double myMaximumMemory; + double myInitialMemory; + short myOptimizationLevel; + short myCollisionMode; + short myBoundaryLayersGrowth; + short myElementGeneration; + bool myKeepFiles; + std::string myWorkingDirectory; + short myVerboseLevel; + bool myToCreateNewNodes; + bool myToUseBoundaryRecoveryVersion; + bool myToUseFemCorrection; + bool myToRemoveCentralPoint; + bool myLogInStandardOutput; + bool myRemoveLogOnSuccess; + std::string myTextOption; + double myGradation; - bool myAddMultinormals; - bool mySmoothNormals; - double myHeightFirstLayer; - double myBoundaryLayersProgression; - double myMultinormalsAngle; - short myNbOfBoundaryLayers; + bool myAddMultinormals; + bool mySmoothNormals; + double myHeightFirstLayer; + double myBoundaryLayersProgression; + double myMultinormalsAngle; + short myNbOfBoundaryLayers; THYBRIDEnforcedVertexList _enfVertexList; THYBRIDEnforcedVertexCoordsValues _enfVertexCoordsSizeList; diff --git a/src/HYBRIDPlugin/HYBRIDPlugin_Hypothesis_i.cxx b/src/HYBRIDPlugin/HYBRIDPlugin_Hypothesis_i.cxx index dbb26c5..0d769f5 100644 --- a/src/HYBRIDPlugin/HYBRIDPlugin_Hypothesis_i.cxx +++ b/src/HYBRIDPlugin/HYBRIDPlugin_Hypothesis_i.cxx @@ -54,7 +54,6 @@ HYBRIDPlugin_Hypothesis_i::HYBRIDPlugin_Hypothesis_i (PortableServer::POA_ptr th : SALOME::GenericObj_i( thePOA ), SMESH_Hypothesis_i( thePOA ) { - MESSAGE( "HYBRIDPlugin_Hypothesis_i::HYBRIDPlugin_Hypothesis_i" ); myBaseImpl = new ::HYBRIDPlugin_Hypothesis (theGenImpl->GetANewId(), theStudyId, theGenImpl); @@ -65,7 +64,6 @@ HYBRIDPlugin_Hypothesis_i::HYBRIDPlugin_Hypothesis_i (PortableServer::POA_ptr th //======================================================================= HYBRIDPlugin_Hypothesis_i::~HYBRIDPlugin_Hypothesis_i() { - MESSAGE( "HYBRIDPlugin_Hypothesis_i::~HYBRIDPlugin_Hypothesis_i" ); } //======================================================================= @@ -89,6 +87,35 @@ CORBA::Boolean HYBRIDPlugin_Hypothesis_i::GetLayersOnAllWrap() return this->GetImpl()->GetLayersOnAllWrap(); } +//======================================================================= +//function : SetFacesWithLayers +//======================================================================= + +void HYBRIDPlugin_Hypothesis_i::SetFacesWithLayers(const ::SMESH::long_array& theVal) +{ + std::vector ids( theVal.length() ); + for ( size_t i = 0; i < ids.size(); ++i ) + ids[i] = theVal[i]; + + bool valueChanged = this->GetImpl()->SetFacesWithLayers(ids); + if (valueChanged) + SMESH::TPythonDump() << _this() << ".SetFacesWithLayers( "<< theVal << " )"; +} + +//======================================================================= +//function : GetFacesWithLayers +//======================================================================= + +SMESH::long_array* HYBRIDPlugin_Hypothesis_i::GetFacesWithLayers() +{ + const std::vector& idsVec = this->GetImpl()->GetFacesWithLayers(); + SMESH::long_array_var ids = new SMESH::long_array; + ids->length( idsVec.size() ); + for ( size_t i = 0; i < idsVec.size(); ++i ) + ids[i] = idsVec[i]; + return ids._retn(); +} + //======================================================================= //function : SetToMeshHoles //======================================================================= @@ -667,28 +694,24 @@ CORBA::Short HYBRIDPlugin_Hypothesis_i::GetNbOfBoundaryLayers() bool HYBRIDPlugin_Hypothesis_i::SetEnforcedVertex(CORBA::Double x, CORBA::Double y, CORBA::Double z, CORBA::Double size) throw (SALOME::SALOME_Exception) { ASSERT(myBaseImpl); - MESSAGE("IDL : SetEnforcedVertex( "<< x << ", " << y << ", " << z << ", " << size << ")"); return p_SetEnforcedVertex(size, x, y, z); } bool HYBRIDPlugin_Hypothesis_i::SetEnforcedVertexNamed(CORBA::Double x, CORBA::Double y, CORBA::Double z, CORBA::Double size, const char* theVertexName) throw (SALOME::SALOME_Exception) { ASSERT(myBaseImpl); - MESSAGE("IDL : SetEnforcedVertexNamed( "<< x << ", " << y << ", " << z << ", " << size << ", " << theVertexName << ")"); return p_SetEnforcedVertex(size, x, y, z, theVertexName, "", ""); } bool HYBRIDPlugin_Hypothesis_i::SetEnforcedVertexWithGroup(CORBA::Double x, CORBA::Double y, CORBA::Double z, CORBA::Double size, const char* theGroupName) throw (SALOME::SALOME_Exception) { ASSERT(myBaseImpl); - MESSAGE("IDL : SetEnforcedVertexWithGroup( "<< x << ", " << y << ", " << z << ", " << size << ", " << theGroupName << ")"); return p_SetEnforcedVertex(size, x, y, z, "", "", theGroupName); } bool HYBRIDPlugin_Hypothesis_i::SetEnforcedVertexNamedWithGroup(CORBA::Double x, CORBA::Double y, CORBA::Double z, CORBA::Double size, const char* theVertexName, const char* theGroupName) throw (SALOME::SALOME_Exception) { ASSERT(myBaseImpl); - MESSAGE("IDL : SetEnforcedVertexNamedWithGroup( "<< x << ", " << y << ", " << z << ", " << size << ", " << theVertexName << ", " << theGroupName << ")"); return p_SetEnforcedVertex(size, x, y, z, theVertexName, "", theGroupName); } @@ -697,7 +720,6 @@ bool HYBRIDPlugin_Hypothesis_i::SetEnforcedVertexGeom(GEOM::GEOM_Object_ptr theV ASSERT(myBaseImpl); if ((theVertex->GetShapeType() != GEOM::VERTEX) && (theVertex->GetShapeType() != GEOM::COMPOUND)) { - MESSAGE("theVertex shape type is not VERTEX or COMPOUND"); THROW_SALOME_CORBA_EXCEPTION("theVertex shape type is not VERTEX or COMPOUND", SALOME::BAD_PARAM); } @@ -729,11 +751,9 @@ bool HYBRIDPlugin_Hypothesis_i::SetEnforcedVertexGeom(GEOM::GEOM_Object_ptr theV return false; measureOp->PointCoordinates (theVertex, x, y, z); - MESSAGE("Point coordinates from measureOp: " << x << ", " << y << ", " << z); } std::string theVertexName = theVertex->GetName(); - MESSAGE("IDL : SetEnforcedVertexGeom( "<< theVertexEntry << ", " << size<< ")"); return p_SetEnforcedVertex(size, x, y, z, theVertexName.c_str(), theVertexEntry.c_str(), "", isCompound); } @@ -775,11 +795,9 @@ bool HYBRIDPlugin_Hypothesis_i::SetEnforcedVertexGeomWithGroup(GEOM::GEOM_Object return false; measureOp->PointCoordinates (theVertex, x, y, z); - MESSAGE("Point coordinates from measureOp: " << x << ", " << y << ", " << z); } std::string theVertexName = theVertex->GetName(); - MESSAGE("IDL : SetEnforcedVertexGeomWithGroup( "<< theVertexEntry << ", " << size<< ", " << theGroupName << ")"); return p_SetEnforcedVertex(size, x, y, z, theVertexName.c_str(), theVertexEntry.c_str(), theGroupName, isCompound); } @@ -789,7 +807,6 @@ bool HYBRIDPlugin_Hypothesis_i:: p_SetEnforcedVertex(CORBA::Double size, CORBA:: CORBA::Boolean isCompound) throw (SALOME::SALOME_Exception) { ASSERT(myBaseImpl); - MESSAGE("IDL : p_SetEnforcedVertex(" << size << ", " << x << ", " << y << ", " << z << ", \"" << theVertexName << "\", \"" << theVertexEntry << "\", \"" << theGroupName << "\", " << isCompound<< ")"); bool newValue = false; ::HYBRIDPlugin_Hypothesis::TCoordsHYBRIDEnforcedVertexMap coordsList; @@ -801,19 +818,15 @@ bool HYBRIDPlugin_Hypothesis_i:: p_SetEnforcedVertex(CORBA::Double size, CORBA:: coords.push_back(y); coords.push_back(z); if (coordsList.find(coords) == coordsList.end()) { - MESSAGE("Coords not found: add it in coordsList"); newValue = true; } else { - MESSAGE("Coords already found, compare names"); ::HYBRIDPlugin_Hypothesis::THYBRIDEnforcedVertex *enfVertex = this->GetImpl()->GetEnforcedVertex(x, y, z); if ((enfVertex->name != theVertexName) || (enfVertex->groupName != theGroupName) || (enfVertex->size != size)) { - MESSAGE("The names or size are different: update"); // this->GetImpl()->ClearEnforcedVertex(theFaceEntry, x, y, z); newValue = true; } else { - MESSAGE("The names and size are identical"); } } @@ -837,19 +850,15 @@ bool HYBRIDPlugin_Hypothesis_i:: p_SetEnforcedVertex(CORBA::Double size, CORBA:: enfVertexEntryList = this->GetImpl()->_GetEnforcedVerticesByEntry(); // ::BLSURFPlugin_Hypothesis::TGeomEntryHYBRIDEnforcedVertexMap::const_iterator it = enfVertexEntryList.find(theVertexEntry); if ( enfVertexEntryList.find(theVertexEntry) == enfVertexEntryList.end()) { - MESSAGE("Geom entry not found: add it in enfVertexEntryList"); newValue = true; } else { - MESSAGE("Geom entry already found, compare names"); ::HYBRIDPlugin_Hypothesis::THYBRIDEnforcedVertex *enfVertex = this->GetImpl()->GetEnforcedVertex(theVertexEntry); if ((enfVertex->name != theVertexName) || (enfVertex->groupName != theGroupName) || (enfVertex->size != size)) { - MESSAGE("The names or size are different: update"); // this->GetImpl()->ClearEnforcedVertex(theFaceEntry, x, y, z); newValue = true; } else { - MESSAGE("The names and size are identical"); } } @@ -864,7 +873,6 @@ bool HYBRIDPlugin_Hypothesis_i:: p_SetEnforcedVertex(CORBA::Double size, CORBA:: if (newValue) this->GetImpl()->SetEnforcedVertex(theVertexName, theVertexEntry, theGroupName, size, x, y, z, isCompound); - MESSAGE("IDL : SetEnforcedVertexEntry END"); return newValue; } @@ -1138,7 +1146,6 @@ bool HYBRIDPlugin_Hypothesis_i::SetEnforcedMeshWithGroup(SMESH::SMESH_IDSource_p bool HYBRIDPlugin_Hypothesis_i::SetEnforcedMesh(SMESH::SMESH_IDSource_ptr theSource, SMESH::ElementType theType) throw (SALOME::SALOME_Exception) { -// MESSAGE("HYBRIDPlugin_Hypothesis_i::SetEnforcedMesh"); // #if HYBRID_VERSION >= 42 return p_SetEnforcedMesh(theSource, theType); // #else @@ -1190,7 +1197,6 @@ bool HYBRIDPlugin_Hypothesis_i::SetEnforcedMeshSize(SMESH::SMESH_IDSource_ptr th bool HYBRIDPlugin_Hypothesis_i::p_SetEnforcedMesh(SMESH::SMESH_IDSource_ptr theSource, SMESH::ElementType theType, const char* theName, const char* theGroupName) throw (SALOME::SALOME_Exception) { - MESSAGE("HYBRIDPlugin_Hypothesis_i::p_SetEnforcedMesh"); ASSERT(myBaseImpl); if (CORBA::is_nil( theSource )) @@ -1205,25 +1211,17 @@ bool HYBRIDPlugin_Hypothesis_i::p_SetEnforcedMesh(SMESH::SMESH_IDSource_ptr theS switch (theType) { case SMESH::NODE: - MESSAGE("Required type is NODE"); break; case SMESH::EDGE: - MESSAGE("Required type is EDGE"); break; case SMESH::FACE: - MESSAGE("Required type is FACE"); break; default: - MESSAGE("Incompatible required type: " << theType); - return false; + return false; } -// MESSAGE("Required type is "<GetTypes(); - MESSAGE("Available types:"); - for (CORBA::ULong i=0;ilength();i++){MESSAGE(types[i]);} if ( types->length() >= 1 && types[types->length()-1] < theType) { - MESSAGE("Required type not available"); return false; // SALOME::ExceptionStruct ExDescription; // ExDescription.text = "The source mesh has bad type"; @@ -1274,7 +1272,6 @@ bool HYBRIDPlugin_Hypothesis_i::p_SetEnforcedMesh(SMESH::SMESH_IDSource_ptr theS } else if (theGroup_i)// && types->length() == 1 && types[0] == theType) { - MESSAGE("The source is a group") try { bool res = this->GetImpl()->SetEnforcedGroup(theGroup_i->GetGroupDS()->GetMesh(), theGroup_i->GetListOfID(), theType, enfMeshName , SObj->GetID(), theGroupName); if (theGroupName && theGroupName[0]) { @@ -1301,7 +1298,6 @@ bool HYBRIDPlugin_Hypothesis_i::p_SetEnforcedMesh(SMESH::SMESH_IDSource_ptr theS } else if (theGroupOnGeom_i)// && types->length() == 1 && types[0] == theType) { - MESSAGE("The source is a group on geom") try { bool res = this->GetImpl()->SetEnforcedGroup(theGroupOnGeom_i->GetGroupDS()->GetMesh(),theGroupOnGeom_i->GetListOfID(), theType, enfMeshName , SObj->GetID(), theGroupName); if (theGroupName && theGroupName[0]) { diff --git a/src/HYBRIDPlugin/HYBRIDPlugin_Hypothesis_i.hxx b/src/HYBRIDPlugin/HYBRIDPlugin_Hypothesis_i.hxx index 7c34352..4733318 100644 --- a/src/HYBRIDPlugin/HYBRIDPlugin_Hypothesis_i.hxx +++ b/src/HYBRIDPlugin/HYBRIDPlugin_Hypothesis_i.hxx @@ -55,6 +55,11 @@ class HYBRIDPLUGIN_EXPORT HYBRIDPlugin_Hypothesis_i: */ void SetToMeshHoles(CORBA::Boolean toMesh); CORBA::Boolean GetToMeshHoles(); + /*! + * IDs of faces to grow the layers on + */ + void SetFacesWithLayers(const SMESH::long_array& faceIDs); + SMESH::long_array* GetFacesWithLayers(); /*! * To mesh "layers on all wrap". Default is to mesh. */ diff --git a/src/HYBRIDPlugin/HYBRIDPlugin_i.cxx b/src/HYBRIDPlugin/HYBRIDPlugin_i.cxx index 1495564..5fdea9c 100644 --- a/src/HYBRIDPlugin/HYBRIDPlugin_i.cxx +++ b/src/HYBRIDPlugin/HYBRIDPlugin_i.cxx @@ -48,8 +48,6 @@ extern "C" HYBRIDPLUGIN_EXPORT GenericHypothesisCreator_i* GetHypothesisCreator (const char* aHypName) { - MESSAGE("GetHypothesisCreator " << aHypName); - GenericHypothesisCreator_i* aCreator = 0; // Hypotheses -- 2.39.2