From 136213bc6677a30ccb5f1d56ad950a76a150613d Mon Sep 17 00:00:00 2001 From: jfa Date: Wed, 13 May 2009 12:03:59 +0000 Subject: [PATCH] Bug 0020228: [CEA 331] the geompy.RemoveExtraEdges crash with the attached brep shape file. Added a new parameter theOptimumNbFaces to the RemoveExtraEdges functionality. In GUI it is a boolean flag. --- .../gui/GEOM/images/remove_extra_edges.png | Bin 26061 -> 23777 bytes .../input/remove_extra_edges_operation.doc | 11 +- idl/GEOM_Gen.idl | 9 +- src/GEOMAlgo/BlockFix_BlockFixAPI.cxx | 28 ++- src/GEOMAlgo/BlockFix_BlockFixAPI.hxx | 98 +++----- src/GEOMAlgo/BlockFix_BlockFixAPI.lxx | 19 +- src/GEOMAlgo/BlockFix_CheckTool.cxx | 115 +++++---- src/GEOMAlgo/BlockFix_UnionFaces.cxx | 218 ++++++++++-------- src/GEOMAlgo/BlockFix_UnionFaces.hxx | 104 ++++----- src/GEOMAlgo/GEOMAlgo_Tools.cxx | 65 ++++-- src/GEOMGUI/GEOM_msg_en.po | 3 + src/GEOMImpl/GEOMImpl_BlockDriver.cxx | 3 +- src/GEOMImpl/GEOMImpl_IBlockTrsf.hxx | 10 +- src/GEOMImpl/GEOMImpl_IBlocksOperations.cxx | 10 +- src/GEOMImpl/GEOMImpl_IBlocksOperations.hxx | 5 +- src/GEOM_I/GEOM_IBlocksOperations_i.cc | 7 +- src/GEOM_I/GEOM_IBlocksOperations_i.hh | 5 +- src/GEOM_SWIG/GEOM_TestOthers.py | 66 +++++- src/GEOM_SWIG/geompyDC.py | 8 +- .../RepairGUI_RemoveExtraEdgesDlg.cxx | 20 +- src/RepairGUI/RepairGUI_RemoveExtraEdgesDlg.h | 11 +- 21 files changed, 463 insertions(+), 352 deletions(-) diff --git a/doc/salome/gui/GEOM/images/remove_extra_edges.png b/doc/salome/gui/GEOM/images/remove_extra_edges.png index bbf6904f6fec1e4a0227c6f28cf9ff56461b0c6e..f5a620b65da3f079785c59a51332eecc176b439a 100644 GIT binary patch literal 23777 zcmbrm1yqz>+b<5H7?emOp@1lYG}2%oNGnJ;QUcPQB2pqEAYBRq(%s!4F(T5PLpKaH zaISgZ_k8EP|L^2QQD4Kt!Xl7-y zE&K91%M9xpnqPw1MwD8JbndXM8^z~6WRUw5{^YjocPayugb~x;os&7mFOz`(%g zj}1v0)cc-ce(dYU3W_Du@rR#D+wi}v|6JmhkdXMnxl!Px>OcjbSE3Bbc_ty@ksvt; zuf!A>Er^MU=`+Gg1GS5&BMoenU5xJv>=Vl}ENrBNm3BsAvs17)EO5W;3Zh?*vAMo? zqV+@d%~RDh|6v_w8g_B*5$TI2^sV}ex2t7HXngope`j?>rkLD1-QE1Mi}YH)FsrQJ z&m|C{8y0yKHNL+0hhIN`TD-zOI(hwtdY2v|=AgAawix~AgyUyuO8Npf6&|IAUi_Aj zq$#uH+N&LV;%OwqUxzp>d$O#*55rbYqxysNcINUQerBSyO_-3XRvijcvKELc9uriP zHh2)tj6|SqCkdUesQ1{M5L}Jbt#sabS}^Xby3oVV$#T$Dwe3ki(t!xZECfoWdNLLXjPgbK2K{M5~BS-;L; zfKv4m^&q#n+3q6l^=vpyZGH@Jk4H|ajUniXt#|Mp5=mL(?iCd2~%V7rG5SiE>aqW z;gicAZo{-L<=S|;=8dz~h@tB%M4@Fq(aw+TO#1l9e*8R8VdE?+bw3hMuq)pjyYeJw zYf=pLlX`ml;l>Ffw4sv}<(7X&B{b-mk1ENZa4gRyc&zFiLnrS~5O9mHde70Py38wN zx=R1~uXomSi1Y3Qc9h*Q-+Q6Q$P84?)pSc+MUK34C&%$}Eb)$#r)##uUMYv3Qa^Ie ziYo)(ghe~O9rAuyeS+ou2WxsiCZj;^1wLfpTsTerT+ld za;nN0IZBT0Um#rhYw7$}mE?5lQh)G@_+R>}p@5;ffM)3pM%M3VRb`Sj*%jzjB~-mB zf8$>7M!T!;@reAL_$hq-uKQ-;SJ_IxwF)Tk*Cc7Qi!jOrsbGZhlCKtFp8q@Md4xpVzv)t~e$gfZjxb6f!ij~JcB%h(QQh|E-R2ooGb zuV{U!#A%CC@sOvuFMYCkV;q?t@X$WgBznUsG-=l=<7>{Ycfx#K*|DiWBJ%XCcM2h1 zW?U&XK;%zx>Rn$^b!}83na<}#D`AR||3kyq{F$}ne(^4z+Hk!-^i7+~Ze+nHRhP5| zkDM4Lx6p|80^T^{YFj(8mnqLv7=Ve+^qVO=;L80B$8(f=||bN>uEHfFjb%E zjjMTlDW8g9+SGww7gr$K)$6!Y?x&&Xxd&1jbqMa?^A9T=|b7SAMtV zPDoBF_qUHlW>5@yn?I~6yeyUe`R9c_!1KFW_y>*@I%?8Mnc{-|x77L%yi5TE?L{1r*xK8ORWxFtUz3)IKZshKgAQsa9G{F`@N{>sCBW>saR(N+hOl#cJ({9+4c+zh*F=0W>)5cjD^?g(P z&#et-=X2NcXVR+|P=40FaSdOe3&hWe-SzU^Iy##i+pG(GD{~jMS0SE(qsG`z-Q}MBFfxC2fBBLL14G)2+Hm)aXsNi9aYv+E!6p$pkC=tkuQc#$^)IjA z^;{Q^D>*t&j_^HPU)5Vk{K}G0^9>IC+SW-LQ$II5v|lax!&1h^Cl&zBD<)c83S#1I zTOoXQ077%TMdX-QChuz7Z``jU1RTTiX!oXtVIX?@XSPY{^(Pn5ozLa7mf`>bUA%Gy z|BfJE#0Q?vB_W%CK%RnseEQly@z4M1g^4xCEq3o!)nL}FB8%< zm=qI}lFsKo3k(ek4p!C=4s`KRYdRh-d_8RWFiS0eBV?mhN+n-c$L9gV>?Pf+tNj^@ zb4X-+F0IukTbP=0D#a<5;u($w*5}+ipCex7qYW=^hv-3pswQzC6{_ zCV!KoYiH$eW@-aDF^lN}-Jq?l?caR8WaSKnmzj2VRC9GNH3ZOmb>zeryV$qJFVsFy zj!sDEF5-{kGMo>*kReQ~@QHa-d)2g5lZz5xJy$h%acma`hVE;E-#%iiKOoS{!#7ne;tIy=8>mYR2a+OiL1tC{vS zJ!86am&@zarGYlC+_^UKfu8m4TerS-P-9j&V?ZdU>KCf3SJ>Rf+yk%Kbz$cXqlS0bMn)zD254MvZtg7<%5*U&){oBb zUfu@%!D&Mb*Xy6!mE3Q~O7~CYu$(q0dnyX&u3Wp8qI2R@gW7O!S^voTvR*ctZNZmF ztiil=)<$4ys$RUAo>EsoB;+Q)Dm>M%B>DJAyJjI&;efgETw4h5n?EhP9(xg~R9m6g z9tTIJmg6O1Ue5b-l|cyCMR{rI@2sQ=unNuuy-A*`|uZLI@+z?7f#3(HMiac5?MyS_&)taI;%gj6ByDCw2?o`}H zS62CRkX<2qJ6nuIJa0!!xCabMHC>OFGhA0PGXjs8{AI8sMHnsM+j$To&Bb%c#%TZj zi@3Op@v5)tH8eE3vXbqgtl&I3CG}=`m4KQW9aD*C;l@p0=yn>9Hu)4Ep@JO`r33mI^CA zF3yCz!{u8wjsop>Y1-imux7&;rIrS&DI`WLiSa&pUfYx>2E%kQ+0_mC?ez>A3e#98?&)ioRlK#-6lLITJva{@O^&DyYJ5YjCD@0}mb=wLx&8c8XGfV{Tlj%=kl2&MzEw zhZm|RdW#VvUE_lGvGw|5?9q6seb43OKAB$h`aW)-`_9xTq05MS#z6>f{@Y_;mvc0# za^raQIjk7@_=i|`vTo;xmmoSjXBvEPE?&NDf4sNMaDsQ`%GO0k6BFiC$q>VyQ9j69Xj=Ri-B&`=(tyg)BWm!#Bd7OW41Q|k=U)ty zqGRbp+;cY48AVG<%**`!X~5_uwq>8Wxcy7eBB0r)d8T2(&Xw-u`vFU!uBO6cm9pQI^TwdhTy?+UPnZ%a6l$PF-;0Z_rvrDa@FD> zVMH!TB$jT%-DYu*3ejrVx^GcDLg{sGBlOIPAxoANZpUPw z_nrJT`7Fo;pL`4sPL+;eUeHMWn)>MzK1@B9%X)o&;cFye6uZt!r1AP#x#Hso40b-@ zpL1|7Je5}HVVaREa%Si3>h9i?ELS2ddpp)vLxBv7jC`iAe~Y8rqmflSzd3-2^(Qop zAZT%0GtJNw+HdM~-T4?8sJ|e5ga|SnO;|+uSRysPC598l!O0?kB9FWCU`aDo0x>On%=xePI>hOBuQBt|ZRNkvyZ`jytA~yct2h59hsy-WyCC&>Z2qbLu zIjVjpQ8pp0r*S8gKWRdw{@HqW3vnCciz5 z?@4NJwG~Q?dAiz{H%0KOC@HN~OQDYHRpdl~wc%!AyiFzW>B94fOY=tQ21P$+OH6$g zRDuIL$QrV(Cw>WM^%5)!Ij+3OR?YSJUi+q>`FLue{R7T10m} zQ+0xgQqY_%iFl_Y$Xn+{uP}79%pOf*Gh-)YBWPzM=y0edA(4l#OSD=OP=^<9@{q!l zcXGilEHUwE=pdKJp(D}fjf&56-hY31&Z%p&UuMt1$q>C9-S5LFjN@)Xtsqrat_o{( zzG&xIaJ9xKAtvVeK$Z$N6gsw-FMLlpUECy@H{Wh3nv^B3?K#v9Z2MB?xdTdGvz$ z*84mxj?O@#=n1QK6Je>2%6@?&oDTI-gHiPkU zbk}m7;2Mn1j$28f`rO{Ca)I2cVg{Fikug)Rz7D0T08_H-Y1{p?!9|~ zCi_ng*V~CYyYHWBJAAvk!e`M&z(4*dLm}}B5z*ay&jXsCNzCW37kS;2k#0VE!e=pP z)DlPxHxgvuiTr4Jlaxln$cSlXX6A#xzab~(uM#=v&U)L?hl3A_N93CQ39jPfGYMxe zl^dyKX$Jx7B_SpK0Tn8YwMma5N1mCa)M6;zX?>JT2P#>Iv9pF)qa3F0C>T7zPz}<5 zilzS-FY@G)2_}CUr0(QBh3j2=xl-_1F%XHw5qD1o{z1(0ju7Zh;GqBzqQJmVW%d8` zqJq2DF`IXGcDANAu)YR<=_C7N&~IagnvMY<0L6fwTT>dyDyglVZ~<2GwS~w6F{d@k zhw&jR1KIAWC#(wlD+6T1ApPFU|F925czbtuZji9tu3w(t0BYZrEBdqcByWCy^Wi7& z%v8>xJPh@*oGgk3lqBYIj&tpCPlZIGXKBA8)l1#T zu;{%GZx@^N&i0U5N1+(73p8`}ZKm$ty<5B%V*H6xu!*&6C+c5hW1c~mN<%AGm5m$^ z7k}gWB_W5Uh7`YG5ky3Icnr7ewffT?Jg4eJs0f^nqpzBpny}QXj9BPBwy=Sr1T;TB zKSM7AIt1{4WQB6ZVq#+YU9Dz4>(siSHM#euUs_St6xe_|8@br=QmV)P9VVvh6FhP5 z{u9knJzCG@WQ+h%l~_;Fy&KZ=P9#|6{}LAFQ(rI6W7_lMu`h1Yk^hA7rw8%nUx57l zeWM&SLDzM#J|-CN5=Eiw;sZ@F%8VB8PlfI4OJ#w9^K%0Qy`K05wsVqkyl-Y*#g04s z#>G#)svMRtG{F43TFu(m6rK`TKD@cR*z+2Ns=i7{h&v4n|3^j!a<$*EP@j{MU2}4e zs(+b!AQB;VlGAVu6T`y7@}c}1GBYE|5Ewv>0P2~L^9Fvym)lQWwi+*EAI?W8#yosW zy;-yS*|cu4C!WV@T)@!KkW$c)DVY4h?8r8v2&m9vZ*147qeZYzdrFDrh!PM`20GoV z04P3&77D;#xMoRAjQ#8S zV5#}wecQ2yhDUXWvv_Mx!U(ZlHegJ~XYY@oaetCzYsA0O0FxHd!MG zG}8F2YnMvY1T&t51R6qG5s5kG5NTQ2W|QK+91Wg0J`2gY_?x>OjG-^~ZGE}`&EMkTA*r6wO?hdlJ2EmdyzYc>U5K>KXB#-JgdP1+yFI*vRwLTU z9SXvx`QL(&N@yXE4=2vYkxKyl#SqQ|K`7_|^Z#&BrsM&4Ih z>dzo5pK!bR{rmSEt@@3W!M&=3Mh!^YC{eDR8I0Jp* z6@I?IqlbscOl}hux5E|t#qRBzLB1^3lY`CO#S~e#&7Y%Y+;)rIR8>yvzo2u(3feQ9 z6vv969s1_!RPXdFij$3~VLm@IGw!k5lQi_+*H@#|TqSHb?Z=O;wwu;lu$aGAo&90s z5fe*d*Qp|{rdxQx${KvKS)U9P+K@Z;r)KGW_}&>%wW@L)0|QT0Ts@6wLEMVg^XLRl zU$NbGv$nQE$$sVn4&^7@Ps}KT&3Esx>W)`fy@bzh65M>)f|w0}+G1ErIuf1S8j7g_ zlgEyk<{d)ut?w`4QHq*4`1HdTV2)T0kJk9Jf6tm-TV!wRsl(bZv2SBTk#U#H+IIWl z=`Mo9f|h~7TSb@1LR?&&&TZ+oZp`)tSv?)MzP&rLQ3Z>0d`3n_)0>+JS&n)Mzz0F0 zp&9lWz4-KE3843cL+xK1DL!&r9rCDMu;@(^?F!!2{Q-mDcN~AhWt8+Kj%fVQ>2l_=|CC6yWlf{lb+?Cqo96^uzf>K2xY(44NbK+y zZ1}%FU-}w%MG=#e`?n&(^L2DD6Vd%p%h&bTZl%!nM(@idizVV*CM@tcvP+^yk!EIQ zN;rLLF)uB$TaeK#x9agkO|%c@YE>eW+@C8dBAbcCnM6esVK#x>{p#VL(w^tW20YUW z91R0~Korv(qZM}A+Vnn;pPtr-=Gp?YCE#@`fMtqEGTvM2I|X40%FxPSZWn8QO;hQR zE?z@0M_tFxLRXu?dA{F|Z&LgCrJ-kI<8fVK+Do*#5ka(3paTY26*h7eo%HedQ8`29zx(_bK_zNjYk^E_j|C7z2Dd zN=L8iozE7w)1|_cW94X9hD*_Vf;KW32AbD=X9TRlyS%)AmGw4iT4Tk%#c*)(@7cN& zhh@+rbcpwJz` z4_GL{skd6?wy^z8x?`~4buHg_Omv+}G5)6x7%Sq+onL!E4RkZ8r9}ePcE>wx98T&G zd@Ak_(DYz$L+f~zspJPj5$W(bJhtJIHzdvzjud*{=+e7Oc0{(wTGa0D>)+oVC*h4@ zl!H%HJkRCjTNmtX57tHuqcvXS22*ex3h_Mbc*VShr}UoZd#=-4~x!WUnucuZ`zrXSax?sPpNT8BF76}@i0 z<$XFwe_H?SJoN2YnX4`c7)G$aax|*_)8*ssmVVzpK3HCjwJOyVoq59@yA#p^kl^kk z&;UVUjESLSi`o&U7k1gwCudV{P}B2NVMiOAnigA6i9LDpM8I+7RoGirm8|)zE1;wJ z<5M-kzIy}YTpYbeQa<6NRoKP4I@SYh6|M$bj8x#5j}qTq_OX*N05*!^yS&AwJqI;WfUzd5?y|Ar zzr$bx<*CPyAD6rxiaO#zv@h6&{1#r06}Z2_2& z)FIm1pEq8mb$fE?*2K)UhxW4+k-U8Q(jjE!*W!a`m!C`TZA^^qwoBxZv8ryt7xb6B zQ7*HZ__a2IJjVk0_WQG7@*^w40N+sYvlys4AER~Mf?)G=zWKwnQFmem*ij{0)p%>V zk=Oih;KR40+OMA4*l?2ERrmq#mjIHVo}TvT$J1hNSk15RRaO)Q&FLZ)71hzA`+DgR zC65U{z|sUUPik*(Z$ydnlxH;T{=Og5Bys%K3V^dk)T}dp{NU7Yz>0hLRt9Q@>t3If zMv2+W?_->|Z~NR$_P7z>BMBAkfo91)8@T!peg9$l&?<9PyxUB_lRy3aVQBhOrI>vC z>UQ*Z-p$|%I$3ypz|WdjtXmNXBJb?_lgTMh>(VN{`WuM+^o$I5LMcR|aCA>Re=$_| zYk4xjiZh_T+&Niz3Y=4{FdT6rHq|9^HtOE{i`Nw#SgT~wxG60goQnZ(ZjP* zeHP8cz;Nk>x?Zc>-qK^x>wl%?V}JlCt~z_ipmDa^BSh8MyRH*gYO>^{X=9qzX8n0x z3g#V#xDkXszDEqd6X`*PI{fZy^wuz2XGe8 z=@~}gxIstvdBFS<&c+Ge-z=5j@=34NaC2z|1(T7RU6fpQ60zyg{{1s8W>s!^L#$R~ zuJ-QG)$nnj`kaK6gJY-%JdmsnBf{#XK!2D6^?M=Cd2+w)X~+VGAA=c) zjRRfM5cxR~*fcr1{@DjVzpyV~9yuV)>c-Htm^~;LE8?f;b#$qE0tVz5BlPyZfq?DkGq2>-SqAa|eSWP0ct^I%Qh`VaH&a49u(XF$+%bT2r4bE-bsG|9^!DiPHDws8t1 zxr=~!c^z=^La3g&_>_-AlSHrOa+RYC+ye^1{|N`30KN!h&5=4!VN(*sP7@x-@3OaA z@1Crxm)HBL{! zrLZ~NGSGE9N((NVX!6737^S0%rLt77_kmh}iblr@S}+q(^WJl$#S&jT^5J^j_M+0x z7<`g=YwnR}_$V}AR?#p8&uIEPN!w$|3ZB4b$?R-hSeBS(ODCqH_rFLhk>(5h}^ zn_zo;yQDIWAUK+hSx6{Ouo$^DW?j$a-RJ>oHbyk?JV9Y|I&{3)p!X8jsdB)^pp%>< z7XoWGZ=82to+o|TY8;qd{kF*-&BWq*m>KjBvv6=t`=Mq)2(8$ZZDL#b3bZz_NjsVH)G5o#VomIdj}L2Lca@H;s=~i#oOxl zW$l&r$SW8*BtlVa22k33qVpt+GVM#96iQLI5>xja^}_d};%nI7?2)}9`+t=Ir20nd zdBqOtxli!q{`7kL@aBWKa(xh0L>(7%D>vp7B=qqz&X1=A(dO-Dab8JeMkWDST=$>NnW7Vh@WoZWQ*&r zYfSPDX+L#xa`NGu&*j~1lU@( zS(0F+$Q5s*%6YDtNX%&GYv-L&1x)D5#}~KA^Tf%2N<1NS$V2Y=^XEQe8%^uj1^*u{ zMJaaWxq`wXERdtJ_K#$&BK=;X2dsU4eZUttYIYTLz1R0|ybT@i=OPl{p>5#>Nwl63jHr-7_ecT<0Dn2k99yv1O#i0+L-805R4dg zH0QCNtT8<4C0G-7pVCMlm6%^4Prj~~bzn@b5$$lB=(F3Gt0c@@Z9Dv6=Fb8g=}zQ{ zuH@+5FDV>b_W*}`Z*3%^)MC)>{oVX;-){YP{w9dQ60o$@%PgsgM7FS|#S*BlUw;H< zt5bDt1M!4k|I;T=e(KeG)w$UrZc}7bP|K!P2&JT^#_o+XMX~8NfoU&lpgKwoPV}#@ zET`yAZ)94up5f9LjEeFZk`H9nZ;OkI;hvK0n^~uHH5T7e(9m>;@J}v{(5(*Ub(QC0 zXcscsQvpS{(T{g$ogb7l=s{3@%?5L*LaeR28AC;sQj%Y8bX1j`&qzpMdg4lc+`%sc zn}BBQhWfL8jx|9iH`GQ*@(58xXA5wx%7rK`8*r~^2mxm{mF14b@VFC_2m77Z9q1uS zYCIokSA1cK$N*dylspnj<4)*%nIPRD)qi6-n4H^cO+dA#@>KZRhk_GeQp`%dL4VzBnMfS-uG(cF6I?Bv^wl+b#I;xxEP$wZUkpF8y5b~b?2Y- z-t;VMx8krRxWtl$&Nx5$x;|D`Y=sueQDs#W*}ljq^?4qRnyNP&d*JE#rfxqQA{(Ki z2b4fH+klR)3Yu#FE@P9PuwU$*DU_n0TZq<8Z_cIN+2?cbwM_Dul?EYHNHOI1 zc=@j6XG)D}_kw3TzdAZ@-MWSKZs_cUTG(krfB8?EuEt=U=LzXw20LlcunvwdnZ(A% zM)RHnBRE3*INxf(A=0+fvs(ZLbaPiXK}uDX9Ex2H=kBHaHU0o1deEz$`)&Q|px*L$ zAKMW*4NvKsIWY@`7*|nmt;|DK*6f;U^33c1RJNY`?ff#>`iE26sh8Me0@@kilTkIJ zMclFuz1a7f5*|K7P1JkAV5$5N(H7Msxx>J)Ly`7>$};_%sP)em$N@#ph>sX;>q+!f zo@eznow~q|$VUdAWboJ({n$`tV^(viD)cHHMb9Min69m6zw2MlS-JsU&W(FH`4gbscDDc~1Yh{L5qeK`F_UsMEYuYoq}D!*v~&<8Qvi(a%W`x>h9vRk@2SnBq)Pk6@VK~- z@ZAe`Tuy7lhN$SnLlr7+Zg2dL0EL=(5Idbo__)OOC3JX%53oD9kx1`bEIOoYB zki?OUAkOIOY$g)zj<>Fp&fZczJUR+XN>VU1WFXH@>&QE0+t6fF#Ty!|i&8v8Nq=7l z)Eb7Sl9$8;rLu;8DmWmP45J}O_g0r+b#KoB+RYU_yxkgdDBv$%d_lUxg#gQ7#ssE) zUiF5M2_jY=hR?B*Ur}~fF=;;2R?+tK&=v{;Jf$Agl((X}`F)*gr&jaAqT41<3(;$n zweeDPULQbvw5r`7WEirYVa3xp>XkXoJ%dt;OGy13dtv-d5x26S{R+jO@K77~SHdYm&bJ@%h5U+S)%zp3Fy1^} z8PLGP&5el+ft{j$$_DfJvQpF7{8j!;EQm{@7#YgQ)KocDk^r`Zq`EpKxw!K;%?GN0 z)}&Vlb3tmltUr{egV8%-q_AE@*RQ=URbL*=y$RFAR+bysu`oSQKuAbv($YcfP?O7; z+oaW3BCT8{;rJa0XVOCmBF*|-rn`0j{5%dP zYX6CrKMHy`x972gp;!>MKJfTYlw23yfnvj~kkA2qXmhz31Rs&})7|bk!C+*vcak3- zMU~bAuCtj?59MQiM0k_jP)i*IIA9zzGmdOz6J2qN5l8JL~(8 zw2ZLuxLG<|-KOPvJPyw4#W)K}F2jq7!p_VL4DX?-^aFwhiE%#G^l)oNE{-<{a*aG7 zGJvwv01G*&)vyt&SgGc&C@#jHixqOrGEJ)K|7d3*4uXE`Dl(@%lpX<6>`0~kT_DwF7K#Wa=7LFX@={|GiNFZ=v;%Rq_bR@*l5^;4r!Zb{Js~E}e2&Q~6clj6=9J%@ ztc9GQ$sxKKGfn?9Mu$%>+lRa)+kc>R%+eFt{$HAakk0Jlr{;;3OJXhJ;o+eI9oAwn z@B5qnbQ&Rtz&g*5^-af0gY^~7)3+OM3#>0E2*!WtGM?7{W1DsH*uFPP{>1`~&?I>f zxWXV|@tXa92N>>UrIIl|<*z-ujai_SIMP%imYls|wea$h)YE zZV3YR2z)Pa!U|P$0NT6_Xn!~xyF>qS4s9#PQ*(gt9&CVOeiTUyXqg}VEQdw4YMsjQJ9ccih`5s zavIc*scN+wOV1*|-KUU;D+zS;It_Tchq{@-C*c8EDhQOo@GLqaNS8|1$``WqdB81E!!Eq4+8c9;OQI3|!-K&g*fnUJE5ltS@i3>fa;WCu?PH#zHEgD5_zz2Eg_F2vMDi~wtDk&GoxiM=O>d8vpwGkzHP5p5fSXEBnzK z$x6N^^WVi%6m@5A!cy8M;9pD2%cj}s8+R|VnmT8`OvRl7*7+>@HiHs_TCcSp%PaVd zNkr`Gini3NXa!yo+xO7gv=t~cVl^mF352}a7?iL{2i1K3B#9poZDm;1R{hOY-aWv^qlUzI{H2+nnxBpD?k*8_w%fsw}HS9qtRA%Q@f(> zUc=3y?%qb5b+v0_^`U6-bxiPxVpI`q-Vo}CRZFGJA@QVI&9OYDOJfAcr$ zt=4T=iSWI@ji0b*zb{jM<7(j^(1%`0If7cNfFytvr)uEGX3PZlVdOS6)cW))6gW0sHIgu z8E37T2XfP&^#d!+{`EPh?4b8PeQ8PWnwFmaC*NAUsHkXZvQ`)f`UQ;YB!T*r4o>af zT3-Yhq%Mnst~*TUG{=ez!jd=0$XaDNYA-$l7>My%F=oQYwU%@A?m5UQTixYbk$w(K zzkPnPZ!A}K-Op??*DNt3hI~m*#smbTj@*muK_w5fb|)*BubbF^Kr7^MtICuYC=kca z^Y%0=)NGltEgBIk8UU%@5{t3Vxq8;d;B;Yb352s@kRUV1qL4yld-ioU^*!!PEY735 z%1Idz?{!!o-7i`TWl*wZw@|0xZ>l4O{ZIZtbF1@Q%;5BJ8~ond2B%Pw(<`B32lwLZ zMkN5H#d5pKWFB9^#|LF>>h?d=h@SEpKheae&$no`&#CnE|T`3-Pnqi;_1gR`cY^;St; z{;5B{0l1+*($cWE2DPj)9S%~%GNn4nF0)rLCRX=du1me~Log58es8;GkF7^@Sh$i~ zI1Oemf{7~$H!Ok12FIy;7Fh&cGSv~}#r1xA5O%DY!Xb2WUrh4=Or;GIaQ8TvF zP5-9%BActK*^y(_6NHa|4bX^tou(Xgc6QQ;dBiL&nPD9ttad^CUv@yspe_jQ4{qTX z2!VGkFtD&(wK-Qp8z6{sbZbZZ9|{P>eEmvV_I9ETMh2%naIx4ky86>0hy5WS0CW06 zNYZIODp2c+HLdQf+s7;xCZ-SIc5KfC&~rO1y#NLMtr$S&3n%w1wOlo|WrzhN zQVL{~Yl*s(C#iw2a_URt&L>q+g9@y+PhSP|+PmHJQl zelqv4sIG-3GhTRFzO9CpW>t;)`U5K}7}Fc(8z-MqGzAyQ^xTT_dlJ+LxTFUPDL*2OA6HXEf8est|bP#pcY|7fxESNAV| zy+@B8efOSrd+kjc_HjR2z?2p^6~G#dR4FK6IpAtcCeCe7uysh>`RDvm3P6>d&fH_rKq3Rj+bj0U*EBUyitg!W=|`sABt5BJo%0 zM?fn@D54&KBRf2-9>oEL!x0?nPK@3-ZyG#*?SJLAL`@Sfx}5?8e-y zCKg;GIytZzVI=JK;!_^G1OSE@c^D%=e$~}D{B>stI28q^9q6oNm`fjB%cg2e&wr?6 zCk}Kg9fbac7hw?KYF#zRZ63vh;U)FLSpMH4xc^m#_t##o*6}Y{$b@xe{57CWzK%d# z_BxP+{1t-|*1wJ!{ueq~#y_<+W4Be+H!ZELuI|K2lK-?6JI<{)dz(|TP~z|EFJG3t zL99&270rELy7d(|7yreuXQVcb3!}CC{Zh8g63RUL$I99^joRUK<@e-U$zI5GtVg|z zGq^ulbWZcWfdAWD^WM5=ggxmDUt8NN`NB_(Yb8PUjM{`r|*x2EI0yo3=B6U$)z*)i+2YuBb%R_?cMbjoP!=x7uK1zNsi zYCWE;bvGL;dw@0FmnwCIlI9&Tqm({mu~WvzYuzbcw|{EQ?9cddrPKUJU~xqS<>ebh z02|L}v4DT$fWA%vT4;ghO+z@~*9Bk3WUtCG2x$I8b#?XG=3a@z-s%w1@|)!t$N{Xa zuM=2hC}n8_qqTCJ9L?F*=ECNsm1{Ar^uWi$*KG_S>qfKd{Mkf; z0MuTR*?(P#jg(R9Q_JUdVYty3N=omKb{AjI2Zmk2BWQ+9@psj1`L;JpVe#?7fiH=# z5aG4|2#R{km1{i_;<%J9;mt;Q5a)SKv=_bEIeO~1W>8f>;>D4P#H{KIB zOWk7Q#n_k^K?Zm z)1`M?5G_0y*hehjwI)E#XMQnK#_#XnSNL=ylHNOFeu1J zCJpj?IM?v-W(Jz^+Lc4+fQ7akJFf1p_jq|f^ziVoIqrS~%7;OdI|&T=x~MQUqg055 zrW>_FqL|;-%#3=CSz)IDfhc5%gQ2I+&Syp}jTGMKF$M-?NXZ`W;o+hFdRzv_ zbJZMe9|&Gx^1g6z!PnRKX{0T0sp3<#=jkCAWY@pgv0Yl8`Z4!+S();@*QKvQzYj34X}(VJdU_Grs|2{{gf02i2HC{p`yM3uVxti zSIa#iCfC=O%6R5_ko@9)q=3uxt+r3JsZ*OMih3z^Gs@G;N3SPF9S>0<-mB4>ukK&O zz4RpWRSHOB74}HNuQGRJWMpg>ev#GiZ;PUeZvyBdx&{`v_LjkM~zqPT!g*8=~I=4XmlD;q)AJ zupBER5Z65;hRbqNIxk3J4$Q&cGisYfiEVl*EEOKzp&cR`>)py2_edqn=|S&+hToUxDNIUEo&vEztan94+>k3H18;i?gj}o1nxKN;oM@*=aapUs zKZ#2;bNieeglN~+)*$GXhYzB2k}v>xzwyO~drNMgfq}{fX%FyzAf~UEs%$P5S4Jls7~!DkvzZ zl=Uw=sEp>+Sa#jjvN`_yW^Z$d-uD#O05ny_gGww-Rkr^b z{OgOi-h-a#l&_JI(uG>_2Z!6Qm%c@;56>?y7QG-L?)=KsD#XvPc1~cj_cb^e4^pwg zAT07b+~Wg`7vL8c_`EGgH-~kDDeCphl(>zF>h>p?{t#YMoOf^dwDo~2>%DvW-$%9@NSH0*?8-t^WQ1GV>)r8^LJ}q zBNeA}#-}a|QrfjnWJ7j&w~=mydFQJ_URB!>eV#fMHrNme_CsLN9}@0i{(|!pF=SE( z2Dcwtk7^^&cu8ev^XoRyCn#caYGxI)hmC_f$*Y)0ht_4iEu_TnAqwuHrZR)!T&-YVxKb8vmjj9*2v#>mdy9W&?&AWGGgo>kfFZ^s1qRF?o zxo<$&0T!RHb6dUd>8S@+0|c^PKxG6;%Ha9d7wVII7m7l&J_fKNZVTK~uYcQGWPDzZ z-}tx@TJrxW4pO9plt>E*Bp9R_LJ30N%>DDcS|A;XbB1l8y1#@jaB;8Zj0xD5#8ALyaqp8*yy~oxc5-G zi|;UF?g@C*ACfnsG&`>;>^)^X8o^o1{IsOHQ{9cYbC=o0>4GaoQt(YvGsC;7m^E3O z0*A+=FP#^|@X`S5ZKr>xKZ|YlioAb5*|M`0IV=I*2{P0Sn$2VOm(jHYyAh9j-0#Sn#?nq zdOh@@WKnz|o^t|j{%g7s^kJKbcsIYbB`?T{eeqmNj!Vg<Q3#o1|tqSbe;X%r&HR)K08@xR=BCslA*v^u9vwE;p&ut-%kxd!Ofd_)wu%1J+LOpKa(sc`wZ9bDb z*vr${&GKsc(6a&1c!wDb!l2GhHrp{rh5};t1!OSV-@J+bgbnBU(3PvxW9-pXTUd}; zNp4f=2?}bUPN+MSi-RHbBM3*nEQa;j^dlnUjo8x=RRZkfH(MD{9>GDua{3L?c|B07 zKF8_+4ExxG5ZoeG=hU!nT-!P_BDd${NyGffGx@xOgYXNB=x8zX+D=P+Z&O>Fv9Iqta=2Z04RPV1 zl>H>}a7lq_mZ82r0x=3^k-LVk?$&ZXuK;pNfJi8x#*1f+*2}g28Lm27AFU#U;|l>> z6YR_KCid;wLmu6zcLi-pVn$s7r|!0P=!kqA>ta4(Ku(vIlc63!Bk3@k#RKT2a86%6k>N|TF2WsnFY9YDg;8YuRP$}&qyi@T6z`HeH2 zb3xIw#4c(&DJjVXjPYkoEervU`!Z?f_#vaK-fIodV+cPkrPs86pK`hqrkmngZY_J>yODJryf zJOi0J*g#SF9!G0VgH=(}>+wA|obvHn9}HRncemu>UGWI$W`?(^qu z5n%COAPdMV{BfvdBB;R%%lY(df2ZeRcE^0}5HoA4B8gO9{$Y5y+ElN)y4t+d=Mg1j zXDs2ES)W!z_fPw@EyN5vydDVFb)b~w%XcKYFK{Lmq*|D&xM&-EeTN=L7@_5TK(Zx; zgeiKP>FNdlDlt)u9_o=i(O+M`8OBfS?f%@&bG+K!k!)4a>d_VuQ__HYd(kI_+(wf0 zZUvDv0gGY_CdA8LaCA%%RS(u5dZ_2fs&8x@mp9ws$>c$uANb>yO22a}MRTf$v<=Xh zID}L-*4b~s-_5Uw^#??E>J)!p!IdpZQ9`=GGm`Q3m+Xy=jh`R(+X|4(rN2pZ$@F%< zLrFK>fgLdseQQNrzOp#e=n{@BDaD78$luwu1?hn*RhY^pksn#ge|hV_$vf((^e|vt43>%Sty`Psi*v4C zy&5wTs~@5EzLK2(^$#NgD^*M4DWR#k*$@np&897*P+5|Kmlx^#zUiXxI%%648Cj)% zAGyqjtO3h(V0~s27_a}-kwOF7NOdCu74rZ8K(bqBB%eMlhHeB^$!IT9tuJ&n^y<3k zelCy_P>=fGAyh_va8y|kTGdzvPL9|Gr%Dl=@SJO2*A?Lpi-~aISk9Ki|LQXTGe&bD z)R0>ppyXN3;__cE4_1qyI)*M=+(hPX_>R~m&=J#5f5<3YC-UC~D`IZ?OFI}dA}=b7 zQmV)x9m>olzGc^iqER@${L_qpyA$mPV^S^TI#ZeQ%sm)>lVN6#J%EB(;(nO>muU zlJXm|6Kk|Yh3w4u^_;5R|MXFW-Oh%1BFrbzo-eCi7lGo653mmn4V_lR%3nY$&_V3T;j~^D#b+Xn&ukH_h5;ii>t?6LP zT4*2W^h39kdMHaBulcLV-@(2z&tgGtcB@o)vG~%`QlPh4_Gc}Mxy1IFn3Bxr&mVyR z{C$YD4W=CMB7V--i8a-xV?{dxJv%8PPmd*EQ{^a$S<F3nM~lPxK3z{{<$@r9c1P2z}iPAcGX76b#H5m?q_WMtlX4IU{ck#=6O=}NZg z+>1iV1P+*$Hon=TNyOj3mNBNYtD<0&J%* zd-3}5ka+~UFW&%=5(1H;?$iJ-+fIm3tOvMa9Ls`aOMR%K{mBLFz>4ZFb1J=gkTx;l z3?Uh1b@kJ5lZh}6qP(Jl7r~`&V1qWuvNRCi1mh}%F8*~E%wb~hLKa+yszSHziszph zD5(SPdz41IYS6Huz-rs)->i2+_iaX5X^?QgHD<`!X0?3#?RHAJm193;mE32taZ)bQ zMq{PipCuGy7SjbD#rtAnjbQOxY$>)=1q9H=B;d}hAK1RmUOovUd@i>f7?1&q0^Cr_ zNaX#O+uy;g9iXWHHkfqQzyXgo>e+oEW{ZJ;|Wil^` zJp-;$&1>y4O4&*$uNO+rFz3X=8$taVU8smAPbRrZ7xO}=t>HCrn0pmD#}n^vemN*; z$0OD&CQln6yA}y%eq?0b?G2t zE-pde_vTV`}+r7i@*eKc@D%T(!2V?d9Q22Rh=+gq(6K^9NV1`aG-ce7;YjZ9SG zXNHkmZaXRW5RkA>15^b7ZdFVjO)a8=f-?>l!*c&gp+3TuXmDyclOs0+1;n*Y!&`Wk z_Cdz-3hy)fjc;G}S|@ld>?rs{$AP~;5gnHhOQH+d_ba53KX-qgZ^jpnwthLZLYvU$ z{!oYk0;00V78}DN?}AGX)=y)Cd{jzG3asC-*|_HU_Gb>LNGnxtMM$<|qR*sCR8}z25BV=JslPu`*KGsHasqF){H&d%GxX(w9I> zE{>E!_vahmyooe?cwax)%J5B>GkC^AW_tTuO{_&Mt9K>+<6(N>yk>S3;Mqs73d@%D zW*$1Cmej8m6#gzSrWId1HDp)up*~mBG*&Kc=w*pLdSa5ETEc9NJ6pwO;H3lt!Cwlp zrlO)^-D{7BNQh!{cRtu}kqP6MwILDMMRg*0&E}J(m_FP(dw8O%#Mu9YKu>ZOT>$-l zLT0q9i%)NO<Ok+BT}?MMlQi*<}z49%XF(4J@)i z)X}n_Ln8f*w##V2s1hK-Y3i>YyPE5UfPN5qu%*C1vH%e&8NtSrt$79 zv%nFbSh~G}rY6zC@8=g2t*f*N+k6ac_uK(-%yX}I`H!H`%zPBvt<6ts`KNQN`)YgI z#JyjN`=l=VPk~WWedtN6fykqsc$W)S}-nw90! fVt8_2J%=x28`ADKXR$9Zx*TC*Y++Pj=p6YUFDgL8C#6D&|+q0W@g)BwwNUgTg=SN%uZ2u>I;;F z$Twy8^pjN&cWEaD%wdQl>#qLrGiS^CqHlpAf z6%`AqqI%^7%kX8%vTvx_p%my#R4Kd9ugS)-zh%Dvx_{M9Iv!5n=e}>602rNdPjCao z6;u+~$~5aF{k{aC3Wb2Nr`kGV?;03SqgBf^i)QxxqUO8Mq$C}ujPC-5AHInx#1ne% zwc5%a18-Z_A96N^uHQOjGT+{aEN-vch9-(E0#zX+{(W{;&pQ|&YXr+BN(h#u*XZoRt6o`L4vdIZ=>skKCIw3pKyArG@d-u-9rC}-P$*Zus#uf0_;cLR z_v$`4tEXOTwEp_JiCWs`leU;gxWX*(WTZu-zScl1FWT-f$SeE?cN_Bd3Hhe-tLVIWD-fu|}x<=iW4&=05XeI3X zhU)rNO2=lJaC67b2ZT4CTj)yi^70D#{bAlSya}fL7saEmI~6&yqOg~^PLtm>P%!dW z>CM@Bq$vSY3JU6_s@mGxla_VKW2QMdIZzkWyFcUNepW9VOPeNKm@{BojaTt&kD0S; z#>Odygf{uBs1S3xYQ9L90FgcUc|;XLhqq}o#3Rwnbokm6Rniv_2Mkr1HMNcq6@OIk{%H;VrCLJ8$dQ=5h)b(n__Z%Aff*MO zvN)sIfc`vkMxAD9^+grFk;Jamu>{Gm;Zt`E&RnPP(+hc{5BIZjq6*e#PTLqVe+uf> zv`pxZ{XQt)@B|vl;%g&n4mXQzD$%}clk&k&j&eBecR@~HaG=cLN-WWnud<*TFYzxr zy7}-%j@*3ylf%L$aJFaTYlLWDek~J*;OdaoOYMy>S=cZ|#yRg^-1iDvWybx{Bq_=n ztHoA&FtsK_asGy2GS~0+$cK+g$ozq*q*fH#?8-FzA#vZtwS@>nB_w8xlyL0q>~1{y zi;I`rtMjPMC28XsPbG>J^SL~($f03i!djZPPA#@nmEj#i=LwAl`UduKwQ}7?oUGFj zUD$4qmFr2Z1gT1LXyJ!-*2g3rs-b9$RY)G^-IU8v#r-7{?3oBc%B8JhBj8rx*GEsK z{Osw-(Idrr#;gWtbXNjl^LgMxX;zrR*Y1LBs*(@+eG!nuy64DPa6LcT8`^yNOr{6( zH5V}1pr^Au?>wMT<#>66mFP_*l&;d3os2`bUN}N$HO|tkh1Du`7#i9*mO2sbP?E#R zKK>*<+f(te_7X2C9nufeM2x4^@Ddmx%CyFSmx$~ z=tMjJy8LJxB2ewrNXO7ZwOt|UQ->~4Z_Ln~XjIzAjY(4+r60K>JSzz>jtq~M&8gmY zM~)L)oe3Va5v+}}MI_ctGF3^J2n#jazk>xgLssJeu@6t6mQkiH<9k@>eiG5b;hVKf zko0N{@WGeC^1?gqDxTH6({gh-(5bcUY}uzHF#t6>I(2Q_J<-0~kR8K`Dkuz#PO(Ul z0{>ngxy<@P zO3!wm^HSECg$#AnJvY>*#}BB;Q}EcT;Mx~n^BjOUjhNfL&+GS4*zM`-!D~kCLoDra zP7gJkNo=l?-YPOe<1Ma){7o()(Yo-N0Ww?NE=O7Xa^Z#+Xp8hl$+4Gp2%WW=D%o`B97G4 z_kEBe%I7lt;oh<(&S?liXyXx_pc=P3>(h~V}x_;s;-)_Ixu~^RKU9V{Co8;7ahm|{* z^14feyW;sJsjkgpz68)w+R<0o)OUKyJz)1!Ld9WLWUBO@RJjeInBp_B4CbW-D;7g< z+;B-PLKL+4s3`)pKL&neP+lH6BC@8h=Gy0yIaLBo(JsTf-|@*J6`?R8QBnPtb+Lw$ z{bO?}SDEu(Yjo9N8Oh18h0o6#UOa6NC2ftg@ZJr7xYa6jDIk9fix$U)mO*w$zg3On zMt@kQ38`YqU%C2J#XzMd@pX2A*3@H(&j_+&4S8d2<_h0Q@Nl+T*6qG=Fy@K-FB38> z5g1j&`Db&5y^rev^{_2Cnqz&!L<&vhieqtuY;-5O zab?TRJJSQ(%?Nkq4Zg2LTxC>poEwke(QJ8Q<&LE6EhekS{%|#lz;Aq~jaW{hY@f80 z63~x{KwF=s0w~~z88TI#8+{}PL_QxcCMDUaXTYs4D~!$jm^1t&8Z1_!ANKUw$Z-HX zJThI65cd9$}4u0AW^3vY3fOp-0k&73a)Z zI@mjtQ*i9A-Pa*j8AV8t<3*~E9^O{0mxxbN>#GmK4 z*@(!LwR&(z*=%Es24I5}WW*$SS4c>XsL;b)#(Ppda#`}t45lzYh;H8P+H^j_h~IKU3P8vZpcbdkqg*I;5!=7PKd=7P_7C6rcCBj{VUHP4FZ z2!aISS?o0GI#R5AyYSj;0(hco+%7~2PJYp5Yd{}rjc;;q+=83xF4biW3+ZQ`hF6n< z`sP&4+yM$!U;PL@{rXangcsM%nBMTUS^Cz$P2rj=cE|MAE^3@K$mVwaQFu5U`D9+w zF3T=w7bJZQ7lti=&Rg-&2%_&u@1>eq2AKQ7%X-2aLvKW1T{y`ct z*IvP6DfjmDvL3%2!{=yulrdxyDXxcqxNw${^zl*{GeBgKRz zCBsh50d=T6yy_AX8ErF%wbbwjxAoBnjN|yW>SefyQPi453*`jo9(p6Vyfid4N+)Io zSzmKI_njt!oD_w1El$GgK>7t^Lm->Su)+egkCQPWS=W8|iW^d@Coo+^& zET0{1b54H>9|_I$fKx+ggf{_c^y*4+PdhIo&zG;XVSe=?jgl%F?AuhM-^w1hX5Kb7 z^Qc%TGX;IYk>@?*TM9kA!mYD(!GK;Ft%4@2rC1tXmR9B;>m2jnDm1xk&4^F4^dkKi zxWGIE3+Xv0PjBchuTJ%%z4F>j(=IzxlH=T?@i3#Q^z-j5a5H*|%jQb^wS0-#6Ic5a9R+37W@m#+NJm^}vx>OF z8)$MZQ_0&c3!9Jq56fGICSjS1@aWigQ@M0R^XgF**h^zBH;O1#nVZHW>Tm8MABV)q zWMyTc_yF6+^~ZRTVr=+GnI^-r>4v+b`N{u^F*eM&@+w%7?~m7Q^eg-b)~z~!FGL&J zv!P-T#93JnY75Sk+bC+*TNk}rxxfB|Dfpru=eIXZye{AL@|Ha$|Hx3KhvB-zH2k*z zfv{Gya&2?G$)$IdFL=&U)PXuuDJ3)h&L$-F3MbpoTQ=ct-g%-xSjqdTpY1q@O z=G?C7noR9&O)4eP$-%MGCnr=85Lfu%scgNB@+pKD%rdpW1j%${BiHk5dy2g72s&}= zqXsK$%n@y=i?Ie+UwgF|J>)uC&w?%6g?2*c$kPZXE$I*Vtrq~1v6J_T zZ7!K(sri-#ca^s*|Hwq*xX_QPDK;qTT7k2Gv2(J zZ{$Aa^4?(%4V6$X*M7_dz2+-mB89y-8&A)!1yYTrvTt7u9eY<^*~#iQzI0ZVsUqx; zXXM5Q!@PU5dnaN!3I%q$rXPnd8p^5(|I*L=x@6G7Y<%G09_r>^};bFAfhtKhz3v+-(w z?*_U&c_Xv@RtFh@b0l(+&*rsJtsFoiEFB{I*`CW6@k7>|w@HsE`lDG0LZuGx8|LH{ zF5Fg2?S$U7Sgxfplg%Qbr$^-EocLB++%(v*gVhK)X84qIDWHp|%%L&ow_@GD{m zQFE$^b@i)E!B{DUaEA z2ktfn@MIvPprCkrdoyb(*Ppcy4p>Dw^0TrGEV{f%0!-YEyiO)3<;(RtqKb>D!wjQO z4-X~kEaxDd+d){}-F1HZ_`GB(jMzf3mxEVD>ghjqUSN-uBV+rJAg>o28w&+;F0ZKp zK(O1$g5l!D40rpg$IpXgFTbkbFE?43d4xxV~Za2g-v^j~w6Tx}7bmwAg9obULP$%i^6*z!ajYe_5t4yOCCt zm@eplDXBQgFbH`BtMK*g5q@GqbVV=? zispe3ZtHniU9K!o2FD5$jbJqCPO}K#P z+T_eK{4J%Sv;rdN>yZw)yX1o2>rveKIQ;gxi)*XF>ls0cHA8T+gM$yMugsqDFbktK zTte%I5SEgrz4(Omr!>Rp>180R-D%YKQ=46X-CH<9BQL{c*NmT*5?`3V{OimAiM{E^+|Ew#`K4NVW~ix8u+b6wlwhH2eS-K69|;y;#hv&p05yl%dhG!( zjnlV3Ii?w(QL6ozI8Zwd0NqqkSU`k=T5g zHhW|%70|*#hSHz7Yfz|VJQ1wSdV#sSZm(#uX($__SMaK`T42081En`pFp%w)Z9b&v zGo~+!nw<)W@wGAPdAy@PXyWxTI(f6B7RS{_V#u{KIde(?E%O& z&fJIE?vEO&@)@F%f&y_bSt9LkC^WOd>qmrkE0X@0XsE~*q^K{0FF5%7Xswv(f9T{|){5`yVVv;@-zHd&_hBUhB0luh)*a0?Rx;3r%E8ZtaOo8My-eY^^s)70SBWC6U}CBC{&_nJfW-Fh|=bFUQf-I*4lsw3sQ75z&qwY%`*Tcsda=vGRt7YDSxKfk`s#2_;xbP+CU^w<@+Q)~o^wiq=(nj{D_T~)S zXDx>gG>8F>O+bEK*$Og9T#)|u?HdZkxG+t%y&cO~RB$krEzc*piFc)XUWxtwnG_F) z!VkQMlP$BN3Ygfo>oP_QUeV51!u#3;q6%ENNrr;mlC760JW0!U0{KVdIbluE#Cl75cl71I)Q@MzcIV?aS&_;@u;71L|tXE|447p2PH}wkG6LgjO=jKGxO7nWPcTT5xFNiLh+oE$E_D%&797%QIXOPHeuXgesx< zDH1N(#-lPx_eT>$^Pe@=e0ri11z zkL<`2%=OQ$UI|)j!X_|7GSS?3y*Zc*UgOWA%+XjU93W|UNq$&WQx;?m#wKc+De;mk zuRG1Mc#+VWpQ83=Kq`5hDeaMpClVwSo!Vt+XHOX;mMM@x@_T-H#;v0M#jRI5%AyBB z1}psW2w7+MJC*LNA{m)NJ?$g`nc(t5B{ZRsU|PXCh7yFVu;=fpd;-#NKrZ_sSL0N4 zqHbOz-#=SQ6_^gH5V&>VX^tZhN|j~V)RRsk+~hd$-7zdNC?n|V6wDCD!vLAXSRw|? zV{cjl6Lno# zbV&Kk^k^*6zU7{9ZFqOGWX|u@Zt*zE;_{Bmegg_R8CJyh@3JROL4eG44;(BA zKWD787%45jZQshnk{cNtGv@~{N2>!QnYtmvifq!%mW0nl83M4?A$VK75(;0`U!_j5 z+`7rzX8Y_t1hoobCXl|s%k^)iUY`49>B%>*ki&tZp^yx|in%C*V0jZEF?Zz|5PFP&3@??oRQam%U2XDP< zA=dZys2+&ALIUAQ-|bmWYCWHzc$HI9=2wJKjb+YT2ff<6`K7yx`%xb=TLA#h-&K^0 z(bge!;QtkJj0Tyuz|UfYSj2TbbWB|z3HpO9G!-JxBg9@3MYuUXzQ;h;j|4vCf2YY8pQVBb5ATU<0NKzGs^JefOEPI3 z{1JTrYK}vi!4BIlkZHCg$oKybuF4xgbRPGXY2AQ?f7AlhlBS_n zAwt43|x$xW&PsAk0 zOCJZHYRgv4BV88l2wyV_FA-&a9h3_{Tq-6JNNBZKHel{}PW!$80y&1457gC8)x{K< zSprMpapF{bH-{FbgtL)$hN;yri+JOiE5iCao=>vtC_nxQ9-g;1w3&fH)S5VV#ETQJ zAHW{#3;f4~WkaoAyg!Kj*19S>-uj-)8}QcsG=e^Bij8XZTmrhZxvIj)mwh7KJ#~Vh zD1&Td4Z7UGuubmi61P3LOE$PnFNKxn$G$?08Tyvj_Wk#Izk&a<)!k#GV&*aW|Mjp;ng5 z98;E9P}aY?jCy}h_61u5XE6Ai0;YgZK45uv;1&jn{5AKn(-_KGcFsa|Zoa^+r1v0N zyt46;Ri6v0*wW;1z^HI5??d{*}8z++^V;dmrD%+r_}^rYQYk!T+As;sJC1q){l`fE|jtkGQY6c=T-T zXT!9ryi6m{a+I@+?CW#$5yP6cKr}}Ma!;NFEyNOv z`ByIIeRxxbmsBM+(y0SyeVJZE*(_OAwx|d0e3U9NHFQxe`nt{nCM5`#N}*w{8bMmg`CP!tdPaJfiIjF zneS-lS-<>p|L+4tb48q+Tzi7YSn3g46I!3cdR0P%Nbj2L`_83sPb(6eU##*}xwfq4 zA0R|+odu$``U}3F%%NCIl+NMZ>=*PFq;bbI9xA~-K~Pv%q}BHM{=~sXA$VNtTsu6n zCWy7niP!VyNccQc4r8j+uD$2y(9?u(dZyz6S_XB2({%A5jQof0I z{gFiX^0LT(BW85i^DM`IpEeX8ME}bnQYHNFINtx}vH}|K&rdzx*>sQ9KakxO}o~9roB<_r{;6Po&bS(NW=hk8bB1Dt4^= zZ@7~^7-c-Ny4=}Iq!w;@{g{Z_{!vuHzJiB#CODvWx1Z1Zdq~F}Nm$Oxb%nG)@m0LA z4Z)*SxS`rOW|sSduWI7_23eYo1D*Zd_6sjSk_|xN+8MKeeNU zn*mS@57ATf{kziyL8uN~fiH)*ECMcAA6ak6zp-ZhvC^=ih@v)(d9j>0b06?c^B zjdIaQQ?c8_ulvgpSOwUuM+7aMEEmu1cRq<_Te{W6ko~C1Id=OX0^!h3-nx+m5`ed* z1t3B`cdh|}Vw$SXYih|?o2=cL+qiHZBnWM!05Ol&Cuycloq2+RD^mvLA2RSZ4R#i5 zCwPQ*koaKVwsbLZ|DbJ;`=NNCsMbA(I`rqI75A?lw6b+H(d-`J38uX-2Ep{VS zcMI=EX`w7RiGnRddlnXO^z`&};iIbMwrzd3HIC*h7 zod#D5@^H&}K+@1x0}2dDsLqsr&5M7gnWoAQP%6yt1#Z#vOSa%yiuF!NnQ$r4 zhT~jW;Xk}sNfR-B(7ztol9(+!32kZNrI7TP+B;P7z<*ol7nBQMHo2ZvgY2y2l+Hum zfyZ$;OS<|qq4<{cJ=<}5@l2^D9@LF(0`AKtY|aFIO+!g>LOyYHwj>P|nPM(w=V&~ml zDVfLX>-~3JF6MAy^9jFyqe9r=huMxi8|hN9H6@sO`26Qw$8S7rb zo7uB$yZwo))~xgT!@9| zx!41-?2i{Ey6HOX6iR~Y)%lkf7nN_>EJ6MpiIw|nQEU?Hf5Ew?TQoR;~)UVpodtgoV?3s*W(VnH;Exq_$(ZxZm=r zmB$adPVBBgy3MuqY12}yKG8xSLb+!Tc2HSSFU6<`7hiRS+`KogBmZr#P^1Qg_xz-6 zMS85K_wp4q)iP^h`iBamz(-8I)W(x%Q9c&zESgllOg)50NXn|s8$tStYYE}WEWvmmEzNmseF*u$7U zTu3fmF}ZhJr`_rrNtd0SE^wju<+^F}wOa?#-F(`{$qvf)^=s8M0efri?&|qR?$cg;C?(7SC zKzC|(uFh(i=T#A}>veo6M@T+1t?P}`SFl)_#DRe<^?N!>#wMVitH*)P5o?VuO@Dg> zXkI~PZ$^RO@0%AaFb+v=tDzeyu=EA9dJWzmp7!BieoJ%Y<2*8AT(6QT8d!(j9Ej}r zpfC9l>>@}^xmKDpg$1;>;KZb`i=z|EMKh}AR(ho|WlySuq+s?~o-r()%wcIsFa;vyUje&atgFzm($kKDZ<9>T^O+5 zpI5PB)oW+}HB7PUz@(7ge*QYrP0X=xF`AK{esPiV@kdJy!?~D}sb|*`KP&qIy-`7MHgB65pKRrN6HY&M9QN` z?Xk!PqS=H*)DqpCJh^a6VKaHM6@>R~k6`*mwC&r77YsG{dz_}&U7mr((99?xP%enH zqgkDAt#psN;O3w!zmPm)NHg^ow=Z+|^fOm^LxWr5$Ownth#rBa*%BqBKR!+M)=#eH zhW*JVt0uQrx$Nw06#jz0R{u-(`E>c+F83+!}iRgOkgiHb5!Z zmAP@8D5$||jwZ#Lw;WPXR~{F#Ps^qrQ6bHw_eT^Ph#*hk|sxCc!eDUbbIS>u5kDj zULEUyP|Zr(bm}Otc3aiV7xIt=1lk|wEJtfFIzIlfS->ky{P_OEdpJZ`W6Qw|uj=vg zXqrntK+tVokRAK;Gyc`{ja;bQ*rlz7QjB1SVB#GS&t$<^P19axz3l&r4rj9)ztDI4 z?SVZdj;5ipl0x|k`AdK4o(11|qLQD|iGn6rd9Q5MqQmaLiEcF{psF$3(oqRByrmAh zTdSw-Q=JUtmjNeoN(zW_l)N=@F+4+5xVJ6d(`j4EV-J{lDrk(8#-ChUYkvTn+}}3y z{tvoZ9m!w8NUmInuDbsq>k+__f+IHD3@ihWLW^WPqk^^KEw>VKRUQrp1=C-=2y}y! zruN5#HTre93klYH*-XGyfOP(*;LgF@n~e7LwRR6{@wL~b-WGy;`$I)oAj-?=NZZT1 z#hMoz%rXQp%8A+A&zIKoV_&)Flc#@_+mcUTOXiIe3)>d!tZ=;UZN`<(3jbFq2Yo#X zU@Pst2Z2;C@FYUE{$B8AkB8RTGkA-K!j5}&;Nf@`|8fk+NQ0X+Qct@O>`S`V?D`r3rL09dyRG$SCD{O-9tu+gmE#Dbkw-c< zm%7_^w4kV-5Xyr0Ml;2xh1kEMAiZ^fN(UlXd)l$28&zZQV1j$(5Z8^jvdfB>DeW=}yHyXMN9oCDCrW*yd-6CFNAA z8|Qj$B@BxGW)>ZzbY^jU(u5h56=##to2DmU_G)#~LKxPN%gBDm`7oc=UuTuXyiZc$ zA~$CwGg5bws*6(ch&<+V%=$br6H&a8Y9;G7V)dp|)69I9G_C&1-~apqbEvUK0Xfi? zrPb)fmvHQ96(lFao8a-0bmzoj72e9bQHo_?{ki~mXtPfJqMq7XJJBMpcS@oyGL#6+ zThj6==iaGH5@v*69dg8zIfH*oZBBaHYbK!+*pDoL+B1#Arn!Q5%p>8Nl$90zhfc?t z>Cl!a%6`Eq_o@;H!?z42cBpa6)N`8Zek}v@+kEPxh2MzOVe`8B@6tzR`{FB8T2lT) z*8B0INIe%&lH0##TV2ezyBYtMG4hN160^7%{r3|z;)Zs)z+QkCf&#wi_U|I|ox~O! zB5|*upC%6^bIik+5UiJ3=M2gF;OF^v=5{j}M+v!LMsDnyTRIIy4WYUP2v|` z%P3{24&R^^X!Wz(I`?+Ys@}t{HvQ6&>e!o2_|C>dq>fRQTq6*jb$m?P#UWc3&bz$e zzzD*uj8s~_292`&5F+IteIU5T)Z5>gs3=+68r!`#zdmB-v#c||DUHTkS(*7Pch*DS zo6A5=eURPjK`n~y*iliMErRoYg;2ff3GoHUHavSbv(iDM0mcHa)D>%T5t`*lSZ2#K zd%SOx%J4Eg(m8_E<{~tl7gQa$i6cB2MowB`x~_0cuLHt`N_GtD`N9Qw_Lr%{y1N=N z!7Ikz;#@2Xjux2 zkrHq3LiV`S0_-&F0l{l^jacDBK0}VU`BOttE593fa&0}?Te0(9x{6u{o;dTI%6pN$s}@`(yhsC#d-DQU57%Z0}^=c?fS7o;XJYiJ8 z6OB|kko*Jifj@=$6wqxb14X_9Z?Z7o0X2zN%-rE+Vk!v8AWO=HVy0T#8?^HS)`S0O zZgFS!d}7nMo#I{4S1gMi^>$&OqNJl?!SV3ALH34e&D@_FWVnAGl+q3BPicU7{1G() zgS9|+Q>4qki*xuk(DKbYZT6=Pv8?_KP*|PW9QCai^t5O4{H`?dBRT`^?UC}gibY0K zt^Zr%;-xX|Y{iAUOM0JOi5}TQi3VGVMgo2$PxW3QfX;VG3Z(*ZCL}EL@pgPB-+|wf z%{{CHN&IRxZLB7O`yUCqHh%NN326(X&4hM_!Y!r9Wto;r{qR%5KjTBuj}!HV_S?%3 z;70%t*HPxf(rrrPuGMm?A9?3`^s)>XZO-uhdRu}^)Y8zuSLwDOYO}wqukk^8h>amD zE8X$P@AyI}$Q!%s>U>{8xza|cy0 zaR7@YLAwi;)9Lb~&{8HUlmZYqS!oBGz28pv7m5ac`L|^GxhYF!RK~EE<)#lG(*=JE z&PKfkl2dpg5{E!-SAwJvB%Ykx%B;1}({T7dm?Oz2o#E`5kuBQkp_XYS(qA^g9H!^ zt^oWJ;4Xx@hh+0LtkhlFdYQaKjUmAOc`#7!zk|3CM2r#%(L$|35E%@C1p~s7utBI! zl-2ZnDpvkX?gCph6Vd=w(c`K#Mh>x;?~hk1VLXx2kchNT2YfESFNBYVrQ##i4zncr z-ug&^U#6r0gm8PJF_=pSaqHJYS$7X=Mbdqe?QAx4fl2GHxs%u5Ls#XZGv#oeT(gWJ znZOx$ECZ}rhn`5o56wor8?NT~JcBgf=XIv+PwlG%Q%*j-ihVtBq6*BK;XDL?)g;fD zx>VcgvVE@ED5XU=o`8}4=;}THp;_kz99LTPu_;1c*Vf4fa9(puC-y9w%|U^~EK;h( z>Hazy*A}uH>3Ge~-1v#No7PY3bBF!)I}HIH!6wMAZ22idl-V6#FIe_e4vFQ}p)qxDfobGGnDjsLrIXt^o|dVv`py*D?gcV(J0 ze}W*qXq$|6ki+;02Vl67{`7nur%ighKe9+`Cb&4V<$Aj=;O4>MjX6ijM_VUMDO(eO zecqP2PvT|sd|g|p!$Is1Ig;{_)P-o3S8+yk;u>SG+GRg0U@fEtI5GTf^?|a01{9sK zc{0TRQLG$ze)FQyKT>wSS4HFjHp4i#UFpe}B1spx0WjU)!ThHZFRx5P#{X2kRlTbB zkLb`7X08`uz31vwywUrR%g9RC(EBaovNj^QA!ys|SChRVPDULV_wuIsX0B}LIcrm+ z-sUAr@9tH$W~AisdN12M(!|$9O&>u>ai`%KD{V9n$I^7l(u=zToW)^XbN7Yo3YnAX zEbk$z!JM7D=Ma`Xa7~Z0#`D}`3xhOyX@~VC?cQ|5G_cN3`-{LOw3DWei8;9GutYu5 z`{afc=Jg@N2sklKYYbPW_cF7VdCcLItr;oZaZ8N+nY%j_kfgo@#un!B{{6W_M*OZ3 zg@T?kRZ4u`!FLaaTLeRhkM^&&dPA}F1cF{}38>n*ovJn8kgH*wsCqG^hx(uKzpYfN zwmxJ1Bdu3H)HNKf;s9b4C}+le^XYnp`o~>-z#;v$oap5pctS}V`0ZRZ5N~AJgg|bJ zXY-E&m(Md7S`}q&)Y+_^LeE-xv8uqMJ$Zr@SI!g;aH4iU1VzirZh>0`s4>S1b+Agy z^0bX6k~O3~yH1Re%+m-RmdZ~FJ&i{;C?OPL9 zDJ#`uPq56-m^ugtY(&D5i=7zEgsBxBZ3c*`rT>HSLR1MQ5A?P3jE&Q zy{$;{V?hvp!{y86o=2h#!D#Xslf&bQ+J7oOJAdK(tpz!B3eu_xK)x$qEYorp4B6~r z+W!|aF2;FRa;6SDQ$zaF1u{yhH7$+R*SpGi3Ic9DmXlyqlEo`6ZpM9~(j}P{1|HXv zDrh#jii@ZF`ClF#iY76Yp4ILK!ur25>_-@#{mgOcS@`XdVktq&?P98N9k1Ti0!!K;!$@ z9)7y#CD&I?T>Ejgi`zcUCLbL|zsh#t`m);_XTp3Tv*0YSn0|@1$h`+lc+0h#S=PjFdH1FE+&~tg%{ZRpv{i8s60pu;`s<_%el$ zLq*_b@&v;Ij8zi6J|!j|B$IY7E?z37B1<%Qf6lQNjN8*P8SDvWnE^F-S4t`bO` zzi@FFp@TNDMUYd8|N9wCC!&3yZbdXxTf@NOFPr@iiahH9+v+<)^pPU^ZjAoBUq`*u z0?yRe>s*~W7!_j;vp?DM*n$?@|S>r6b9q6%O=M&|j~J#Y6QPu5+qa%8vEQ z(44?JeK&s6TWMrw?*^s0dpNV+sH{AUq`lC+s%^=y@}#ZomHIha0wfR`xH*{t>H-Ej z*|&B1Cq}pXUf;*rsvd$B@2Bx`gY>eG_xCEP;tV+GUOq0e*qjl*Ox(vS z&B!Rx?x6rY!qK_%J%a_REv*l$y{W? zH*88jUqYxE-=9gJy~nnFw1hQT>*n$!e9r*;2&Oz00uS{AAYgueOkyV7S5HrT3kwTl z<5b&v^q6V+y9MJ9735BD(4QlkLQ4p=B}y1stR0*UhJrlGUBp`JVt9-F#%!h-%+c2Z zWM6`>H}Ci1=_gj3S(yArjdV^U2xddYBGV>Yb?o-q&Rfg(i7|&(x^!@->$w$T6e9TS z=W|(!b-~zZ>!W!}(Y}ZWZU`N#xLWRkM2DpwzI+Ruk)*V&v71bp#(P&3pX(CXAMn>Q zT~RQ+Rz=?4eQ3H(W=xLs;N1!m96nZPK_y@HQF?;b$XZ=x7_FSi;5hlm=RG*%t$|`t zBRs@gPtdo8FAY)8^A>!1t-qB_W5Bf^FNc=R9t=fbG;5nO?@qm92m#$Ct8!~sEMxV8 zVj^kC&QWK*Ol{|v?w~(^z8tZAM)+E`@dW}#8_%jL+Lk*)Fr%lMoXnhd24ez(gKLgU zD)6r5)79)!9dfsapC7%q;!`VwE>yROo@jQRewbi5Dj!EVPiM7 z@)5fvIX=l02d@VAWNO;7gnU1|B-g{DYM4VQkrNVn4|SO)V6^!QXXGulR9S#ZHq)MB z`N;r6MZb}f2Fk}K7%JqHap7}Vt8X0N@;s+ylt{X#YKusUNYtYv6azxG2Vk1?ro^i; zY*gebyIf$lD^VEFnc-b-4yLYRBGM}! zZ~R|q&=9tdKD>OuzVmH>FdpPb`!oh1gvS^_p-)&7Y zjpfeMdljTG636^Plz55vQl?ESIjfl6>uJOK(7lAUuv;MeMtU0%2f0$}JBY8Cr zE8+WpN;}V}rnYSXg9QssMCnCA>Ai;*QF@CM6{OeDTPV^wD1x*ID7`2xA`p-gI*63e zK>~zcr9(m}p_3Qyy=T1p-Z?*B`MJj)8EfsCm9@V0&8)dm2|qFhx*~ynW>xXA_c$u9)=ytbvEJhu<7OyR{zp4U@QQ&R)f*-H8Wty2p z+~X6A{!)m(y*K}rW0RAE1JEPi4G##SeK9Nldh!JY%p{J23x4r%aQEtKjAfvMz#Pl; zAUuv7a5l|>t|%rO_z|-EOc9WR3D_=XfpX*qU*^PU?Gg^?A`?m>DwA?~q#|QANQ)#T`#YW5YV{C~0nQ18>(WMt|3*VvF zj;sdl3ukA(cAXFhXZ&qo1h<>FX+kf3bJfs6;K}h|Dr8OGVAiWy4=5#(Njli~N9%y} zLEp%E-}!|AA!OCu>BQt-6-^TTO#4*RoF5tUosRwF6tTdcqyf545uAGJ|Q~K+$sVk^mWS zYoe|Cp#B!!%b2mOT`n)bb72mB<5Kgc`gTw{|HnuK{ekwxH0gy%DBXo*gV)HgXtfUv$xLKXA9j*SAMMS$985y ziQdi25wM@^#qOL7-!M8mZ%qhS5MSNrRwX$o0bJX8YvIF!S0-`Mn6rkYPMdOn`CdPs z*xX^2u8l>rqDxf@*9h|~L@sN-!(95fgv8eLNE9TRg2+_O>nm*B zfpFY6Kn!{B2g2>}`+56JidoL+NzqtMLtQ@WhREU zR5JhJTPu;!HgHv`Rg*&g0o!bmb;0s?G zA1vD|#t}viDscxHfa7E3c<}f)GHK#TN3GNQ>`0Hibv1MLl`4w^J`Dcv)%){(+ z-gl0Ekqya!t?vABotM=PZ$>?4+pD~K^r1HUWn)ow=Wy#2AQ!Gbp_0V5FmoYekZ@Th zX=^0jhfy3S8UJvSMEzok2e;`fn-X{{)NO3OFt({s%7ERh2axePb}uqb(u;GU2Gm_t zW@WXz#IIhJF@BqRZ{*7>czjmoUH5-c+!mkivC6l=WYu%%r?S&#iMWZGAFCU-giQO z3ZZEV{uWi!9 z5Oj17Kzo4}2e%gv=N3Bq4wThYh8t&GGq)w)R)c)Ij9bga%Fby{s$5l2&Zm&wlWRtD zZFSQ?p2WJ>4I=rjkX(*D2LJhz!)5x8gn{%`BqSKclgq)$c(JHqFJ!Sef#Bc>|0{~H z5NTnjHmvriXMvZekx=rVG;*fyAIZV7o1&jN{Tx`Lc;m(ml6Lo#*a&j-k|T>^9uDFU znzuVTD(WaI(d8OhhztAbPrRM_7p`gsWpN@z|M1FSIZ0fK$)E-(uYRu#j$(vKB%o$Oq*|d zb4~lt{cq@TyuGy3OMRKzRsQC)u}US(KPf;{k_(j_ZAHm9D%PZzDSNjn&SL%<1#5tx zs6t$FTtjIOI}EN>{Rn}NB1C20z_O5CFXDa zidu*gv1n1s)i1km*}g^v_t|3PPE}YDda0&*i)JEx3fZ^pQg}Ix`Bb~JiW?cy}~0RO0WMcVD*z1%OUp_AKZn4p@k-g81HS_@$C>&U%@oh z8iZg}bS%f$_3C!{+Mc}B%EKB6j&>h2n&BqxeXky^(4M2sTcMj)bjnCG6*<o6`7 zj`>E7>pzZtT%#e^kj)Qw_!Zs#SFY$mlSOp=a?PlZsVSE_w9T-|Y5Wn!JULXWWFx!Z z966}_0J4^Mb$YmfGLBgy-|X;yP=I`$@)9!XqL)2TZ|Ob|v|(&$F`kGQ#SCC199c9n z;)DHdkn4{RpBcJLobr8fhfJNffQF7Ilix&IK=gnO#fQS|E!sI$g0&kxs`R66NxnQz zu^(;YSH`LjTXth#3qzaDEZGCaA{$wAj_-nJ$Az}+wzg+Xm#kW^#h3=K!J)yTWznZ> ztNko|&L5?^$;LL6DsS;0#`{P6Wtl}e2+T}BC7 z3|(~TlMNj44emy)kSs1OO;otXO`T6B`a-5gI$|yAA}#~j<|7p{(gOVWq1FSlbK>A! zV**Z9D)?JcUGTup(=85ZpIw`y%HHuxED11}9wgl2O3?y|KyH^?T2kbsD@@d5Ndo;! zIlTACr)6zY)I{&XbYh~3!S}17ER6f?ES6g1%N$9CwQ||CiCvTXaBYmavDQs4GUOuu z2CFWy0eR?2Zn^JXKEVr#ag#Ug3!b_&N>5HU(~2K5Y6jHim@(6P9o79f?LHmf6?Kh0 zMbNMZ?^)mpt4}sUo4Q5^-Fl^5rw>URD;AjJ&l)3t_J<5e7f#na(X%Oe0FkIUTbi%m z7`udoH2@4VasHy%)&9mm{BX}^?gs_#kTfV7w_}BypBqBWOFpbV^Ua)XM1Fjgd16$c zQ$gqKIu_g;>X|eFN?@W_n3BnYs)6GBTOd-d_ZQ3Del;pvH@SRy$x z*;2m|x3n%*XCv$+f2Z9{A!Z}yUwl|;Kc}S=N7IeJMVGr7cwK%E`~W^eV0Z)I*Y=S>RLx#z zaz&2+=>TpT_4>wvboq1l?|I~b{?9-bef;ioAkDm%prT>(q^sADO(YDmq4qc5d!5{i z;i9rKY`G>=K@cR8)uM<_;o)ZdCLJ3}HSQ7i!orFnM1r!%u`q1tx=S}dB-!MWgQ+06 zuHpRTn##BJIPNrDPo;OTH;)f|y|2qrSS0_6*`T%5r7z(A&@!RUI%tU zvz^H~R!2YKssjqQTT^Pa#<`O7Ji zGrgT1$k?i#M0dR_o-8Q+qekH?*mDu@VD5h$qCb4GTdkR83n7Oyx1OT{M5F_FVXjm{ zHyqztG4##tFuFS5@eu#8U|b=oBR6$heC>mzQX(iQMlxRo6TVyG?o(s&$!gF_U>iW8 zX3t@g4E)jLM{U;y+EkcCs9zoF&JOut-Ubu*RgsTzkNV;CXct>{%X0=2;g*yU>H(o> zvqVQw1dMn!17Mja!WZ}Zo1ns4dafH%=HQ{((QgdXcoov^6=MP;eUtw9tFE&AgFZ}e zFt60h2$`kc+8vvOsXKHT9W7+3Y2(`EOcOZP-pW$P$>WpoxXsE*j)Q$a|CM;yfsn4; z9m#)0C8>ruNk;DS4-gO8Hj}l99Bn+-l`F{Vt}E(FQp6_<&n|t+KVLTai1+q9`QK_f zS`va&oana3R(HMVCy}>*r99KM6Aa#2YXZ43c=$fk(HcixfGLm^p#VY=KCn-+{|25U z#C{I{^u@#d^U5?@BdLb73xQ42eO`cbJrgsO+iiz zD_snqX-|Ij0jB2WeNZX=pRtN*qlfUcEXGngdx&=`k6Qou^>M&g^Wr1Glf5B1a2Pqe z+YxB$c=*DxxJs=e`8$92G=Ym+C@|duM0jW6;hJ8vIgm&RK;wVQxczS0I>7+a)#2?o zBaYwaPJx<-r1Sr&+|uaCrQuTpxnCyfv0Z<%V@FZD_T+vr(U{4aHku2mY}2dBI%kJ| zC^{s(ZM#$rcj@R`){>tZiwocMrgR52M80cs%e6nRH`?-rGmBi8YSdqo68g4*7?K{y|+;9?in=B z>AfKuDNC9r(FCCLZNvn-Bs-P7JdtT*-|W@7?^9%tgKYvMzpw5=5Yi=mu0HQ);UR1Z z;(m=^{Ju@L_BRT4vk1oP=R7&S%+R?;pGB^)zGTg_ zeOOCRcz$yJEIoE0OD=;`E&hSLe5RR2aDQs#qKxP68|2mBjCr(4y`+l7VFIxMrihO6 z51VMd=Lq-gB8rj1MQ0|P4nKS((m{OfmRhK($?WG3a_(Lx2%=ZhP**3p7lHx{nC@6l zWDA)$1xV7hE#ja=8jcq{4)i?>q6&+JM7|0bA$TtLFZBSvel5@j(Qo!%s3`MMp)R<^ zvCWYd7uuW(ZBQu%>_XE-R*zf>UjcEZ6(m>kA@e*t`b5-HntB=0Wsb4_Lieh~*zO4{QBhEyf1&sP^FqBy{@y(=4yLVQ^`a&vj+ULS0vAIP7 z#ND{j(eMvqC=DH0?&NSUJ=!)2S{5B7TB-2n@Nawub2lAWj?yPY(Q@&{}*BC$Fq!qK~p^Z zTHwm2qhZBN(gmxZPW>UhWy`G3>rf0dLuWkX-Q4tg#BJ5Pv_iEqtyVtmM9FRX)T3Fw zN#C!%Uy(q5tVhpi*(Nt?yLm!+Ry3`2j&&YMa9dhWFq^2DN9|ITnmWc_cL-5m*0)OB zTF*+7adP}oaZK&$w7SHi+3PLXtJrkXT5@d-Xn9YezG^96Z3WWm7EmQ$!|6V!`|AL; z*O+|Ndx=S6!)T4r_qTGVFc`E!% z7f)`wxmMrnV$`dlXIG)2xB%fO=deK@AUx%E4PqGVu&&m1Wp^HODPg}&CO zQ;4Xa8tPm(tUJr5fBeBtz0;Q6uiez}(Ru2j-@)?C-u8HTAp7Z|TcOPlO){NHa|f5@ zQfnv;FL^rqU8wZ-uXUCZO+Mln1QHk_R9UN-cLSss<3k>JdGXcUe>ZU+4x7K&j(r*f!%A}t~cWbfjr^(7Zy}ul2xRf77PP*!GL$eA{6GVXmVmH zPm?*HYZ}N4N*QSQYDj3ZaV55(u;r?=11FboebG?xgg!OtEyk^j-dY#l)3k;|0db4k z99hzkDY`U5~Dg<@&%1;jTH;p6Rev=x@c?5+*w> z4dzipn@wZxDygt@>Ptxgd(6FiS4>e`Oz6P_>6I!a&&lqj-(PXmgVVM%<0JG|PZU3~ zWYVu@Tz8IjD)$+CG z4UZ4)DC?QR*bT(U&A3hMqbs-8hQcx{+FmB5ZD~_oDCxNbENS3N1CrtWZR;ao5q@7; z(6gyOtzwo?R>SXO)hF%nPpXzQu!>&2KOb~<5~TPr#Gr9=wXKHTLvRm~)tL7BnMxgT z?qrLX;1UMD5!{w3HCf60iW8?u);UhpBVaCvIZjR_rz*ipZX^XQnv~oZG~H}4$u@Dw zi(IEW;t62+DwEWy~BN|ZAJL_}*HCuJ2hWzqKD2}>&0{*uUN|cA~A`~m`N3jUW z5@IHE+Hgmd!%l54Z)>!eK6zD4Lrl`NC2&f2wy*VT?liFm^SF3iQ_=J1!F6e%C7{o_ zOVGK!Zir&S5~D8(Mca>G$QSP&q`y66TPf1RnX<}FJd1Bw_GdiX{Fz+BDjD$tbb>RT z<0p?Bv;uK;xD9_*;VdCbjlc6;*LcJ8yrfl!acb)}m*DhDP-~y%@f)8AcVbd??YK2a z`cx|0A3_VGMX7^iku^Ae|9id@9d;H58AVW`<;;Gi&f~T|rn-ckDHw_6U-@xW!}V|T z#;B$Gj~}BIRr4tvLkxLl5lMcKawncc&Iun{V6J%zz#E4B^oxY#s>knl1T^zumokJl z6`*u~^uKaBFB4e5#PEEj8u&N|Q7ZE>RU@OBy4+VaGLv#za1e&e8nn!reBCS8qW$_& z%VTsUnMK+<~)#4izC;Hm=wX@2?n*;{rZ! zT1>dp;V$A*zgd#8vJ)6HEPOcN+dqaPVWfn96Z~I^O{{n}-g``*z+-?VP)1&LGMk7_ z>rJUeu;Rv4hq*z&5NlU6wQ6YfVWgp00?*8~SEkisdOwj-9|ZfM(H+IUyIxe!uc{L3 z_w^@ms@-N|8-SNJ+xI>3G*?KKbMs~?eo=;B`>91-v~AK0(NITC9iu0&ig7H!kbI+F z@?YvOlceh>LA$I_b2C)&tBdGGRpdAO{&Wtcs!>z9SKyTwcI=$QH0jroJ=+5w#3Ig? z#c&KSIL0DiH`^!vH!OC{-W{;GLFXA(dFd*k5q&BRYa>X<=P4;Lz^<4q+#SQ#-33$B z3L4nt|L~NiYXm%cpX)D%9ht>Ei+&LJ3j4T5jdzwPzS`M50ECy#h%;f$7?W&mTX$rb z924i=q}h?)_{n;2!{`UhhTvOBC^a8`_l)Yy=xC-%AK(}pW#}?H(E9Z;L4*D;5FysW z#Y{_UFxK!vEVudYkj#!`wfnOEiiU50`fwAuAz%F0T>yxeG4Ar5{^@feBGdS2)kZ~~ zeOycb-xHpCQ4nK9^NN&jflHP^}z3H%s|pT+N}12g~x_V~}=G|ov<2$uSYx>0nNmKxysj@S!*+wlHou0SEt zEEL#4#)s=_mu#ZKA()BlR_Yx?DytY`CtNVMe|MripJL!5jqH(YMWTyS02c`(Vlhac zm_^Rt*nQAyPsp;WZ1Cb+bG}P_`kTu-;et_#zd4w+QKNhUZCi=u8z}rOxD%l@HxT7m zAt_luj7#79XOp+rD6-BdVZiFI5zPFR~1p!1- zN`f3y8B^bCe3IOJ;Q4ZFrbCG|B$X^b2edSgNg8Mo6`=rsE>yw`Wro^riyda`4-W^u zFd_1`7~P%Ja|t7H{uU<7T74na=U$TiC9ele0YC4dr4^r%@Atk$RZB!Vh9_)BOg~&r zOfNz85u@oN1F=Dvs%64cZuUU^dv`)tXZ&gv@V=LrIsqwZ1J&9uIQn}U>!`t5{MNrF zt?J{6N&WnrMRfBiA5AK$jqhWv1mN@(s4jr6+ xEI;A2Iz<$USoOV;eTPWxG-bBjMqz|&_fF{$0kw~Yh_7iO(NNJTUI Command: geompy.RemoveExtraEdges(theShape), -there theShape is a compound or a single solid to remove irregular edges from. -\n Arguments: Name + one shape. +\n TUI Command: geompy.RemoveExtraEdges(theShape,theOptimumNbFaces), +there theShape is a compound or a single solid to remove irregular edges from +and theOptimumNbFaces is an integer parameter, that regulates, +whether the faces, sharing common surface, should be united, or not. +\n Arguments: Name + one shape + a flag. \n Advanced option: \ref restore_presentation_parameters_page "Set presentation parameters and subshapes from arguments". @@ -23,4 +25,7 @@ there theShape is a compound or a single solid to remove irregular edge \image html remove_extra_edges2.png
Improved shape
+Our TUI Scripts provide you with useful examples of the +\ref swig_RemoveExtraEdges "Remove Extra Edges" functionality usage. + */ diff --git a/idl/GEOM_Gen.idl b/idl/GEOM_Gen.idl index 4cc2a6c16..08f580d39 100644 --- a/idl/GEOM_Gen.idl +++ b/idl/GEOM_Gen.idl @@ -21,7 +21,7 @@ // // File : GEOM_Gen.idl // Author : Sergey RUIN -// + #ifndef __GEOM_GEN__ #define __GEOM_GEN__ @@ -1781,9 +1781,14 @@ module GEOM * Remove all seam and degenerated edges from \a theShape. * Unite faces and edges, sharing one surface. * \param theShape The compound or single solid to remove irregular edges from. + * \param theOptimumNbFaces If more than zero, unite faces only for those solids, + * that have more than theOptimumNbFaces faces. If zero, unite faces always, + * regardsless their quantity in the solid. If negative, do not unite faces at all. + * For blocks repairing recommended value is 6. * \return Improved shape. */ - GEOM_Object RemoveExtraEdges (in GEOM_Object theShape); + GEOM_Object RemoveExtraEdges (in GEOM_Object theShape, + in long theOptimumNbFaces); /*! * Check, if the given shape is a blocks compound. diff --git a/src/GEOMAlgo/BlockFix_BlockFixAPI.cxx b/src/GEOMAlgo/BlockFix_BlockFixAPI.cxx index 62e33fd4e..674a9867e 100644 --- a/src/GEOMAlgo/BlockFix_BlockFixAPI.cxx +++ b/src/GEOMAlgo/BlockFix_BlockFixAPI.cxx @@ -19,10 +19,10 @@ // // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // -// File: BlockFix_BlockFixAPI.cxx -// Created: Tue Dec 7 11:59:05 2004 -// Author: Pavel DURANDIN -// +// File: BlockFix_BlockFixAPI.cxx +// Created: Tue Dec 7 11:59:05 2004 +// Author: Pavel DURANDIN + #include #include #include @@ -31,37 +31,35 @@ //======================================================================= //function : ShapeConvert_CanonicAPI -//purpose : +//purpose : //======================================================================= BlockFix_BlockFixAPI::BlockFix_BlockFixAPI() { myTolerance = Precision::Confusion(); + myOptimumNbFaces = 6; } //======================================================================= //function : Perform -//purpose : +//purpose : //======================================================================= -void BlockFix_BlockFixAPI::Perform() +void BlockFix_BlockFixAPI::Perform() { - // processing spheres with degenerativities TopoDS_Shape aShape = Shape(); myShape = BlockFix::RotateSphereSpace(aShape,myTolerance); - + // faces unification BlockFix_UnionFaces aFaceUnifier; aFaceUnifier.GetTolerance() = myTolerance; - TopoDS_Shape aResult; - aResult = aFaceUnifier.Perform(myShape); - - + aFaceUnifier.GetOptimumNbFaces() = myOptimumNbFaces; + TopoDS_Shape aResult = aFaceUnifier.Perform(myShape); + BlockFix_UnionEdges anEdgeUnifier; myShape = anEdgeUnifier.Perform(aResult,myTolerance); - + TopoDS_Shape aRes = BlockFix::FixRanges(myShape,myTolerance); myShape = aRes; - } diff --git a/src/GEOMAlgo/BlockFix_BlockFixAPI.hxx b/src/GEOMAlgo/BlockFix_BlockFixAPI.hxx index 9bece72c4..d2511898a 100644 --- a/src/GEOMAlgo/BlockFix_BlockFixAPI.hxx +++ b/src/GEOMAlgo/BlockFix_BlockFixAPI.hxx @@ -18,7 +18,7 @@ // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -// + #ifndef _BlockFix_BlockFixAPI_HeaderFile #define _BlockFix_BlockFixAPI_HeaderFile @@ -41,77 +41,53 @@ #ifndef _MMgt_TShared_HeaderFile #include #endif + class ShapeBuild_ReShape; class TopoDS_Shape; -class BlockFix_BlockFixAPI : public MMgt_TShared { - +class BlockFix_BlockFixAPI : public MMgt_TShared +{ public: - - void* operator new(size_t,void* anAddress) - { - return anAddress; - } - void* operator new(size_t size) - { - return Standard::Allocate(size); - } - void operator delete(void *anAddress) - { - if (anAddress) Standard::Free((Standard_Address&)anAddress); - } - // Methods PUBLIC - // -Standard_EXPORT BlockFix_BlockFixAPI(); - void SetShape(const TopoDS_Shape& Shape) ; -Standard_EXPORT void Perform() ; + void* operator new(size_t,void* anAddress) + { + return anAddress; + } + void* operator new(size_t size) + { + return Standard::Allocate(size); + } + void operator delete(void *anAddress) + { + if (anAddress) Standard::Free((Standard_Address&)anAddress); + } + + // Methods PUBLIC + // + Standard_EXPORT BlockFix_BlockFixAPI(); + void SetShape(const TopoDS_Shape& Shape); + Standard_EXPORT void Perform(); TopoDS_Shape Shape() const; - Handle_ShapeBuild_ReShape& Context() ; - Standard_Real& Tolerance() ; -Standard_EXPORT ~BlockFix_BlockFixAPI(); - - - - - // Type management - // - Standard_EXPORT friend Handle_Standard_Type& BlockFix_BlockFixAPI_Type_(); - Standard_EXPORT const Handle(Standard_Type)& DynamicType() const; - Standard_EXPORT Standard_Boolean IsKind(const Handle(Standard_Type)&) const; - -protected: - - // Methods PROTECTED - // - - - // Fields PROTECTED - // + Handle_ShapeBuild_ReShape& Context(); + Standard_Real& Tolerance(); + Standard_Integer& OptimumNbFaces(); + Standard_EXPORT ~BlockFix_BlockFixAPI(); + // Type management + // + Standard_EXPORT friend Handle_Standard_Type& BlockFix_BlockFixAPI_Type_(); + Standard_EXPORT const Handle(Standard_Type)& DynamicType() const; + Standard_EXPORT Standard_Boolean IsKind(const Handle(Standard_Type)&) const; private: - - // Methods PRIVATE - // - - - // Fields PRIVATE - // -Handle_ShapeBuild_ReShape myContext; -TopoDS_Shape myShape; -Standard_Real myTolerance; - - + // Fields PRIVATE + // + Handle_ShapeBuild_ReShape myContext; + TopoDS_Shape myShape; + Standard_Real myTolerance; + Standard_Integer myOptimumNbFaces; }; - #include - - -// other Inline functions and methods (like "C++: function call" methods) -// - - #endif diff --git a/src/GEOMAlgo/BlockFix_BlockFixAPI.lxx b/src/GEOMAlgo/BlockFix_BlockFixAPI.lxx index 883e4fec6..e66051950 100644 --- a/src/GEOMAlgo/BlockFix_BlockFixAPI.lxx +++ b/src/GEOMAlgo/BlockFix_BlockFixAPI.lxx @@ -18,11 +18,11 @@ // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -// + #include //======================================================================= -//function : Shape +//function : SetShape //purpose : //======================================================================= @@ -40,7 +40,7 @@ inline TopoDS_Shape BlockFix_BlockFixAPI::Shape() const { return myShape; } - + //======================================================================= //function : Context //purpose : @@ -50,7 +50,7 @@ inline Handle(ShapeBuild_ReShape)& BlockFix_BlockFixAPI::Context() { return myContext; } - + //======================================================================= //function : Tolerance //purpose : @@ -60,4 +60,13 @@ inline Standard_Real& BlockFix_BlockFixAPI::Tolerance() { return myTolerance; } - + +//======================================================================= +//function : OptimumNbFaces +//purpose : +//======================================================================= + +inline Standard_Integer& BlockFix_BlockFixAPI::OptimumNbFaces() +{ + return myOptimumNbFaces; +} diff --git a/src/GEOMAlgo/BlockFix_CheckTool.cxx b/src/GEOMAlgo/BlockFix_CheckTool.cxx index a5d825255..51532d02c 100644 --- a/src/GEOMAlgo/BlockFix_CheckTool.cxx +++ b/src/GEOMAlgo/BlockFix_CheckTool.cxx @@ -19,15 +19,17 @@ // // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // -// File: BlockFix_CheckTool.cxx -// Created: 17.12.04 11:15:25 -// Author: Sergey KUUL -// +// File: BlockFix_CheckTool.cxx +// Created: 17.12.04 11:15:25 +// Author: Sergey KUUL + #include +//#include +//#include + #include -#include -#include + #include #include #include @@ -78,33 +80,43 @@ void BlockFix_CheckTool::Perform() myNbUF=0; myNbUE=0; myNbUFUE=0; - TopExp_Explorer exps; - for(exps.Init(myShape, TopAbs_SOLID); exps.More(); exps.Next()) { + + TopExp_Explorer exps (myShape, TopAbs_SOLID); + TopTools_MapOfShape mapS; + for (; exps.More(); exps.Next()) { TopoDS_Solid aSolid = TopoDS::Solid(exps.Current()); + if (!mapS.Add(aSolid)) continue; myNbSolids++; Standard_Boolean IsBlock=Standard_True; Standard_Boolean MayBeUF=Standard_False; Standard_Boolean MayBeUE=Standard_False; Standard_Integer nf=0; - TopExp_Explorer expf; - for(expf.Init(aSolid, TopAbs_FACE); expf.More(); expf.Next()) nf++; + TopExp_Explorer expf (aSolid, TopAbs_FACE); + TopTools_MapOfShape mapF; + for (; expf.More(); expf.Next()) { + if (mapF.Add(expf.Current())) + nf++; + } - if(nf<6) { - IsBlock=Standard_False; + if (nf < 6) { + IsBlock = Standard_False; } - else if(nf>6) { - IsBlock=Standard_False; + else if (nf > 6) { + IsBlock = Standard_False; // check faces unification TopTools_SequenceOfShape faces; - for( expf.Init(aSolid, TopAbs_FACE); expf.More(); expf.Next()) { - TopoDS_Face aFace = TopoDS::Face(expf.Current()); - faces.Append(aFace); + mapF.Clear(); + for (expf.Init(aSolid, TopAbs_FACE); expf.More(); expf.Next()) { + if (mapF.Add(expf.Current())) { + TopoDS_Face aFace = TopoDS::Face(expf.Current()); + faces.Append(aFace); + } } Standard_Boolean HasFacesForUnification = Standard_False; - for(Standard_Integer i=1; i0 ) { - IsBlock=Standard_False; + if (nbe == 12 && DegenEdges.Extent() > 0) { + IsBlock = Standard_False; myNbDegen++; myPossibleBlocks.Append(aSolid); continue; } - if(nbe<24) - IsBlock=Standard_False; - if(nbe>24) { - IsBlock=Standard_False; + if (nbe < 12) + IsBlock = Standard_False; + if (nbe > 12) { + IsBlock = Standard_False; // check edges unification // creating map of edge faces TopTools_IndexedDataMapOfShapeListOfShape aMapEdgeFaces; TopExp::MapShapesAndAncestors(aSolid, TopAbs_EDGE, TopAbs_FACE, aMapEdgeFaces); - for(expf.Init(aSolid, TopAbs_FACE); expf.More(); expf.Next()) { + + mapF.Clear(); + for (expf.Init(aSolid, TopAbs_FACE); expf.More(); expf.Next()) { TopoDS_Face aFace = TopoDS::Face(expf.Current()); + if (!mapF.Add(aFace)) continue; TopTools_IndexedDataMapOfShapeListOfShape aMapFacesEdges; - for(expe.Init(aFace,TopAbs_EDGE); expe.More(); expe.Next()) { + + TopTools_MapOfShape mapEe; + for (expe.Init(aFace, TopAbs_EDGE); expe.More(); expe.Next()) { TopoDS_Edge edge = TopoDS::Edge(expe.Current()); - if(!aMapEdgeFaces.Contains(edge)) continue; + if (!mapEe.Add(edge)) continue; + if (!aMapEdgeFaces.Contains(edge)) continue; const TopTools_ListOfShape& aList = aMapEdgeFaces.FindFromKey(edge); - TopTools_ListIteratorOfListOfShape anIter(aList); - for( ; anIter.More(); anIter.Next()) { + TopTools_ListIteratorOfListOfShape anIter (aList); + for (; anIter.More(); anIter.Next()) { TopoDS_Face face = TopoDS::Face(anIter.Value()); - if(face.IsSame(aFace)) continue; - if(aMapFacesEdges.Contains(face)) { + if (face.IsSame(aFace)) continue; + if (aMapFacesEdges.Contains(face)) { aMapFacesEdges.ChangeFromKey(face).Append(edge); } else { @@ -178,34 +196,33 @@ void BlockFix_CheckTool::Perform() } } } - Standard_Integer i=1; - for(; i<=aMapFacesEdges.Extent(); i++) { + Standard_Integer i = 1; + for (; i <= aMapFacesEdges.Extent(); i++) { const TopTools_ListOfShape& ListEdges = aMapFacesEdges.FindFromIndex(i); - if(ListEdges.Extent()>1) break; + if (ListEdges.Extent() > 1) break; } - if(i<=aMapFacesEdges.Extent()) { - MayBeUE=Standard_True; + if (i <= aMapFacesEdges.Extent()) { + MayBeUE = Standard_True; break; } } } - if(IsBlock) + if (IsBlock) myNbBlocks++; else { - if(MayBeUF) { + if (MayBeUF) { myPossibleBlocks.Append(aSolid); - if(MayBeUE) + if (MayBeUE) myNbUFUE++; else myNbUF++; } - else if(MayBeUE) { + else if (MayBeUE) { myNbUE++; myPossibleBlocks.Append(aSolid); } } - } myHasCheck = Standard_True; diff --git a/src/GEOMAlgo/BlockFix_UnionFaces.cxx b/src/GEOMAlgo/BlockFix_UnionFaces.cxx index e513cbe59..d63b5aaac 100644 --- a/src/GEOMAlgo/BlockFix_UnionFaces.cxx +++ b/src/GEOMAlgo/BlockFix_UnionFaces.cxx @@ -19,10 +19,9 @@ // // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // -// File: BlockFix_UnionFaces.cxx -// Created: Tue Dec 7 17:15:42 2004 -// Author: Pavel DURANDIN -// +// File: BlockFix_UnionFaces.cxx +// Created: Tue Dec 7 17:15:42 2004 +// Author: Pavel DURANDIN #include @@ -59,7 +58,7 @@ #include #include #include -#include +#include #include #include #include @@ -79,21 +78,22 @@ #include #include - + //======================================================================= //function : BlockFix_UnionFaces -//purpose : +//purpose : //======================================================================= BlockFix_UnionFaces::BlockFix_UnionFaces() - : myTolerance(Precision::Confusion()) + : myTolerance(Precision::Confusion()), + myOptimumNbFaces(6) { } //======================================================================= -//function : GetTolearnce -//purpose : +//function : GetTolerance +//purpose : //======================================================================= Standard_Real& BlockFix_UnionFaces::GetTolerance() @@ -102,6 +102,17 @@ Standard_Real& BlockFix_UnionFaces::GetTolerance() } +//======================================================================= +//function : GetOptimumNbFaces +//purpose : +//======================================================================= + +Standard_Integer& BlockFix_UnionFaces::GetOptimumNbFaces() +{ + return myOptimumNbFaces; +} + + //======================================================================= //function : AddOrdinaryEdges //purpose : auxilary @@ -129,22 +140,22 @@ static Standard_Boolean AddOrdinaryEdges(TopTools_SequenceOfShape& edges, for(Standard_Integer i = 1; i <= edges.Length(); i++) { TopoDS_Shape current = edges(i); if(aNewEdges.Contains(current)) { - + aNewEdges.Remove(current); edges.Remove(i); i--; - + if(!isDropped) { isDropped = Standard_True; anIndex = i; } } } - + //add edges to the sequemce for(TopTools_MapIteratorOfMapOfShape anIter(aNewEdges); anIter.More(); anIter.Next()) edges.Append(anIter.Key()); - + return isDropped; } @@ -156,7 +167,7 @@ static Standard_Boolean AddOrdinaryEdges(TopTools_SequenceOfShape& edges, static Handle(Geom_Surface) ClearRts(const Handle(Geom_Surface)& aSurface) { if(aSurface->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface))) { - Handle(Geom_RectangularTrimmedSurface) rts = + Handle(Geom_RectangularTrimmedSurface) rts = Handle(Geom_RectangularTrimmedSurface)::DownCast(aSurface); return rts->BasisSurface(); } @@ -166,7 +177,7 @@ static Handle(Geom_Surface) ClearRts(const Handle(Geom_Surface)& aSurface) //======================================================================= //function : Perform -//purpose : +//purpose : //======================================================================= TopoDS_Shape BlockFix_UnionFaces::Perform(const TopoDS_Shape& Shape) @@ -176,7 +187,7 @@ TopoDS_Shape BlockFix_UnionFaces::Perform(const TopoDS_Shape& Shape) // processing each solid TopExp_Explorer exps; - for(exps.Init(Shape, TopAbs_SOLID); exps.More(); exps.Next()) { + for (exps.Init(Shape, TopAbs_SOLID); exps.More(); exps.Next()) { TopoDS_Solid aSolid = TopoDS::Solid(exps.Current()); // creating map of edge faces @@ -185,28 +196,40 @@ TopoDS_Shape BlockFix_UnionFaces::Perform(const TopoDS_Shape& Shape) // map of processed shapes TopTools_MapOfShape aProcessed; - + Handle(ShapeBuild_ReShape) aContext = new ShapeBuild_ReShape; - Standard_Integer NbModif=0; + Standard_Integer NbModif = 0; Standard_Boolean hasFailed = Standard_False; - Standard_Real tol = Min(Max(Precision::Confusion(), myTolerance/10.),0.1); - // processing each face + Standard_Real tol = Min(Max(Precision::Confusion(), myTolerance/10.), 0.1); + + // count faces + int nbf = 0; TopExp_Explorer exp; - //for( exp.Init(Shape, TopAbs_FACE); exp.More(); exp.Next()) { - for( exp.Init(aSolid, TopAbs_FACE); exp.More(); exp.Next()) { + TopTools_MapOfShape mapF; + for (exp.Init(aSolid, TopAbs_FACE); exp.More(); exp.Next()) { + if (mapF.Add(exp.Current())) + nbf++; + } + + bool doUnion = ((myOptimumNbFaces == 0) || + ((myOptimumNbFaces > 0) && (nbf > myOptimumNbFaces))); + + // processing each face + mapF.Clear(); + for (exp.Init(aSolid, TopAbs_FACE); exp.More() && doUnion; exp.Next()) { TopoDS_Face aFace = TopoDS::Face(exp.Current().Oriented(TopAbs_FORWARD)); - - if(aProcessed.Contains(aFace)) + + if (aProcessed.Contains(aFace)) continue; - + Standard_Integer dummy; TopTools_SequenceOfShape edges; AddOrdinaryEdges(edges,aFace,dummy); - + TopTools_SequenceOfShape faces; faces.Append(aFace); - + //surface and location to construct result TopLoc_Location aBaseLocation; Handle(Geom_Surface) aBaseSurface = BRep_Tool::Surface(aFace,aBaseLocation); @@ -214,73 +237,73 @@ TopoDS_Shape BlockFix_UnionFaces::Perform(const TopoDS_Shape& Shape) // find adjacent faces to union Standard_Integer i; - for( i = 1; i <= edges.Length(); i++) { + for (i = 1; i <= edges.Length(); i++) { TopoDS_Edge edge = TopoDS::Edge(edges(i)); - if(BRep_Tool::Degenerated(edge)) + if (BRep_Tool::Degenerated(edge)) continue; - + const TopTools_ListOfShape& aList = aMapEdgeFaces.FindFromKey(edge); TopTools_ListIteratorOfListOfShape anIter(aList); - for( ; anIter.More(); anIter.Next()) { + for (; anIter.More(); anIter.Next()) { TopoDS_Face anCheckedFace = TopoDS::Face(anIter.Value().Oriented(TopAbs_FORWARD)); - if(anCheckedFace.IsSame(aFace)) + if (anCheckedFace.IsSame(aFace)) continue; - - if(aProcessed.Contains(anCheckedFace)) + + if (aProcessed.Contains(anCheckedFace)) continue; - - if(IsSameDomain(aFace,anCheckedFace)) { - - if(aList.Extent() != 2) { + + if (IsSameDomain(aFace,anCheckedFace)) { + + if (aList.Extent() != 2) { // non mainfold case is not processed continue; } - + // replacing pcurves TopoDS_Face aMockUpFace; BRep_Builder B; B.MakeFace(aMockUpFace,aBaseSurface,aBaseLocation,0.); MovePCurves(aMockUpFace,anCheckedFace); - - if(AddOrdinaryEdges(edges,aMockUpFace,dummy)) { + + if (AddOrdinaryEdges(edges,aMockUpFace,dummy)) { // sequence edges is modified i = dummy; } - + faces.Append(anCheckedFace); aProcessed.Add(anCheckedFace); break; } } } - + // all faces collected in the sequence. Perform union of faces - if(faces.Length() > 1) { + if (faces.Length() > 1) { NbModif++; TopoDS_Face aResult; BRep_Builder B; B.MakeFace(aResult,aBaseSurface,aBaseLocation,0); Standard_Integer nbWires = 0; - + // connecting wires - while(edges.Length()>0) { - + while (edges.Length()>0) { + Standard_Boolean isEdge3d = Standard_False; nbWires++; TopTools_MapOfShape aVertices; TopoDS_Wire aWire; B.MakeWire(aWire); - + TopoDS_Edge anEdge = TopoDS::Edge(edges(1)); edges.Remove(1); - + isEdge3d |= !BRep_Tool::Degenerated(anEdge); B.Add(aWire,anEdge); TopoDS_Vertex V1,V2; TopExp::Vertices(anEdge,V1,V2); aVertices.Add(V1); aVertices.Add(V2); - + Standard_Boolean isNewFound = Standard_False; do { isNewFound = Standard_False; @@ -298,10 +321,10 @@ TopoDS_Shape BlockFix_UnionFaces::Perform(const TopoDS_Shape& Shape) } } } while (isNewFound); - + // sorting any type of edges aWire = TopoDS::Wire(aContext->Apply(aWire)); - + TopoDS_Face tmpF = TopoDS::Face(aContext->Apply(faces(1).Oriented(TopAbs_FORWARD))); Handle(ShapeFix_Wire) sfw = new ShapeFix_Wire(aWire,tmpF,Precision::Confusion()); sfw->FixReorder(); @@ -348,7 +371,7 @@ TopoDS_Shape BlockFix_UnionFaces::Perform(const TopoDS_Shape& Shape) sawo.Add(c2d->Value(f).XY(),c2d->Value(l).XY()); } sawo.Perform(); - + // constructind one degenerative edge gp_XY aStart, anEnd, tmp; Standard_Integer nbFirst = sawo.Ordered(1); @@ -358,7 +381,7 @@ TopoDS_Shape BlockFix_UnionFaces::Perform(const TopoDS_Shape& Shape) TopoDS_Edge E = sbe.CopyReplaceVertices(anOrigE,aDummyV,aDummyV); sawo.XY(nbFirst,aStart,tmp); sawo.XY(sawo.Ordered(aLastEdge),tmp,anEnd); - + gp_XY aVec = anEnd-aStart; Handle(Geom2d_Line) aLine = new Geom2d_Line(aStart,gp_Dir2d(anEnd-aStart)); @@ -372,13 +395,11 @@ TopoDS_Shape BlockFix_UnionFaces::Perform(const TopoDS_Shape& Shape) B.Add(aW,E); B.Add(aResult,aW); } - } - + // perform substitution of face aContext->Replace(aContext->Apply(aFace),aResult); - - + ShapeFix_Face sff (aResult); //Intializing by tolerances sff.SetPrecision(myTolerance); @@ -390,74 +411,72 @@ TopoDS_Shape BlockFix_UnionFaces::Perform(const TopoDS_Shape& Shape) sff.SetContext(aContext); // Applying the fixes sff.Perform(); - if(sff.Status(ShapeExtend_FAIL)) + if(sff.Status(ShapeExtend_FAIL)) hasFailed = Standard_True; - + // breaking down to several faces TopoDS_Shape theResult = aContext->Apply(aResult); - for(TopExp_Explorer aFaceExp(theResult,TopAbs_FACE);aFaceExp.More();aFaceExp.Next()) { + for (TopExp_Explorer aFaceExp (theResult,TopAbs_FACE); aFaceExp.More(); aFaceExp.Next()) { TopoDS_Face aCurrent = TopoDS::Face(aFaceExp.Current().Oriented(TopAbs_FORWARD)); Handle(TColGeom_HArray2OfSurface) grid = new TColGeom_HArray2OfSurface ( 1, 1, 1, 1 ); grid->SetValue ( 1, 1, aBaseSurface ); Handle(ShapeExtend_CompositeSurface) G = new ShapeExtend_CompositeSurface ( grid ); ShapeFix_ComposeShell CompShell; - CompShell.Init ( G, aBaseLocation, aCurrent, ::Precision::Confusion() );//myPrecision + CompShell.Init ( G, aBaseLocation, aCurrent, ::Precision::Confusion() );//myPrecision CompShell.SetContext( aContext ); - + TopTools_SequenceOfShape parts; ShapeFix_SequenceOfWireSegment wires; for(TopExp_Explorer W_Exp(aCurrent,TopAbs_WIRE);W_Exp.More();W_Exp.Next()) { - Handle(ShapeExtend_WireData) sbwd = + Handle(ShapeExtend_WireData) sbwd = new ShapeExtend_WireData ( TopoDS::Wire(W_Exp.Current() )); ShapeFix_WireSegment seg ( sbwd, TopAbs_REVERSED ); wires.Append(seg); } - + CompShell.DispatchWires ( parts,wires ); for (Standard_Integer j=1; j <= parts.Length(); j++ ) { ShapeFix_Face aFixOrient(TopoDS::Face(parts(j))); aFixOrient.SetContext(aContext); aFixOrient.FixOrientation(); } - + TopoDS_Shape CompRes; if ( faces.Length() !=1 ) { TopoDS_Shell S; B.MakeShell ( S ); - for ( i=1; i <= parts.Length(); i++ ) + for ( i=1; i <= parts.Length(); i++ ) B.Add ( S, parts(i) ); CompRes = S; } else CompRes = parts(1); - + aContext->Replace(aCurrent,CompRes); } - + // remove the remaining faces for(i = 2; i <= faces.Length(); i++) aContext->Remove(faces(i)); } - } - + } // end processing each face + //TopoDS_Shape aResult = Shape; - if(NbModif>0) { - TopoDS_Shape aResult = aSolid; - if(!hasFailed) { - aResult = aContext->Apply(aSolid); - - ShapeFix_Edge sfe; - for(exp.Init(aResult,TopAbs_EDGE); exp.More(); exp.Next()) { - TopoDS_Edge E = TopoDS::Edge(exp.Current()); - sfe.FixVertexTolerance (E); - // ptv add fix same parameter - sfe.FixSameParameter(E, myTolerance); - } - - myContext->Replace(aSolid,aResult); + if (NbModif > 0 && !hasFailed) { + TopoDS_Shape aResult = aContext->Apply(aSolid); + + ShapeFix_Edge sfe; + for (exp.Init(aResult,TopAbs_EDGE); exp.More(); exp.Next()) { + TopoDS_Edge E = TopoDS::Edge(exp.Current()); + sfe.FixVertexTolerance (E); + // ptv add fix same parameter + sfe.FixSameParameter(E, myTolerance); } + + myContext->Replace(aSolid, aResult); } -// else { - for( exp.Init(aSolid, TopAbs_FACE); exp.More(); exp.Next()) { + //else + { + for (exp.Init(aSolid, TopAbs_FACE); exp.More(); exp.Next()) { TopoDS_Face aFace = TopoDS::Face(exp.Current().Oriented(TopAbs_FORWARD)); Handle(ShapeFix_Wire) sfw = new ShapeFix_Wire; sfw->SetContext(myContext); @@ -465,15 +484,14 @@ TopoDS_Shape BlockFix_UnionFaces::Perform(const TopoDS_Shape& Shape) sfw->SetMinTolerance(myTolerance); sfw->SetMaxTolerance(Max(1.,myTolerance*1000.)); sfw->SetFace(aFace); - for ( TopoDS_Iterator iter(aFace,Standard_False); iter.More(); iter.Next()) { - TopoDS_Wire wire = TopoDS::Wire ( iter.Value() ); + for (TopoDS_Iterator iter (aFace,Standard_False); iter.More(); iter.Next()) { + TopoDS_Wire wire = TopoDS::Wire(iter.Value()); sfw->Load(wire); sfw->FixReorder(); sfw->FixShifted(); } } -// } - + } } // end processing each solid aResShape = myContext->Apply(Shape); @@ -483,7 +501,7 @@ TopoDS_Shape BlockFix_UnionFaces::Perform(const TopoDS_Shape& Shape) //======================================================================= //function : IsSameDomain -//purpose : +//purpose : //======================================================================= Standard_Boolean BlockFix_UnionFaces::IsSameDomain(const TopoDS_Face& aFace, @@ -492,10 +510,10 @@ Standard_Boolean BlockFix_UnionFaces::IsSameDomain(const TopoDS_Face& aFace, //checking the same handless TopLoc_Location L1, L2; Handle(Geom_Surface) S1, S2; - + S1 = BRep_Tool::Surface(aFace,L1); S2 = BRep_Tool::Surface(aCheckedFace,L2); - + if (S1 == S2 && L1 == L2) return true; @@ -586,7 +604,7 @@ Standard_Boolean BlockFix_UnionFaces::IsSameDomain(const TopoDS_Face& aFace, //======================================================================= //function : MovePCurves -//purpose : +//purpose : //======================================================================= void BlockFix_UnionFaces::MovePCurves(TopoDS_Face& aTarget, @@ -594,17 +612,17 @@ void BlockFix_UnionFaces::MovePCurves(TopoDS_Face& aTarget, { BRep_Builder B; for(TopExp_Explorer wexp(aSource,TopAbs_WIRE);wexp.More();wexp.Next()) { - Handle(ShapeFix_Wire) sfw = new ShapeFix_Wire(TopoDS::Wire(wexp.Current()), + Handle(ShapeFix_Wire) sfw = new ShapeFix_Wire(TopoDS::Wire(wexp.Current()), aTarget, Precision::Confusion()); sfw->FixReorder(); Standard_Boolean isReoredFailed = sfw->StatusReorder ( ShapeExtend_FAIL ); sfw->FixEdgeCurves(); if(isReoredFailed) continue; - + sfw->FixShifted(); sfw->FixDegenerated(); - + // remove degenerated edges from not degenerated points ShapeAnalysis_Edge sae; Handle(ShapeExtend_WireData) sewd = sfw->WireData(); @@ -615,7 +633,7 @@ void BlockFix_UnionFaces::MovePCurves(TopoDS_Face& aTarget, i--; } } - + TopoDS_Wire ResWire = sfw->Wire(); B.Add(aTarget,ResWire); } diff --git a/src/GEOMAlgo/BlockFix_UnionFaces.hxx b/src/GEOMAlgo/BlockFix_UnionFaces.hxx index 9cf0578d8..afe00c173 100644 --- a/src/GEOMAlgo/BlockFix_UnionFaces.hxx +++ b/src/GEOMAlgo/BlockFix_UnionFaces.hxx @@ -18,7 +18,7 @@ // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -// + #ifndef _BlockFix_UnionFaces_HeaderFile #define _BlockFix_UnionFaces_HeaderFile @@ -28,10 +28,6 @@ #ifndef _Standard_Boolean_HeaderFile #include #endif -class TopoDS_Shape; -class TopoDS_Face; - - #ifndef _Standard_HeaderFile #include #endif @@ -39,63 +35,55 @@ class TopoDS_Face; #include #endif -class BlockFix_UnionFaces { +class TopoDS_Shape; +class TopoDS_Face; +class BlockFix_UnionFaces +{ public: - - void* operator new(size_t,void* anAddress) - { - return anAddress; - } - void* operator new(size_t size) - { - return Standard::Allocate(size); - } - void operator delete(void *anAddress) - { - if (anAddress) Standard::Free((Standard_Address&)anAddress); - } - // Methods PUBLIC - // -Standard_EXPORT BlockFix_UnionFaces(); -Standard_EXPORT Standard_Real& GetTolerance() ; -Standard_EXPORT TopoDS_Shape Perform(const TopoDS_Shape& Shape) ; -Standard_EXPORT virtual Standard_Boolean IsSameDomain(const TopoDS_Face& aFace,const TopoDS_Face& aChekedFace) const; -Standard_EXPORT virtual void MovePCurves(TopoDS_Face& aTarget,const TopoDS_Face& aSource) const; - - - - - -protected: - - // Methods PROTECTED - // - - - // Fields PROTECTED - // - + void* operator new(size_t,void* anAddress) + { + return anAddress; + } + void* operator new(size_t size) + { + return Standard::Allocate(size); + } + void operator delete(void *anAddress) + { + if (anAddress) Standard::Free((Standard_Address&)anAddress); + } + + // Methods PUBLIC + // + Standard_EXPORT BlockFix_UnionFaces(); + + Standard_EXPORT Standard_Real& GetTolerance(); + + /* \brief To get/set the OptimumNbFaces parameter + * + * If a being processed solid has less than OptimumNbFaces + * faces, no union will be performed. + * By default this parameter is set to 6 (to correctly + * process blocks - hexahedral solids) + * Special values: 0 - do all possible unions, regardless the faces quantity, + * negative - do not perform any unions, regardless the faces quantity. + * + */ + Standard_EXPORT Standard_Integer& GetOptimumNbFaces(); + + Standard_EXPORT TopoDS_Shape Perform(const TopoDS_Shape& Shape); + + Standard_EXPORT virtual Standard_Boolean IsSameDomain(const TopoDS_Face& aFace, + const TopoDS_Face& aChekedFace) const; + Standard_EXPORT virtual void MovePCurves(TopoDS_Face& aTarget, + const TopoDS_Face& aSource) const; private: - - // Methods PRIVATE - // - - - // Fields PRIVATE - // -Standard_Real myTolerance; - - + // Fields PRIVATE + // + Standard_Real myTolerance; + Standard_Integer myOptimumNbFaces; }; - - - - -// other Inline functions and methods (like "C++: function call" methods) -// - - #endif diff --git a/src/GEOMAlgo/GEOMAlgo_Tools.cxx b/src/GEOMAlgo/GEOMAlgo_Tools.cxx index bad8a3c15..2556e1331 100644 --- a/src/GEOMAlgo/GEOMAlgo_Tools.cxx +++ b/src/GEOMAlgo/GEOMAlgo_Tools.cxx @@ -286,41 +286,58 @@ Standard_Boolean GEOMAlgo_Tools::ProjectPointOnShape(const gp_Pnt& aP1, gp_Pnt& aP2, IntTools_Context& aCtx) { - Standard_Boolean bIsDone=Standard_False; + Standard_Boolean bIsDone = Standard_False; Standard_Real aT2; TopAbs_ShapeEnum aType; // - aType=aS.ShapeType(); - switch(aType) { - case TopAbs_EDGE: { - const TopoDS_Edge& aE2=TopoDS::Edge(aS); - // - bIsDone=aCtx.ProjectPointOnEdge(aP1, aE2, aT2); - if (!bIsDone) { - return bIsDone; + aType = aS.ShapeType(); + switch (aType) + { + case TopAbs_EDGE: + { + cout << "$$$ case TopAbs_EDGE" << endl; + const TopoDS_Edge& aE2 = TopoDS::Edge(aS); + // + if (BRep_Tool::Degenerated(aE2)) { // jfa + cout << "$$$ Degenerated" << endl; + return Standard_True; + } + else { + Standard_Real f, l; + Handle(Geom_Curve) aC3D = BRep_Tool::Curve (aE2, f, l); + if (aC3D.IsNull()) { + cout << "$$$ aC3D.IsNull()" << endl; + return Standard_True; + } + bIsDone = aCtx.ProjectPointOnEdge(aP1, aE2, aT2); + } + if (!bIsDone) { + cout << "$$$ !bIsDone" << endl; + return bIsDone; + } + // + GEOMAlgo_Tools::PointOnEdge(aE2, aT2, aP2); } - // - GEOMAlgo_Tools::PointOnEdge(aE2, aT2, aP2); - } break; // - case TopAbs_FACE: { - const TopoDS_Face& aF2=TopoDS::Face(aS); - GeomAPI_ProjectPointOnSurf& aProj=aCtx.ProjPS(aF2); - // - aProj.Perform(aP1); - bIsDone=aProj.IsDone(); - if (!bIsDone) { - return bIsDone; + case TopAbs_FACE: + { + const TopoDS_Face& aF2 = TopoDS::Face(aS); + GeomAPI_ProjectPointOnSurf& aProj = aCtx.ProjPS(aF2); + // + aProj.Perform(aP1); + bIsDone = aProj.IsDone(); + if (!bIsDone) { + return bIsDone; + } + // + aP2 = aProj.NearestPoint(); } - // - aP2=aProj.NearestPoint(); - } break; // default: break; // Err - } + } return bIsDone; } //======================================================================= diff --git a/src/GEOMGUI/GEOM_msg_en.po b/src/GEOMGUI/GEOM_msg_en.po index df66b8bae..345d34fae 100644 --- a/src/GEOMGUI/GEOM_msg_en.po +++ b/src/GEOMGUI/GEOM_msg_en.po @@ -2254,6 +2254,9 @@ msgstr "SupressFaces" msgid "CHANGE_ORIENTATION_NEW_OBJ_NAME" msgstr "Invert" +msgid "GEOM_RMEE_UNION_FACES" +msgstr "Union faces, laying on common surface" + msgid "REMOVE_EXTRA_EDGES_NEW_OBJ_NAME" msgstr "NoExtraEdges" diff --git a/src/GEOMImpl/GEOMImpl_BlockDriver.cxx b/src/GEOMImpl/GEOMImpl_BlockDriver.cxx index 7a98359ac..880661f70 100644 --- a/src/GEOMImpl/GEOMImpl_BlockDriver.cxx +++ b/src/GEOMImpl/GEOMImpl_BlockDriver.cxx @@ -18,7 +18,7 @@ // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -// + #include #include @@ -506,6 +506,7 @@ Standard_Integer GEOMImpl_BlockDriver::Execute(TFunction_Logbook& log) const // 1. Improve solids with seam and/or degenerated edges BlockFix_BlockFixAPI aTool; //aTool.Tolerance() = toler; + aTool.OptimumNbFaces() = aCI.GetOptimumNbFaces(); aTool.SetShape(aBlockOrComp); aTool.Perform(); diff --git a/src/GEOMImpl/GEOMImpl_IBlockTrsf.hxx b/src/GEOMImpl/GEOMImpl_IBlockTrsf.hxx index b6827133d..f618a2695 100644 --- a/src/GEOMImpl/GEOMImpl_IBlockTrsf.hxx +++ b/src/GEOMImpl/GEOMImpl_IBlockTrsf.hxx @@ -19,8 +19,8 @@ // // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // -//NOTE: This is an interface to a function for the Blocks Multi-Transformations. -// +//NOTE: This is an interface to a functions for the Blocks Multi-Transformations and repairing + #include "GEOM_Function.hxx" #define TRSF_ORIGIN 1 @@ -32,6 +32,8 @@ #define TRSF_FACE_2_V 6 #define TRSF_NBITER_V 7 +#define TRSF_NB_FACES 8 + class GEOMImpl_IBlockTrsf { public: @@ -49,6 +51,8 @@ class GEOMImpl_IBlockTrsf void SetNbIterU (int theNbIter) { _func->SetInteger(TRSF_NBITER_U, theNbIter); } void SetNbIterV (int theNbIter) { _func->SetInteger(TRSF_NBITER_V, theNbIter); } + void SetOptimumNbFaces (int theNbFaces) { _func->SetInteger(TRSF_NB_FACES, theNbFaces); } + int GetFace1U () { return _func->GetInteger(TRSF_FACE_1_U); } int GetFace2U () { return _func->GetInteger(TRSF_FACE_2_U); } int GetFace1V () { return _func->GetInteger(TRSF_FACE_1_V); } @@ -56,6 +60,8 @@ class GEOMImpl_IBlockTrsf int GetNbIterU() { return _func->GetInteger(TRSF_NBITER_U); } int GetNbIterV() { return _func->GetInteger(TRSF_NBITER_V); } + int GetOptimumNbFaces() { return _func->GetInteger(TRSF_NB_FACES); } + private: Handle(GEOM_Function) _func; diff --git a/src/GEOMImpl/GEOMImpl_IBlocksOperations.cxx b/src/GEOMImpl/GEOMImpl_IBlocksOperations.cxx index 9c461c123..6f7e86cd0 100644 --- a/src/GEOMImpl/GEOMImpl_IBlocksOperations.cxx +++ b/src/GEOMImpl/GEOMImpl_IBlocksOperations.cxx @@ -18,7 +18,7 @@ // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -// + #ifdef WNT #pragma warning( disable:4786 ) #endif @@ -2311,7 +2311,8 @@ Standard_Boolean GEOMImpl_IBlocksOperations::CheckCompoundOfBlocks */ //============================================================================= Handle(GEOM_Object) GEOMImpl_IBlocksOperations::RemoveExtraEdges - (Handle(GEOM_Object) theObject) + (Handle(GEOM_Object) theObject, + const Standard_Integer theOptimumNbFaces) { SetErrorCode(KO); @@ -2332,6 +2333,7 @@ Handle(GEOM_Object) GEOMImpl_IBlocksOperations::RemoveExtraEdges GEOMImpl_IBlockTrsf aTI (aFunction); aTI.SetOriginal(aLastFunction); + aTI.SetOptimumNbFaces(theOptimumNbFaces); //Compute the fixed shape try { @@ -2351,7 +2353,8 @@ Handle(GEOM_Object) GEOMImpl_IBlocksOperations::RemoveExtraEdges //Make a Python command GEOM::TPythonDump(aFunction) << aCopy - << " = geompy.RemoveExtraEdges(" << theObject << ")"; + << " = geompy.RemoveExtraEdges(" << theObject + << ", " << theOptimumNbFaces << ")"; SetErrorCode(OK); return aCopy; @@ -2384,6 +2387,7 @@ Handle(GEOM_Object) GEOMImpl_IBlocksOperations::CheckAndImprove GEOMImpl_IBlockTrsf aTI (aFunction); aTI.SetOriginal(aLastFunction); + aTI.SetOptimumNbFaces(6); //Compute the fixed shape try { diff --git a/src/GEOMImpl/GEOMImpl_IBlocksOperations.hxx b/src/GEOMImpl/GEOMImpl_IBlocksOperations.hxx index 449c36f51..491a60613 100644 --- a/src/GEOMImpl/GEOMImpl_IBlocksOperations.hxx +++ b/src/GEOMImpl/GEOMImpl_IBlocksOperations.hxx @@ -18,7 +18,7 @@ // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -// + #ifndef _GEOMImpl_IBlocksOperations_HXX_ #define _GEOMImpl_IBlocksOperations_HXX_ @@ -125,7 +125,8 @@ class GEOMImpl_IBlocksOperations : public GEOM_IOperations { Standard_EXPORT TCollection_AsciiString PrintBCErrors (Handle(GEOM_Object) theCompound, const std::list& theErrors); - Standard_EXPORT Handle(GEOM_Object) RemoveExtraEdges (Handle(GEOM_Object) theShape); + Standard_EXPORT Handle(GEOM_Object) RemoveExtraEdges (Handle(GEOM_Object) theShape, + const Standard_Integer theOptimumNbFaces = 6); Standard_EXPORT Handle(GEOM_Object) CheckAndImprove (Handle(GEOM_Object) theCompound); diff --git a/src/GEOM_I/GEOM_IBlocksOperations_i.cc b/src/GEOM_I/GEOM_IBlocksOperations_i.cc index 4763ba016..9eb087de4 100644 --- a/src/GEOM_I/GEOM_IBlocksOperations_i.cc +++ b/src/GEOM_I/GEOM_IBlocksOperations_i.cc @@ -689,7 +689,9 @@ char* GEOM_IBlocksOperations_i::PrintBCErrors * RemoveExtraEdges */ //============================================================================= -GEOM::GEOM_Object_ptr GEOM_IBlocksOperations_i::RemoveExtraEdges (GEOM::GEOM_Object_ptr theShape) +GEOM::GEOM_Object_ptr GEOM_IBlocksOperations_i::RemoveExtraEdges + (GEOM::GEOM_Object_ptr theShape, + CORBA::Long theOptimumNbFaces) { GEOM::GEOM_Object_var aGEOMObject; @@ -701,8 +703,7 @@ GEOM::GEOM_Object_ptr GEOM_IBlocksOperations_i::RemoveExtraEdges (GEOM::GEOM_Obj if (aShape.IsNull()) return aGEOMObject._retn(); //Get the result - Handle(GEOM_Object) anObject = - GetOperations()->RemoveExtraEdges(aShape); + Handle(GEOM_Object) anObject = GetOperations()->RemoveExtraEdges(aShape, theOptimumNbFaces); if (!GetOperations()->IsDone() || anObject.IsNull()) return aGEOMObject._retn(); diff --git a/src/GEOM_I/GEOM_IBlocksOperations_i.hh b/src/GEOM_I/GEOM_IBlocksOperations_i.hh index ff6480f8b..49e326ea1 100644 --- a/src/GEOM_I/GEOM_IBlocksOperations_i.hh +++ b/src/GEOM_I/GEOM_IBlocksOperations_i.hh @@ -18,7 +18,7 @@ // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -// + #ifndef _GEOM_IBlocksOperations_i_HeaderFile #define _GEOM_IBlocksOperations_i_HeaderFile @@ -112,7 +112,8 @@ class GEOM_I_EXPORT GEOM_IBlocksOperations_i : char* PrintBCErrors (GEOM::GEOM_Object_ptr theCompound, const GEOM::GEOM_IBlocksOperations::BCErrors& theErrors); - GEOM::GEOM_Object_ptr RemoveExtraEdges (GEOM::GEOM_Object_ptr theShape); + GEOM::GEOM_Object_ptr RemoveExtraEdges (GEOM::GEOM_Object_ptr theShape, + CORBA::Long theOptimumNbFaces); GEOM::GEOM_Object_ptr CheckAndImprove (GEOM::GEOM_Object_ptr theCompound); diff --git a/src/GEOM_SWIG/GEOM_TestOthers.py b/src/GEOM_SWIG/GEOM_TestOthers.py index 76d4e2811..f1da60701 100644 --- a/src/GEOM_SWIG/GEOM_TestOthers.py +++ b/src/GEOM_SWIG/GEOM_TestOthers.py @@ -104,6 +104,8 @@ def TestOtherOperations (geompy, math): vy = geompy.MakeVectorDXDYDZ( 0, 1, 0) vz = geompy.MakeVectorDXDYDZ( 0, 0, 1) + v_y = geompy.MakeVectorDXDYDZ( 0, -1, 0) + p11 = geompy.MakeVertex( 0, 0, 0) p12 = geompy.MakeVertex(30, 0, 0) p13 = geompy.MakeVertex(30, 30, 0) @@ -320,18 +322,17 @@ def TestOtherOperations (geompy, math): v_0pp = geompy.MakeVectorDXDYDZ( 0, 1, 1) #v_0np = geompy.MakeVectorDXDYDZ( 0, -1, 1) - #v_p0p = geompy.MakeVectorDXDYDZ( 1, 0, 1) - #v_n0p = geompy.MakeVectorDXDYDZ(-1, 0, 1) - #v_pp0 = geompy.MakeVectorDXDYDZ( 1, 1, 0) - #v_np0 = geompy.MakeVectorDXDYDZ(-1, 1, 0) - v_0n0 = geompy.MakeVectorDXDYDZ( 0, -1, 0) + v_p0p = geompy.MakeVectorDXDYDZ( 1, 0, 1) + v_p0n = geompy.MakeVectorDXDYDZ(1, 0, -1) + v_pp0 = geompy.MakeVectorDXDYDZ( 1, 1, 0) + v_pn0 = geompy.MakeVectorDXDYDZ(1, -1, 0) #pln_0pp = geompy.MakePlane(p0, v_0pp, 300) #pln_0np = geompy.MakePlane(p0, v_0np, 300) - #pln_p0p = geompy.MakePlane(p0, v_p0p, 300) - #pln_n0p = geompy.MakePlane(p0, v_n0p, 300) - #pln_pp0 = geompy.MakePlane(p0, v_pp0, 300) - #pln_np0 = geompy.MakePlane(p0, v_np0, 300) + pln_p0p = geompy.MakePlane(p0, v_p0p, 300) + pln_p0n = geompy.MakePlane(p0, v_p0n, 300) + pln_pp0 = geompy.MakePlane(p0, v_pp0, 300) + pln_pn0 = geompy.MakePlane(p0, v_pn0, 300) # #part_objs = [b0, pln_0pp, pln_0np, pln_p0p, pln_n0p, pln_pp0, pln_np0] #part_tool_1 = geompy.MakePartition(part_objs, [], [], [b0]) @@ -410,6 +411,49 @@ def TestOtherOperations (geompy, math): geompy.addToStudy(freeFaces, "freeFaces") + # RemoveExtraEdges with union of all faces, sharing common surfaces + tools = [pln_pp0, pln_pn0, pln_p0p, pln_p0n] + + Partition_1 = geompy.MakePartition([Sphere], tools, [], [], geompy.ShapeType["SOLID"], 0, []) + geompy.addToStudy(Partition_1, "Partition_1") + + faces = geompy.SubShapeAllSorted(Partition_1, geompy.ShapeType["FACE"]) + + Face_1 = faces[0] + Face_2 = faces[39] + Face_3 = faces[40] + + geompy.addToStudyInFather(Partition_1, Face_1, "Face_1") + geompy.addToStudyInFather(Partition_1, Face_2, "Face_2") + geompy.addToStudyInFather(Partition_1, Face_3, "Face_3") + + Vector_5 = geompy.MakeVectorDXDYDZ(0, 20, 0) + geompy.addToStudy(Vector_5, "Vector_5") + + Rotation_1 = geompy.MakeRotation(Face_1, Vector_5, 90*math.pi/180.0) + Rotation_2 = geompy.MakeRotation(Face_1, Vector_5, 180*math.pi/180.0) + Rotation_3 = geompy.MakeRotation(Face_1, Vector_5, 270*math.pi/180.0) + + geompy.addToStudy(Rotation_1, "Rotation_1") + geompy.addToStudy(Rotation_2, "Rotation_2") + geompy.addToStudy(Rotation_3, "Rotation_3") + + Vector_6 = geompy.MakeVectorDXDYDZ(0, 0, 20) + geompy.addToStudy(Vector_6, "Vector_6") + + Rotation_4 = geompy.MakeRotation(Face_1, Vector_6, 90*math.pi/180.0) + Rotation_5 = geompy.MakeRotation(Face_1, Vector_6, -90*math.pi/180.0) + geompy.addToStudy(Rotation_4, "Rotation_4") + geompy.addToStudy(Rotation_5, "Rotation_5") + + Shell_1 = geompy.MakeShell([Face_1, Rotation_1, Rotation_2, Rotation_3, Rotation_4, Rotation_5]) + Solid_1 = geompy.MakeSolid([Shell_1]) + NoExtraEdges_1 = geompy.RemoveExtraEdges(Solid_1, 0) + + geompy.addToStudy(Shell_1, "Shell_1") + geompy.addToStudy(Solid_1, "Solid_1") + geompy.addToStudy(NoExtraEdges_1, "NoExtraEdges_1") + # RemoveExtraEdges freeFacesWithoutExtra = geompy.RemoveExtraEdges(freeFaces) @@ -474,13 +518,13 @@ def TestOtherOperations (geompy, math): # GetShapesOnPlaneWithLocation Loc = geompy.MakeVertex(0, -50, 0) edges_on_pln = geompy.GetShapesOnPlaneWithLocation(blocksComp, geompy.ShapeType["EDGE"], - v_0n0, Loc, geompy.GEOM.ST_ON) + v_y, Loc, geompy.GEOM.ST_ON) for edge_i in edges_on_pln: geompy.addToStudy(edge_i, "Edge on Plane (N = (0, -1, 0) & Location = (0, -50, 0)") # GetShapesOnPlaneWithLocationIDs edges_on_pln_ids = geompy.GetShapesOnPlaneWithLocationIDs( - blocksComp, geompy.ShapeType["EDGE"], v_0n0, Loc, geompy.GEOM.ST_ON) + blocksComp, geompy.ShapeType["EDGE"], v_y, Loc, geompy.GEOM.ST_ON) group_edges_on_pln = geompy.CreateGroup(blocksComp, geompy.ShapeType["EDGE"]) geompy.UnionIDs(group_edges_on_pln, edges_on_pln_ids) grname = "Group of edges on Plane (N = (0, -1, 0) & Location = (0, -50, 0))" diff --git a/src/GEOM_SWIG/geompyDC.py b/src/GEOM_SWIG/geompyDC.py index 889d0b69e..76bdb024a 100644 --- a/src/GEOM_SWIG/geompyDC.py +++ b/src/GEOM_SWIG/geompyDC.py @@ -2990,12 +2990,16 @@ class geompyDC(GEOM._objref_GEOM_Gen): # Unite faces and edges, sharing one surface. It means that # this faces must have references to one C++ surface object (handle). # @param theShape The compound or single solid to remove irregular edges from. + # @param theOptimumNbFaces If more than zero, unite faces only for those solids, + # that have more than theOptimumNbFaces faces. If zero, unite faces always, + # regardsless their quantity in the solid. If negative (the default value), + # do not unite faces at all. For blocks repairing recommended value is 6. # @return Improved shape. # # @ref swig_RemoveExtraEdges "Example" - def RemoveExtraEdges(self,theShape): + def RemoveExtraEdges(self,theShape,theOptimumNbFaces=-1): # Example: see GEOM_TestOthers.py - anObj = self.BlocksOp.RemoveExtraEdges(theShape) + anObj = self.BlocksOp.RemoveExtraEdges(theShape,theOptimumNbFaces) RaiseIfFailed("RemoveExtraEdges", self.BlocksOp) return anObj diff --git a/src/RepairGUI/RepairGUI_RemoveExtraEdgesDlg.cxx b/src/RepairGUI/RepairGUI_RemoveExtraEdgesDlg.cxx index 9a7cc55dd..9eb3e1ba6 100644 --- a/src/RepairGUI/RepairGUI_RemoveExtraEdgesDlg.cxx +++ b/src/RepairGUI/RepairGUI_RemoveExtraEdgesDlg.cxx @@ -24,13 +24,15 @@ // Author : Michael Zorin // Module : GEOM // $Header$ -// + #include "RepairGUI_RemoveExtraEdgesDlg.h" #include "SalomeApp_Application.h" #include "LightApp_SelectionMgr.h" #include "SUIT_Session.h" +#include "DlgRef_1Sel1Check_QTD.h" + #include "GEOMImpl_Types.hxx" #include @@ -62,12 +64,14 @@ RepairGUI_RemoveExtraEdgesDlg::RepairGUI_RemoveExtraEdgesDlg(GeometryGUI* theGeo RadioButton2->close(TRUE); RadioButton3->close(TRUE); - GroupPoints = new DlgRef_1Sel_QTD(this, "GroupPoints"); + GroupPoints = new DlgRef_1Sel1Check_QTD(this, "GroupPoints"); GroupPoints->GroupBox1->setTitle(tr("GEOM_REMOVE_EXTRA_EDGES")); GroupPoints->TextLabel1->setText(tr("GEOM_SELECTED_SHAPE")); GroupPoints->PushButton1->setPixmap(image1); GroupPoints->LineEdit1->setReadOnly( true ); + GroupPoints->CheckButton1->setText(tr("GEOM_RMEE_UNION_FACES")); + Layout1->addWidget(GroupPoints, 2, 0); /***************************************************************/ @@ -97,6 +101,8 @@ void RepairGUI_RemoveExtraEdgesDlg::Init() myOkObject = false; + GroupPoints->CheckButton1->setChecked( false ); + activateSelection(); GroupBoxPublish->show(); @@ -282,10 +288,14 @@ bool RepairGUI_RemoveExtraEdgesDlg::execute( ObjectList& objects ) { GEOM::GEOM_Object_var anObj; - anObj = GEOM::GEOM_IBlocksOperations::_narrow(getOperation())->RemoveExtraEdges(myObject); + int nbFacesOptimum = -1; // -1 means do not union faces + if (GroupPoints->CheckButton1->isChecked()) + nbFacesOptimum = 0; // 0 means union all faces, that possible + anObj = GEOM::GEOM_IBlocksOperations::_narrow(getOperation())->RemoveExtraEdges + (myObject, nbFacesOptimum); - if ( !anObj->_is_nil() ) - objects.push_back( anObj._retn() ); + if (!anObj->_is_nil()) + objects.push_back(anObj._retn()); return true; } diff --git a/src/RepairGUI/RepairGUI_RemoveExtraEdgesDlg.h b/src/RepairGUI/RepairGUI_RemoveExtraEdgesDlg.h index 3eabb54bf..8172867d7 100644 --- a/src/RepairGUI/RepairGUI_RemoveExtraEdgesDlg.h +++ b/src/RepairGUI/RepairGUI_RemoveExtraEdgesDlg.h @@ -23,12 +23,14 @@ // File : RepairGUI_RemoveExtraEdgesDlg.h // Author : Michael ZORIN // Module : GEOM -// + #ifndef DIALOGBOX_REMOVEEXTRAEDGES_H #define DIALOGBOX_REMOVEEXTRAEDGES_H #include "GEOMBase_Skeleton.h" -#include "DlgRef_1Sel_QTD.h" +//#include "DlgRef_1Sel_QTD.h" + +class DlgRef_1Sel1Check_QTD; //================================================================================= // class : RepairGUI_RemoveExtraEdgesDlg @@ -60,8 +62,9 @@ private : GEOM::GEOM_Object_var myObject; bool myOkObject; - DlgRef_1Sel_QTD* GroupPoints; - + //DlgRef_1Sel_QTD* GroupPoints; + //DlgRef_1Sel1Check* GroupPoints; + DlgRef_1Sel1Check_QTD* GroupPoints; private slots: void ClickOnOk(); -- 2.39.2