From ed5673f40bde611ab306086e0eacf64ebb764f6c Mon Sep 17 00:00:00 2001 From: ana Date: Tue, 16 Dec 2014 19:27:28 +0300 Subject: [PATCH] 0022762: [EDF] Fast detection of face/face face/solid solid/solid interference --- doc/salome/examples/CMakeLists.txt | 3 +- doc/salome/examples/check_shape.py | 2 +- doc/salome/examples/fast_intersection.py | 34 + doc/salome/gui/GEOM/images/measures12.png | Bin 0 -> 35892 bytes .../gui/GEOM/input/fast_intersection.doc | 61 ++ .../gui/GEOM/input/tui_fast_intersection.doc | 6 + .../gui/GEOM/input/tui_measurement_tools.doc | 1 + .../gui/GEOM/input/tui_test_measures.doc | 5 +- .../GEOM/input/using_measurement_tools.doc | 1 + idl/GEOM_Gen.idl | 20 + resources/CMakeLists.txt | 1 + resources/fast_intersect.png | Bin 0 -> 814 bytes src/GEOMGUI/GEOM_images.ts | 8 + src/GEOMGUI/GEOM_msg_en.ts | 47 ++ src/GEOMGUI/GEOM_msg_fr.ts | 172 +++++ src/GEOMGUI/GEOM_msg_ja.ts | 172 +++++ src/GEOMGUI/GeometryGUI.cxx | 4 + src/GEOMGUI/GeometryGUI_Operations.h | 1 + src/GEOMImpl/CMakeLists.txt | 3 +- src/GEOMImpl/GEOMImpl_IMeasureOperations.cxx | 84 +++ src/GEOMImpl/GEOMImpl_IMeasureOperations.hxx | 5 + src/GEOM_I/GEOM_IMeasureOperations_i.cc | 53 ++ src/GEOM_I/GEOM_IMeasureOperations_i.hh | 7 + src/GEOM_SWIG/GEOM_TestMeasures.py | 6 + src/GEOM_SWIG/geomBuilder.py | 79 +- src/MeasureGUI/CMakeLists.txt | 3 + src/MeasureGUI/MeasureGUI.cxx | 4 + .../MeasureGUI_FastCheckIntersectionsDlg.cxx | 696 ++++++++++++++++++ .../MeasureGUI_FastCheckIntersectionsDlg.h | 98 +++ 29 files changed, 1551 insertions(+), 25 deletions(-) create mode 100644 doc/salome/examples/fast_intersection.py create mode 100644 doc/salome/gui/GEOM/images/measures12.png create mode 100644 doc/salome/gui/GEOM/input/fast_intersection.doc create mode 100644 doc/salome/gui/GEOM/input/tui_fast_intersection.doc create mode 100644 resources/fast_intersect.png create mode 100644 src/MeasureGUI/MeasureGUI_FastCheckIntersectionsDlg.cxx create mode 100644 src/MeasureGUI/MeasureGUI_FastCheckIntersectionsDlg.h diff --git a/doc/salome/examples/CMakeLists.txt b/doc/salome/examples/CMakeLists.txt index 76c3883e1..0817e5fb4 100644 --- a/doc/salome/examples/CMakeLists.txt +++ b/doc/salome/examples/CMakeLists.txt @@ -65,7 +65,8 @@ SET(GOOD_TESTS complex_objs_ex07.py complex_objs_ex08.py complex_objs_ex09.py - complex_objs_ex10.py + complex_objs_ex10.py + fast_intersection.py free_boundaries.py free_faces.py GEOM_box.py diff --git a/doc/salome/examples/check_shape.py b/doc/salome/examples/check_shape.py index a0e728967..f10f31c8a 100644 --- a/doc/salome/examples/check_shape.py +++ b/doc/salome/examples/check_shape.py @@ -10,7 +10,7 @@ geompy = geomBuilder.New(salome.myStudy) box = geompy.MakeBoxDXDYDZ(100,30,100) (IsValid, err) = geompy.CheckShape(box, 0, 2) if IsValid == 0: - geompy.PrintShapeError(box, err) + geompy.PrintShapeErrors(box, err) raise RuntimeError, "Invalid box created" else: print "\nBox is valid" diff --git a/doc/salome/examples/fast_intersection.py b/doc/salome/examples/fast_intersection.py new file mode 100644 index 000000000..4854a579f --- /dev/null +++ b/doc/salome/examples/fast_intersection.py @@ -0,0 +1,34 @@ +# Fast intersection + +import salome +salome.salome_init() +import GEOM +from salome.geom import geomBuilder +geompy = geomBuilder.New(salome.myStudy) + +# create a box +box = geompy.MakeBoxDXDYDZ(100,100,100) +# create a cylinder +cylinder = geompy.MakeCylinderRH(100, 300) + +isOk, res1, res2 = geompy.FastIntersect(box, cylinder) +if isOk == 0: + raise RuntimeError, "No intersection!" +else: + print "\nTwo lists of indexes of sub-shapes localize the intersection:" + print res1, res2 + +# create two boxes with gap +Ver1 = geompy.MakeVertex(0, 0, 0) +Ver2 = geompy.MakeVertex(100, 100, 100) +Ver3 = geompy.MakeVertex(100.1, 0, 0) +Ver4 = geompy.MakeVertex(200, 200, 200) +box1 = geompy.MakeBoxTwoPnt(Ver1, Ver2) +box2 = geompy.MakeBoxTwoPnt(Ver3, Ver4) + +isOk1, aRes1, aRes2 = geompy.FastIntersect(box1, box2, 1.) +if isOk1 == 0: + raise RuntimeError, "No gaps!" +else: + print "\nTwo lists of indexes of sub-shapes localize the gap:" + print aRes1, aRes2 diff --git a/doc/salome/gui/GEOM/images/measures12.png b/doc/salome/gui/GEOM/images/measures12.png new file mode 100644 index 0000000000000000000000000000000000000000..0dba5423c56f67eb9f2a9c534ce9fcb48c194612 GIT binary patch literal 35892 zcmYhi1zc0_8$L`3%0Q_xhDvvjfuJJNDBYcd(ICtL-KCQlt$=`}v`B|Y z^N#QD|9{_?5Bsol#-2LQecjh}-RDGTsJ*%mcnHA5!@IBeT22cO4?h_XkAV6f0q#s0 zd4(A655BwBD;d1Xk;j|3gFCj;s?vCPHL;|ZFe2PB$=lb4?s#|)zTUp@`&>T3@$iuS zigMCA@62{O?xyJIwth1GcXs2q7r5uX+cMg*k@09Gb$jSH+eb?JyRZ6OC#2=+3Gdxo z3CDMLlBZA%W&0u(myyQAR73Re;ltk<+PWJVZJUoH{w&?-O*>X~oK%|rFl{Rx|0l7h zU2f!upq~sd^qbn{nM&?Z%&wFa4YWT^7nVGmJx*P`*sP+wBTdY&uHy6eOn+lIqwCF5 zpSgeS^{1_szprcqo6r8z4Z?oL28#YUiWYAb@R#5^>y4^QQvS zs}*>oc?K3rk@_RxF_!J|ppzs3UjIHxE&SWl_(`u6w|lRh#Xq?+$=e3H@$R$d-k(Mn zpr#wq-q{vz*0pH9vvno2!}**cL{hf+Q0rfAe|%v^Djm}>vaXG{9F$fvHCgDI^J z_3e(+(~8<_plv3qLGwCK|CuL)L2=D>{Qz+-!A5ZO!}L5)(QIa?B@t%{s{FoZ<%~&jF^Dk~HgQ1sXK(Q&9Yk-@a9qm3N=fRMVcJ1vpR0!BR8!01KdsozQ z5+`a!0dQnz&cz(I+Bh?SwZ=J9dWw8Qi%W<@+(4;n|{(=fX z9fYK64a5zikbJ41>&`)azTBxrCOQ_x@skr;EUi10+y)q&x(r+VYp#`dTEhnF| z{t)_=p6r#)bya0(Wv5+tXNO~!k-ow4y@NS?qO|VO*@pwTa4IcYqsnZLD@l+9S>YxU zLP9G>JDyy8Kg?4AO_4A~Sw@K__n4tbUu4z*l>nt+j+X78(d#~I84@k4H0}LnEwV)2 zLG;Dk#ZtB&Jl-KP9M%(-DsU$j1sj;X^WEq}s%y)`8B#U^IkRqa88ed3RrxDxK|!G% zt;@BXcD!{#KO}xT{UcPS!yP_(4n7VOVvv=)P)$cQ_4LBGBCFP(ppFQ7zb8l`RB%tX z#}FUXvWD!9kRQqwY0qK>(v~Y4?GZr+H?|{(woJDDKbAt2Q56OaI|rOaq`xY(q=J@#Rt9i%BSn<+(t)ACB(N*w#ygW@?H00IFz7B#&AMAY|^I9?f zL_lL~N4oKEH;5SDt|iS&v&GN$*-rhte9I^M)wwHA)lR^vmMv79TFmXDNE*W zsXD7nrXh0XZ1(`-)PSWQyax))V4{Zu#?b}?E&e%2d^C?=N2^UfS6in*%G-E89{uw) ztzVD_22!|8n(@VZjVdzj=l4r^>KD|VEJ(FPlko#Ho%yYnH%qo&{wL+^V}TlpBA-Wy zr^;4?KRJ5Wg~L>-TC3SSyfwnK!>qyCuY9bB`xTTEEs52h43z&c@HQeG`vtY{@yM6o za(XVyB#=K#T4gEu`OVJ<0kMRrFO{q}cemB-E<#3nPS_gu6yGeS&vlXqZ5r@|m#;_} zalVa{miOW!lv8*b|D6Wae+Iy^JYLhtR1}8FJTNhGQ-jQfCG75U#XhJ@A)qy6kWNda z%K@Z&bzW(?nl_2OG*Z0uR0X_i^IvO>Z+)Zu$5^o3-$BOI#%rNbm1tI!27gv8>CK`} z<9luS(;^-v)6=5!ebtSxVowk*P9%%d4?An3YtQHZA-I^GQwgPLK1~BVOHhr36}s9y zU&WHfJ0pXg(*aG+r7_WgmoY-Brur+9zI3Tcw9+Oyf>Zwj4joevStoYd5Oa{#HOp#H zmy!BLy+WIDN&C#`T7!^#4{beXP-Eotc-${iTub@+xKeA-@mQsZc|kHoq6+oAR4HS@ zJ*8HzxP2KRdB5}_E)F((E*ENcs>q3jp=J3^o+nqD3H=!@tQ!&Sk5f11s)jO4i6;pL5WM-_xu}5AAGV+5+?Z@!?0qBfTjXgCEVXA7}T=(nQPQ*!R-DYqNXY&x{ncC`+fD z4RkwTPw3nO2sNQdTeAQ7>FqE?(CzPWovdADEz-JOHQiy_9#M9s|J>6%+pz z2oLy<`J+lvS~G;pR%S@S?Mb;wy8FV=m-H)5y;wPww#+Wc!nMJ~|FsYOskb zDY9l0OlhcfH#;Aj}b?;?v}+=(R@tFkzR%6*QvlQGgXK}k;isw>VdzxZyHxtzbS?MuuKMwS24D9VUt+X{q2PXU+(bi z3~_A@@a+wh{vIgV_R>FTF7tiS7zgD@gp%1sj%`IhmbQ*1!5%9$DkRGwh*F_xhgwR$ z;n+wi_%VTStf@W~62+?orF4|U?EP-qRYxdelRNrBIJlotq?yc4MZ+sQ2L{#M@gtMq zddgf#I9Y`zf~4FOWL=%ofvq3jKqt$<;R2x9R>E79569eltC@NS#0p>q*JOta6NY+WgO@mMnrL!=XJ6^s~S-OSTDVLB*loQEHWM>rxcLM&fc)Y zDDlo)-pOeok4S1JkBANlg7X{3)xjC!n&4(%#(dqt9g3BLwAA7OA77X-EZd<3ZIlxJL!yZ|9B)Ctj(y0}>Ii#GRFN)G{DlQdoD&?$d zr8Ubem`Rk?^xq(?F8Hut)bC4N8w@z-32M@T)2(&jup!8LD*dfJUD$5eLrLibp8n#~I^WIh6 zm8=(S+ou;(R1B=U2TeOME_b^`I^IIClSOd!X#)Hnb4Y*?L;zpuNf(HtChU!O75959@?~0~#8*xF`?l8s#y1S_WS# zKSb2=fJRD9o|YLcC!ozjPsAITu6;M3)Bpj58fA%E_b%V-T`$_M38W--Sb&b>gDc0o4#A!C+uns<|?n&x6n!H%Yn>WreW2Bx>7K|@1njxtFWExHWzA{Fejo{ zM9}xkuP#$oJ{At|Qksl%-xT5$s%mY^X`E8&@ZO8n=q6*Lj;Czt#Gsj`@=Fp^04+84VjYaS5_!t`8q4c69uD4wGn!R!XL8MF>CFy zxOt1rEF2ed5DGHj>!fF5$rpyYY4-Ca&y|F$)EX35r--2_k(#JYkQGZpk(C^L=6*nE z&nK+EQ4}{{ziGqY*MBDOIW}s3W^FK%I^Q9G`SV1V$EpqGzFAloc&z?Y9P{t;EJpCg zzwf%n`|(4+SKZU%F)%rrO|QbEs9Du0fNofpgq3wpiy?At+moJ8G_Jzq`arlUp9eU5MgNGVf_+ zRi_sZ@E=WG&44=tdMg?0c$Fj>H_ne5sZw}@+Yih901mzYN57qjyT%glAR~z`uO@RZ zOk>lR}c2T@$zQ$5_~_6`2;z?yptLt74xG0=Ts_M%pIRu6iru1`Q;Dw z{m3pj97TfWW+CjhabU4(LyQhK+KIoNeP$!X0u`lY{cOUQD+{8lF{rf>O29Vv6l|ur zpi%{RQhT~hhM1t{<3dH%r{$5+cN4_$KeiJvl;q(@G}#2UpS`Ue0!0Xy^wf3!i#42W z+&y2Z@VkDuwb1rvK5(ky<8JF;tZA2o*FP8ax%Y#cZLhN1Y(0iL@~L;}Gu`%n*ZaM) z)qrv%uMh8ee6cPeT9taqizl@-;rEJjQT+MA!uOhgF)!Um?d*J#_Q~#-=b+ zSKcM>O*`DdKKEeE%&%#(JnUh!j)+Tq_EBRPR{EUwnroK5DOE=W{lMV2SLGp3b}LTxDp z)Mcvc1B;6h=-&4Kn%3mqWaS$RTAOS`uqFj6k_t)0cMD;`r zOV`g6YtO3n!!eyVi*-#d7t57GetQq=_SCH&%t@^8&s)XJUA0;LyWCxs=#qH9$1fDv z$?mnyA7SO9Nav?KGi?kN0ZANkd1&S$;y)CY8$7Q_d2x~)R@2lS)xmx~+LY0`0kS(g zmFPk?UwD7q<&X$CD;B!geVB0kJznVMs4E0xN$N*LjL7WYp~B@~_onO@XFdH`XA~vx zzsi8iiQ+}anD!lqleU|Mw}&!4U&1oAZC?KExclbfW5mB3iyzDVcVoB3U7;bS@PoQyP7}7V6m)s9X=Q3LR!hcN9X2s` z^LZfKh&Uqk=pAo?im1w$`V_Q@#+2W?&fiv>urd2XKY=MfcQodrMttB%J^oIF>qpCe zz9_ymA+gj=K2S!F)#h`Foix|lf1e*Wv#1pbCk$d{-8mvoGBHW8$;A zmv@_GuD`F^i*>{e75&4E&EkLJ5EQC z0l1#o;3E6ry$scz#=h{Lk;Z*Gy7$B>+)+3nesAkPt5yoJtdXiTzF zmHklCcPSomq0T{%9DI>!1l+2$Ro5(V1PlfnPKRDPeE>f)Q%IU11pZ(T9o(JO)RRl{ zD5z|D&5F-QOdGFaHe_xBQx-u`>V9F#zl9 zAQ};G=-;WQVcdBwz5FDts7Sp3vf(&Kgd3S#SDli!FqgJK=pM1@RyH^l%_?B!UUOwp zd7F35nE>uB3ojSa&9W|w2LBchTVJ{>YJfXvy`Uc#MOh*D&rH5`u#I>bo+=a z4$V<*&$dGwfAtUkrX-B?h5x6k5{0~80Xa0nh^j4>iaM~^GEr{Uz*MQ97&(ROs9bA5 zvL-N|ej-z?X@m*fFFw3yh()`S_sr^Q<~|fABt&n;g5$3&!p2cUJ(nOl16=YIDz;IU zTVH1ls|dMAm=kOHFm4)z)5ZfKb(?F#frnl0Cp$kS1LlHBRvxH=z2TVVeCl5M^!?BM zB;*-c9)ZWJH9`q}z3L3}5ZkDV-IEO`mGoq)KgtN|=yf3MIzSeW0 ztO?N}WIc=SQ!Dt9^>@E`e`WLNUos%n(7;TU953zH!uJp^vU(yt-+hbrBFHY&PjeaA zi!a44P71`9@j$)KCFX^vv3JRPgv8|SXIMb24cH_O#YdJ-@1V{0PVZXw(Hhgwav>1? z-dxEx2GjIhQ?*2gZtKF{fOc6^Ix`$e;>bm_im<}b(|yMiSu%eJ+=Bv z@q<-&>ile6mOJCL%nD?=KI4ox^JiJ>A)ym|nRPI>Vkjt)wUX&Hjx&^`JeigdoXd9U z-$x}~&!3Hv9urA05M^b@cfKEFydJ$dlpw`vpTPcdb2TV3^G>aiy3NFniPuKFx@5k( zPJJ+DWK9VmZ2Gz~mo}bZMk!%}L39t$G7ex7gE8!m~V;<+tgY0;LnHEV|sReSYJ-lek z`!WM47Ah6D=KtYy@jdG(7q2L{-Qdfs4#T`Tw*&ty)7({Sj(m~)^ULlU8kT z*PY!@jRtVyYnvS*sQ&1+$JG0`E3u?8jIsVJ2x^!1w}+}S$HwEMolhjzD>hwWqnsTV z{sV2J#a$Opy?&!MqyD0IQ~o+tdcP=Y(qM3q_GF4~BzBe={Pxo0j$FqX0fhuFpXcKB z$G~&hHp6Md6oe~66Il~speCM;u%<+?7iYYl_CG2UjEa5Dha9obC)cg-TW{!dB-f3b zJ!8+LD>O~DUZqydgZPR|HnoaZwQf+f)GG4?(HX9Pxv&_h>!=T!i_Xg^cv-p`&B}N~ zAC7B~s`<2=;|WU?#08?)J!d@>dvg`w(|TD=X0eC?z2lWhu=Ln*@nqHL2kc8ftPQlGT`3UXB*_rCghJJi((@v-6h^aTJyX| zozRY6ELVfYS@b#8sS$91!p&ItRjMYN-*d@|9Sx;NDql|GC8uoyv*z3Bhdh%%-^dvT zyq39mWOHJGC$%R3(r*0b*vJnO5{P{lZ*}?NJ8v25qmG&Zao$+*h_U9OKUiXyxLCnx zUcNZV<;x6w7S?RjTGNT-@GB&nIhloVFU>D`u@`F!(%BU+<_F zp7<;mA@lUg+id7$#Y{i^Y6G_oG!SQ9jSzBY-j#-j3E(WOc7KO6-48ZGk(Vgz0%F?K zUPY;K!^F1Y?aL%`{hh2fxTizF_(4JG*P5ieRy^R3?d}E?gU?t{W^V(o`6YRudp%cn+%oYvywKL3~6!)b?%()@3hOi;3JR=Tz^P?!kS(% zb|xJy&Hf}^7-5P_&baB+`4Ic}uwo?8t`JG}ql(c8C*T-;GAZSSfxOrY6R z(sOrNSpRMN@Xf39C0{;xe>4)YAh`Kr(Ddh4b_{_yWgQ6ZK_Qyp-<}`5@IP7-#-EzVCR` z{FOpY@sYdHXshuieU0e3hokuW$~;02%i}$kFP5gyXf8MXods+ZW3%J>4laoND9kVF z*ht-Y+PII;E&!R^fM%BUZ(Rok>H(X9u8LT^f!6Vct{3Xuxq*NAuRJvq)31Wr&Wa+x z+E;X&AG=WsJeuPhatryqSjwNH*Z>c2A*nrJV1HNraO%5Zhy&2Y8p z&3Lok-GJMFQ%;_gBYt8Mzo-i`&Cr)yWhfkYQ3bA;)aR1^>P=b7;^aa5aD1AO?7W3w)&ka@c z2+jmOBTl7AJyGc*NA>^DnNdI)8miEyrXZ8dKH0U-eG5n$m$us$+~D6N1HDDr5e{_$ z1My2SB1n|vZ`N#OBO|_aweH`H31rGD-tvt8s zsiv_ilKjO73RR4o+7>mcOWO&rmIMPDrkj_5X!JhX+lLa4^Ka|!3~=*XK@l;_iTKh+ zjHWQMgdPtx_v}4`A*@9#O1~0fDdd};eR=;yTi+=Eq|&;jkhAem=YVPh6XRyDbn}*R z^8GHAcsXLw3JW!;j*70qfU_=zulA*CANbJf>bO53b6iS*dFGMNbK67TJGMk;lNnpo zM1aymFlFjVk~mz;h5)*wD8}6R zWC%L0QW|zr0ZX*ZTwShYqdRyXiMVr+8GfuxE#BY6Jh15d>Af-EnT-DR&htzaGx%YW zTBlQ*KR3~PK-4L3%qjByDfXrF#HIWyQ8fv=DwQ??{kg0?aoj*bE0iem74c*Hc^wqK z9!s5Pss{L{OEr#7sTf3!_JsHRUa7jRds+xt_&Gf?Ae*LKe1K)a$rA}PIfY`YQd|`# z40~IR34seSLv_u_6k)YJ9tfW%a8Bs}gCgvGLy98othy2y+VdODtxPR+=z)L>?I6F- zNWpDOup?^+ZB}#Ems?-4L>%A>b+&ZK`}bv@HkP@>1y53fnm+)@x-~7iRTS4I$`u$QqLJJ61^80Ga zs&i%^Qn>>{TkzJ}lTaQO!OJnyM5eMo%n4jTb=isBELPM)0=3$2HP!c!nfAF&z2UcP zIy_3HPXyIJE)bIj^7UI~cp)tP z()q=GyTeEphQ7j#HtoYX%S7!UOChED5JmVT=qTn7ci`{*9x_1axe5$V8{GA2f`5`hJ|Op_ zYIk^#S`enzh()*si)}ivTjVHei<0tCh*HS<%oLZJrXOxzZ~lVdo$1>=z*S?wbtvnu z*9R<2@|6rEHT+5{lfm(_6Q z;7shP7L6mS#+37f&F?ZqB1?w9mysFN)EkCv%(|@vA)U$Z4zc7XKp)|%|6y1szTPZ) zoV?5Lf#XUJuBe|zQQ_t4AmK&T2wEfP;oekeZfoU=JwWmT?VVaqXRuyVg=x5peZ85IRS9cdIv?UGhf3RUW2hAyc zpVUbCv;%&Eiu?ZEgTAx?)Qi%=ECB&*TE?GMKTAV^adWkjEp(?)5~fAE4nb7)EBDDa zC(hyb+5ifg^X{OLh;a`1F%`06g$M8DA) z>3kRE9LxF^T~nsa16^^4Uoxa#U$`(q&nZ%yTiFE01$gk!N=UuzOUz6i#)X`7Dy6SX^N9Q1x9>%|}WH}5i^2}UEkgzi7iAyVb~f-N7*S8PT0!%}LIpZIvu zQUQS<*>VR2AWZ2QNEeu@H>sTb^N9CD|aM*$_0)Qd@F)#LYJkM{sS@Pv$7C zAfNy?xtVw^g;2E!xtg3TZJkBs;BG|TbApR}wH&-}H)Ps3AD{>5q@YtCAqi>N;_j%B zzkAnl&t!lMLuW&fLl0Qbd>54SUdvx9_r5!Mr+YGQ?g*d*~oQLTLmWkCAzgo+%=IXr7(&o?@E2iF-vsEyF^c>2~C#He;viUHZB9<$s zhk}hF9Ai{@FVK)n#a~Rr6Autd{X~M5zUB`92d1kJ+}kRZ*Q#J*oaI532YD(l(PtaA z+*OISn(*s;(ZUeO{G+d`VH8zk{s)+c4r-G{GQYn0MpITBzY?PFOl%6H*@8-O z3WIkWwj;mVS> z3Hi37);DHxa^t@E*j09F`z+Uz4_IarJ9ZR&mt%*0K>5)lJ4Sd(&6BB#`Eu^ET|UPr zV{BzT&!Od^GnuZ|Dye2txLIUt&?GxnRdag*+Sb`c5Q@2}GBTgSl!AOznV!iEqi7A` z0~PkBV57P}Bi{Uxp58^tYmw^;DxY_k#UBt7hJJ91!D=8(8}$sPdR){tyj)+H=2W|O z0*h85?W4FFe4Zn7_6DCwY)TpOu@6eVXyOG)g7!O@eTgc+HG%c+$T#TF%y~H^1Hl}Q zk-T1!p<1J#vR;Kpv%b?` zVzp-d3kO0&TVioE8T39*%c~U^+Q1gY4M$R?v72kRb4fEWs>^SD{SdA?ASb zOQN7=T)jt@hIpOoX&x?8;$AKlW7ITLFjD^u9HMKks52x?Bc(a+PU&sHg*{#bIClEa zI5)>70@vp_uF3A-o~s9QW8L2M4*ERZU_H& z9P5I3GRs}A9R!f2U^_l7fgGID-p0CgSO-Q*$r5Cf3wald`wWhEU=ACy9N;6n?OSS$ z6M_GSPelrNvKqu)-r6Yotcoi?r@6Yky|t0p4FKScj~|@dJwJ?m-oh5b^pzwVXMS3+ zF_c2M%O6?1ao2<0Ez|%R){2Qwz4f}9nwqAjrsn2>*OxxY`M?ClK|zKl z%f&z+`{6)e*pvNibAzj!j_N;*W+q3A=0+ESRc|hv#F{SmGoxbzFXiKlrAoq?uo``g z2>UcBca$KO8F$4v1b>?I^YicQ?99*4TlGe10)&;yN*CuC&dkkMuWMH&)r_xWN2^Xn zSc)ncI4$o%%lEg;z@EUPBt@8qVPZZ&_+kr#AYA}@vAx{d*mF8_$tm5?=UKPB?Av&G z6?omaeUsX_jG{4LO-|{MeqK@P^m1rrLzsBL%$b^0Kd3k{}TO z=J3$=RYGmj9~_?BUuuHgal_MuZOg7seoRVMAE5aOz9T(7vVcxu1f|mZmivB%sN|@l)N~Y(7iYs>*7!H;^?!>fAl`ZBPM5V z-hGWU&(fzbcPavgjN4p%1Kr^cFdv{;CW&_VZt(#l<5N>p<1!sN3izj$(GJL=N9TtI zOhy_4KZoa@^)*p0Q2Q+{dcMtr{FIcB`0^{M<4a>|bB%Cx^gZZMjXwA_$%I^yg$=^f z{E}m4oT!=zV(cylBP-$u4Y0Um3=do!jY-^G&KObrlo*LR73Lw%VeZqcRw)Q?%wn#jQHb^OKU|G)=_>L5Tq=m<gj;+>foSW;B_0iW5&Lu8iZENpz_V4q#jHR}KDNF+088OTX zumb(Z>ZY63xl|HxfqXWPXM79V@aiu>g(8a<+A5EY_B|CQmJ};kB%7@xiTw)=M zqvDEEt-E(N&m^D-BZ7l^IV^FsPwnq%*eQ&}h)kLoAP-~WO~3%8oJ^&h9dBreIemN; z&LOuXhmhbkiH*LHk11Zd3mp*j$_7>)^li@&oUxF#BCODo2<{S{S|NEn26a|qBfeJ; z4hdr@g5;Jwm4_V=&07fZ)b0k1Vt&mD{C||}VKLJRF8dc`1h5#1dQ$p+v%E)TiDQD& zuz4my2o0CAF1QA4`Zyfpu)GoLrAks&Q9=oJ!xZnAr0UpwOy-2H@vsb2>+yfi`+l^6 zBoZ(1&*Frxtmfr!^hGQvrv0eh#@xY8N`@pIA@r(;P!6`J1mI;e9J2Jp|9`1k!H^ub z*+-g1buUdR{)PJ=0VBM_cRmu@Z{!MwN$~rZ_{Fx1-pBdR7{}M36vjx{Gliw$cA7HRHt{q;;4L?sFa)cFllc;`VsrUfbcddC zu%}WJ3?2eYl#@4OF{>0re4h=$Ay31v&^r*^yx8#&3J7-4UpCMQ1SQ>4bETWIB&z4E z`nZLTec^+8O-GyD8|D9~SqmlVzrk$s^9PWsj28UEEZY|`-$xkEOes0sG9klDZ3FVp zDuvwJuX3tgq+uj-Fo~QdDWJ`HbDTfZW?Fq}$NY;3|EG#$>70kL-13;XqLOj8gh{ag z3j1q0t&ti&g|TvJyVxctl`RRQ@&XbZYkC@!T~~ca!vH_k4K;fvnFrV+LeRwXiBgu4 zOTj?o&fhtE6gs@4I!(p1%yXjCTr+45#Di`7)#K>>VkON)|8&r;{OJ1}WBo_B(g1GkY~a&;h%bpEhjA$;9_bqoXrt!->wJa7_~NF+ zrx*K#IHL09vl)!3uvIhxn+hIK#y*2H6xdhwk9Q9*4Oq|Ne> z;4?1WnZoP~CGf(@?BxCjF1+PefOH#5?Ia~Y+uO5QkJ9RTDgw=EIUO9JF!zunOl`*b z@Kmfd3=|Aqe7SFDh{gM*4a?#1?Z8?SEsxP88%~l2VS|qTgI63C3{JC%Niv)Kdixzc z9~TZn;AHSE7Ej;^N4J=iDqXj^1l^hh6K^P{me;p#z!%E>KV+5!imWxIPxpc39C?D^?s5 zdfV6WsSfxPw{p6DaEZmPwMI&DEv?x+O~-JitS;=X5ClT(%Eeh8;)3ur3+|`IB2!9h zX}b$~hqOJvX#0H8mIu|7StELS`+C{C+1WVQIM_KjI5~>hiVKPgiVBMgi*eF3D2h&4 z;Tenu2hKM7&veWniv(nV!Lrsk;~%6!Jw~k`sxiyU5nb`|2~uVjmB&%XQA1JX+vVFC z+mF2;gfJ1x2jTR6w|CpFe-j7h}!Nji>4fFI5>?<65sj9(6oUSwG(yb4p{2cC;rW<79b@+lk#O zq$;<2RL{hlGRWke=WCd@_YOzbh70!l_>20~hgYy2qRWrx|C#ocwf| zx%i&&KN06_%gM<(KHmOb$?2^f_+_`vV{?oKbjI7e?`1M7zu(SFIeNgC#ksI0PbU2^ z7s(`K(*uyTFRU!#)>>=Xz$$@}NCGxKeJOa1Axe;jg4c?R)w{Sn7adeOX1O9x7A5tS z5<&CBj7>v(6VT@WcQ*bUNoMeEHxcvj(dXwTTCJFF^_#)e97rAqzqXn??7M@UZNVo< zKBb0%k?%tjc@PbaZbrKB%o8Gk53Q}OpUoEoF8Iq&8XQsMrcLklloATF=hxF1`h^W; z2FA7Zn3LnfCiCo!OC3?K%Is8)J)P&{OEgh1Bg@yQ!XlN$?;rEP;A^@6bHQ`3S;Cd| z4eYr&`M*x<;~z(c{LCnj)@r=^g}g88v_ zl{tcOt1i?L=Q$hwP zvuoF>{QiCGR|n*Qono5}-2S1MdM02E8#UB~nLduz9e2~YY>6w_;EtXxQlC<@d%D;_ zQ4Hbzy%q%$h%3w~UTe*B9#(gw*{Wn#X?V@`e@%#2W)9m%B$FAB&5)KB#}bb<4EA(c zs)$ouC~vo(+uzxNBQzLiRC*FuR^wxGsv{$3T4z9IelRc?oE!U@hS(vb9~7LXq&Y1Q z6VgdxSWhJ(@v#xPV`cCL*qcMn3G`}MzLXD21$5)Gx+9dd%z;Hm)bvk#5a8?Q&u^b* zq#|lkK~HFKI|_WDFWh8+llz2(UpMcW;L?cbuw@aHN9Bl?P2;w^m{)IU^yd8)@z!?f zYXPD2VK~@&DvJZ!OC4~rA=mcDoa(?T`xZWM>n#!ey&Q`v{h~Sin1c2X85EixcQ&4 zV(HJr*HPftA3Rg|FuE24+AFjCAKhlUQwqVLb(K%_|5G;-FKLn$XgK(YZ@aZ?YqwKh z%j-x|f!p`|mo;&+c-DN-pmp(6HNtN|a!$L`&ZTGhebWC@svx2xOK+?J9vB_OyM3dD zxVl2(9zLQmly}hNOw{``81(;_6PgCDQ_F&mpuLSCoOo%)RgBN{{!Pj&FKN>?5Y@sndwj*BDBXnu?vsnP5 zC!TbMP{#oLAwPH9><(SV6gW9>5Apuf z_Z%)213vDq8$f6RKhEKGeOwQQVqiGeSPSTNaK(S70+X@~Funm27pHPg5kB^F0p7gV zMLS*^#eX#r|FWO#=G6O16KCe7EN)g{5ng!m)#77-5gA<#jwO|=`s}%kWOo$)y5c8_@NxbZ zwO5RBaQIr>Tog7nIdKoCQzqT8wcOg%{x$;-^qAgU|He6=h7XgE5L%=x)RAdFZ9?Ip5CoJubWXmkrKKX6tY)MGC62__UplrPHz< z6joDE)nfz-1zZfP?)4bT2vp(s*u5&CC{yD(JXuQuX2z?a^-^;G^)SmT?@?0Cm=irxGC+FE_pd-=w$;XI-t9E>FMx1n0EU%?xo|1W8W2jh3%&9e zRqTE@f;{A@*Hl#zG%Hd7X(t@VEyN86zJ?>$lGJwz|@z=j>bjx`|~JzmseJHklZ2>E>~_ z2A^k9@?X?EgZ>tTgN3<(y^NMd;#sDY(w{~Vsusv@YU4w9SYF!Y3v|3<)`I1zt+b;N zHdap>e@&71JZRcxlZ5ZX_D_nf~U{4mVkd+qyP_lj#> zYt7wq8#Y)DCVufnHiQOtlg~LKO4!=kwYBI1g1?}lcmDnZV}Qj4XNK45?w__o#b~@^ zGWvsQesWMkYA9kbR&lT=dx^o3m}k*c&Q@Z=JwwG3;OS0FG2V&weWMNU6o_0@;W>fH zMREr7IfntLD^!A;Hj;&8jQdn4{r4rv+(me4W3UiTJgY_s^dQ1w;+93AU7HyImL;&C z#(!5wR_UM&1P{X%XbP%58fe0^jZ1=v%77*XQMJNy+g zH8cCw_IGa9wd3UdGa3MG-35wJx~WcReO9WF*$ySBLW zzOMK+GA|wcy^ezM)^5*ScP3`xs_r5G&6_u+xMzQQtgWm-Wog;)6|hMf=W1if74w6x zgBnSen%}#}hT79Y1}I#Q9CRNDr1B2Kg3=bF&L`&2xMfY4J1}mt=hs3AGZp(~apWD) zFY@#Ajm-UA#*#kU2~EEXyg$As1-Uz;efl*s;6l`ACXrM9tE;$>9n>6}3a3hocRx!H zc0G|lCnLBs`G${|*DHL#Ee12G$eR)E`&wt(Cl5H)2+TAm2gn_$Lx53E=pb}T@O4f| z!5l}6YyFH2jz;JpBZ#l4xjd{8&--vMuIXnSbH!bs-^)iX#2a_Nnci|TnT+{$E&F)v zK)Fz$ zgmv^+K5dpzO)2vqMf)=8OmDdq{Bq-e)7D1*yA-?ozaMv@)! zy{~ibczFL)t5iajTAOv(*C>h`vOE*!dFAC>5mc+AuR2_e?wytXex9M8$SvIw{FR36 zm)~KVPUGG4q|K1MF?FG9lAavm;*EKE;Zwqq;wVloP7JL8P#$jAwJ4;MCL+YZaD04~ z=|RnMPD`rNu+l~@8vR0eCZJ(B$o*NW9d+GIVuWx53ZbzWirJm%vWR5?F}K1oZLD0O zt%mV?G3SzPv4==>^2n4u>Y>`hIT3Re%4@PbyCFRy2qS;T8GdyctUBn|6Uq58(m9`}$p7v*(p({+$e(zN0WPchRpPN?DvCSc;Z zyF37AKqyBX(Fv__9#(RmjQhSeN|Nj@QbvOLGS5NF1)ypTm;|L7vxte>Q0+o zJ~tXevcMu(=Rg;xQFq9l`2D%AQM$Jvujg>aczi0Tx>AV9^0>y$GMaob5o+7tbqVo* zw4pv5a=s}u@sI6`r#39)`o#4M+D9a}39Un$>+bBrh6@Cty0y5_No8P41IJj1sbG|_YxEFMZ&oSGOT+H-SwU$TsA{kj| z(+$4Fr)D)=be=y;%5GlDDhhf0IRY4!gOblhomOhX>fyx*kpYpY5Z_~J{>Td8{V7OL zfjut-t39e`8{7g8zO4IxJL|8rvykvUyy6jGl1>jy1S@!r2d0WY}HIp!M)>KO@vob&B%B3HY2P7R`_#L%Ql29%QGsPD$U4jUnhU zpaxE4e3>Az;w9|M0T&1)sLG-_ezs_aiMFsP1 zh3KK$s(VL3b?PM^M6Z2$NKW7bq(3$$CMGUUE0pcov#l~3J%Bpu>3v2J-3Xj}x37nE zt6CesWq}uzLEF%KE$K3B+==r}-}D4p2e|dWVdeUrj43YfxGkEey(r zFaH}bbHIX1kdS{R@4&wy?%Hv7VCH((ohoR?GUC-1C64N%C9h=q{P}ZjP0d$VUjUFI zkw{flRX;yJ!d@JJd&U5aAeWe^@^mQfuHRx0T~>(S4tt#RQBRi80-m->DR7qH>z1;+ z-;S>P1_uXwczBqYnEVSn?ZxT&s0Y6YQ(@Ss@>6%?-L3LF30u+fNz%Apc#wdLPgHrh zETAG0*(T^e7ly~#qZU{?}`IA zZSIP&xE>+u>kE1`W}+J3WzFz&2PUb-@MQ!QQAtxGa{@6JQ1@%XD4b?;v_mYHgLOXorde~$@wY8(A2%4_O}afDSAG%HT{kId+sv& zTC%#jy7e`0E3begCw-yi^|&H*@$X?`@umk_+m813E-pW}w(cNCRsi6-<*H{RbXMUs zgL~fl;fK~Wv3`gg!OZYNTy6m(k2k`KV?Ewhugif$G;N?3@m;Dx+fmL&UbqaeMK#J4 z$u00qf`I&MI0lcAt^N7CKfWP{_J67)xIef_Y5!fHtT7p?!TOl-v<4Xw+oN=u*buN2 zNKC=F6$oSQm^Sk7(8lFgRdH>oM zE6EQQJ50_g$!#WgrlzNW_*KwEziP2i<<@ZqQxb~nUk7+@DYu$T%ZQlt)j5W%H*}QL zRaI4*jCG{-#ve_Xj4A(k9O)&Ihi;sNw%1pNQrn&8KqR!8gp-ut-5eBXyL=V}}d)u&oAsjDi z%9H#tYW-%(L%lz|i7A-noD3ELTg^2CWd7}ACv9B(#=IH~W6@hJt+UxpuT<{Q2e15o zb>DP7{8HumZZUGx_3+yZ@t4hOSpkI_88z;Un6s0=MFmAE$*DY#apxgY;&ye7CU9Zm zC(40T~!(TR7XfsH2}HUH1NR$ zK0qtT9zh6yH!;U9B^5Aeksac&T1_`Ebv`S_1mpup}CnhI%Jq-bYEeEwKt+j*1Wj$5ITh47#08iH*+oy1W6uPse9mlSg zYVOmYr!fsuKR~s$_X@geAcI0j+q{vi-Nf*B_ZxI9EG|Z+e$5>e*%h|eozcDBHm|l) zl#`RY_M*2}$-G}3P~J8HndDlx#kB~|*Sgc03}VfgS2x<*XZDUA#gQ*g9@s;BxwQu= z0&L#l;5YUdg;rz*ZTGbFwfSR%nv=OG5fKqt^S}%jf;`0S6cLSqaA+O3-qZZeE?Q88 z>UR?Ci@_MSe6SUtr{6Gvi#Ugc&2IC9e5kf?b>L&l=bS_5?9;VsKym-b*C8JUUEKX60ASj zDL}Xi>%+gZAlw5^qbn;bBO@d0>gw78{wgUct*)$yiHSY-_1)_+$AjK_$|ee7$L6kK zVFAMSi}#Tqd3#yNS5$bhJ{lzFL^$wwX%Vngh(aU}F7H14`HChjp7|Xrcq78nCol|VXyUIVuqZM0XQZtAN@-QRpCjdjf{=} z0SiLOhvzNkY6z4ogzZRL2y%iCUWo+W4jk*w&JHOl>9c3gfX5ve7~tjQEh#B+fGhAV zXqz|r7cd{5ZmL9LS&%4*f;@qaao_`aD|stjD^E2~;3Q1_O_d%g8TuIdX!^XABBtl- z%v}yKcY~x2_2?Ob(sU#OvAsm|Jt;8>ge}(hkw*1P?$yrd4a71^=FB5WhuO|CJ4A{ajnyO4JH!}~BqdDXw2agdW9$ME)8K0ABYFugs*4q5dN>M&5;SeKKRf;t|27%- zwZZfz0~R4FL{D5Vf^ua)S>_(!5}0(Op*Wi!+gsh*VqeF3l z7vhzwW<#Y;rO!^XXFiY3uq7NX3RV^!B#LVJjpT3H%2XVTncSu55HZ75f?TU?!4YA=vZ+W(n#F&Jo8z{l_qAN#*L~m zB)fIPB|PozA{sO4t^olZjI^kP+JxD#!v0^6lP;oCvj3#=nbIbOOlF=&AmHod2RwX6+3mOyr@qpl-%(tZGlafaaTjG$s%8MwDQE73P^yW zMhb6iR_n1w-;)O>3s^|DmN&irJyY(Y=cy{`WpAZD{Y6rImWMph zrXj_)kVM~@1jwHN3taZ6GJhHQ7BWN!cnR`68trf9zqexchlC{p?yu$d&^wt8zqWoz zJ$BBkF;MONJ~+ks>VFB3)HXf>ew8;M9kZJ{zv@3{&x}Z3W&d_RHN!LqBM*1y+1uSC zSSa~@Z81Cec%9hm?vtaHG;YmTPXNgH^13v`?uwOcH0{A4pSUa(_En3cGB-7Ok&=8fic1Og=1oZLW-5v|2i>~T;UyjN`VFJ$ z71nB#)O@ZX4MA-rE4f6nJCkjvVGK+N62R>Yi~u-Gi?ePW*F2L<e!b_q$Dzp$d?j zPk+-9j#|K+eU^U4ia~4pIbN|aPn#HxdoCA5CgOQn6ewXUE#tq z#2gNX8k!q5?o~OrgfzCMpCKyb6cB59$am&-!}(zlGGu4&uqYuDOqei2^n+Mr1Sn#O z@H!U|Ke6T1nf}rVvOoqd)P&eh0P=8lMnPafyRfj}6|NV^Zp>2x!@416BP9-iWNboC z>qCsSr~1=qQig}szA?3H%s+eKYdlG3Tx7%BXTg2_d9d% z1Z+FYkkn&FZ5zMtAiy1n{<%YuX7&d0O8~|in1gz)_YTyPR26{Sqj*c#l@Ps%Xj#ev z5k3LHk#x>O8;O-ei7x#HmIjH<EZDR{2-G(W%B zH6!=~-p*y3^Nv5u{+@fDJr~W2J&FKp1>7wQ14oi2-?mqXK+;m?{rbS)SDdUgjj#5P zg%J@&>`b-BRZ+aHe$vtReX7-3yt+W0a%Go^WJrUdDJu1;%kvdCL^z{6PfGT>;c1Wd zAdV(4`8da^Z5d)$8-)+4-7#_i7`e7%hNj}~#IO%+bF)N>MC)<2+QBC5pC{})&5;Js zp(^6II#%EKK2e=cCD>8_l$;lBi!{5c+RS6cs|svAhik6YY$A_myd_>#;>8_tik=4| ztxsX#?S}ZhERKiq-BHrZp%~{=14HxGC}89dJ~I{y)i#Ed={J4({dwLWw`6!kuV|Oq z%-RW~;Kf6m*&J%;)D!y6w9K(~&@IH?U^*`7w_u9lvsDe~uZj@I&Y{%ZNddCjAd<|& zm3YjZ{fXN160c9m)8=|h!8j3e$6~)|HoGUYZ97))kJpK%%nKqDngyL1Kk&+&Q)`($ zO8kmO$Gt4tkc4+pN+fShHL=p#Wh}1POO&D0#B5Lx@le8@R+_xSy%sCb6>ZrP+dCjt z8vVT&RoJg}t}PA^QJwWH5ulEcuzwj@tYZ8AcuXp#IaH(O^ULwxxA&2qCen+KlcgP$#bWTXs5sEC@n2J)k~LfVPTCr8c$I$ z8|0>CSUsSyC5I%L(msTzdcH}xW%5H^Ooi9Ko+p_7<%$Z>YaR#AK6F3FJ-3st=~w#w za|Ug_OJLQPTOmTQ@0nrhUawZ8dxr z#>2d*FNbB#g$xj$`eE)&?}u;SoQnASofOP@kwaISQk;1{p(GqAYL?Qg&ePXn0`E+Q zI}RUcI8K7R#qnh;W`@s1XaZ43M5vL;MTZ_zY&^f-z)beDW|Cu^#yLHjZL^-A`$j z%@)b>{2m8~auU@DYGc#C3^sd-Vk10nb2dePh3e z56J^)*_@9Cln(Zoi73F7-N;4%Pa;V~d;(8#qY}?8|eldsVN zfk0~wPtG`lrNDbud^L79FN0qPO@;Oic%jR<&Lf&SpBvNr2fy^fAAJ12Es?nG&QI6J^lpr5% z)Ma4OuZ9X+IwqcKnHB^!1hFcKDp0#Nn2*nCP@lW*(qC48%H2{AM1 zyv)I_0CyPi3UhY{QTo9Qpv|LH`j_NYghp<(e3uZ);k?Gk*l7WB!hnyDuK>x`iuz-L z+~=nnSfc%&`@9qCLy!IZc_{SYs@^mi!vR>$5}~Cy%#8=Fp)4e9B-((dd^1B3W8njl z+I))fM}U9%a4X2>`_9hJc(!T4VlVgBK)U>N0j*(peY6L{*i`xUTQm&Yfxrv!d2b%5 z51^QXhuhH>9;q8l50ybADS6AUcke`hdmr2v^*&Ld>5h1RLV&&MbfNKiZ@@I&UTp%7 z!v57)+lXVhCa-g|Qc69>5PCZg{c48cy__fI4N|h%CzU_hwgO3Z%WQ_?Rx+MT#xdTW zOAY#IRhHJ9YOhZ?P2CXPd%YDM zhw-uX9ZwP!u&rJse@LYMSIE3IMCOBetBe^ftHagb!QJO)F%*88^HzS6a!h?q zfaO)@+NG|PQR~`v6V=@4{T^v9&;rXqlj;iXMj8YDCM(5eurO1MHedPAhES;C%SFrA z=FAO;DiihmKkM&AD7l=ZIJK>9qtzE{>Z4* z@`fhYx;?FOcKZe8iEo#5K65ZOuokjnEYQ$>LC1MbF{QcQ{1sc8BcoNdm%vm!ZQT#L z?k36u!CgxU=dCQn#!7`2Im*(l~HSvWq&nqLWfEyA#FWsK0&+5IZ zB4iGmct56%GxqHT2XzC5rtjFJjkyA5MTJK*bBai_nyRj`#H$IDH**K`x>H);QXr)~ zRU>8`i&q?k6X#ONcu$n-_`bbx_Da3Z?WFRm!m%ZsNsSXpZ=Zq0kd{y9(!18z{hu_AS zqM&vDMZbYcg#z^ z{s4Id*X-T-(4DF@aVu@N@yaucK={Fthe{`#1Zj(-Dpx*TSj8)KB(FL;k&S{dmB}f* zP6ds}d|jYrawU?hzEEXPRPbv4b}y~Ofj@dfRABJro60MFl%m6)t+Bii71@zvKnZ6> zc-r>8q4>fRxou5zGm?4>a_(+Ylo%Nxm;^Z3;&$_*0R1~U;{8u^07zc97@WWUkOp?J zICrW(b-PT}-^ANQY?;}N=3p_b#wl$yt@r1#`=^hbyIVxX%7wC0ir8Lvs!1vm4jF7;~=Zrehr6K z?+S03&7O}r4r|6$xsAcpeZZU{s&r-Jz2gu&-K>JfcXu zM=D9d$r@w>eQXkN!fC4RM)rJ+so&9lt)lu)D(o74Gq;@DClNNJ%IqyRBVp%)tn~sX zPCe{Xc;2q`s~6Oz1q;6>C8kaNBybA#Mgay2Yec#Ne>W^-!n@?I)_`)nrSN;&)Yplz zttBj2#jK*s-1Q7-5v)8mQ>4 z(N%^NLIQSb@j$1a6rC5P+?9I^v6$4B?9Vu;uy#>Y&?_MUAFd%>lw$TXr7Hx~1Qy6w zJxn^r<0U)b^c&}fhalXf!A9M z&p+%?Ez}z>$kMq8-_~gXoy@=*HbtW+IW?G8W{SX=A97^lUNTa_e0=@sT4oQB#JwK4 z>>6=A)dhK?6iV@up(=Tq)a4*lcp;2?mz{I*SK~2-A&HkAXrKa$!~jkYXaxRXsW)9& za)VmWw?v&n_ESmAga$K*;JYtIwXCevllb3P37>i1{ZPQ__G%(k{tI9h@@C9cfBD^2 zqvhPG)5T8vHr!_S$6gi_3E+I~F|P@mA5K%F5)$|h7$iO25fp^vLJJNGgz?)W+&f*cTuG23I1bKbz^< zp3D{H&L@T6#-tt`EDtYrO363n$c{=?ePz*EyMj-8B#>_)=4&Hc!Zyb@!mxQft$TD~ zR%RfwZ)FlHs-C(%DJ8PCAs61PhMtt*Q+Xxe6{z2NTkBf^wD6(q&~D}Rz<;=Gg-87T z5NjHTy^HGI>!R1?&8Pk8lFmMesJ3i%#wX@qRqg)tJxEUVXXobqPx!--`08Tc!O~3^ zQy&i2(jU^VjEpVlab035@7M4-DjE+?eQ`|LZ*H~Se0Z24{qZDzUOhp!{&?$82KJOGphT<7+rV_f_Ll?YTJaWm?(v zy9{!=ysYEt9jnW4a+-E5)44%Z=AiCkH1M_kPp_^sjN-bxzJ2^FZ^C=>YEt5S#lO-C zh$V6P1dKqh&-Yjifz8D$%8KMUF#~3{tt%LQDxU>aB+OJ*=zcY<&N5?{<%+^RK1F%g z$#izae%=d&^%Ox&ms)T9E#na=#(UoR>_(qvl8qEBY=(EL3mVF7T<7zYDKZr!aG9Wf7iKIPzb@Z(tau$D2N(D+m`**;GD5V|BtKJ=19pwzem z-Re;8Yd++!-eXzsXmK~d1X^}o@>UEHq4%bT{uPy9t%mVRgahU&L65IF69x*z;UGG1)RbTe-S=+%=i6cpr4#3kg0Z zX6P}Olbkb}`vi71b=q!D}}9z#Usj$W~rnT9Wyi9hJl5&rR89RQK# zw7td&0k`p?Ft)>xl+z6yQcejzqHCAOy#

gF4$jU(5$5I}!(bz9SL;{r_`bffy@Y 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 P00000NkvXXu0mjfYB4YX literal 0 HcmV?d00001 diff --git a/doc/salome/gui/GEOM/input/fast_intersection.doc b/doc/salome/gui/GEOM/input/fast_intersection.doc new file mode 100644 index 000000000..4de27fc29 --- /dev/null +++ b/doc/salome/gui/GEOM/input/fast_intersection.doc @@ -0,0 +1,61 @@ +/*! +\page fast_intersection_page Fast intersection + +This operation checks whether or not two selected shapes are overlapped. + +This tool is useful for fast detection of intersections and gaps. +In contrast to Boolean Operations, Partition and Detect Self-intersection +algorithms that compute topological intersections, this algoritm computes +intersections by generating tessellation (triangulation) of the source +shapes and detecting overlapping of resulting meshes. High performance is +achieved through the use of existing triangulation of faces. +Due to this fact, the tool is not suitable for computing exact intersection +of shapes; however, it can be used to quickly find zones where +intersections can present, and then use these results in further analysis. + +\note For more information about Partition and Boolean Operations Algorithms +and their limitations refer to this document. + +\image html measures12.png + +\note This dialog supports navigation through the selectable objects (in OCC 3D viewer only): +- Scroll mouse wheel with pressed \em Ctrl key or press \em "S", \em "P" keys when input focus is +in the viewer to navigate between selectable objects. +- Press left mouse button to select an appropriate object to the dialog box. +. +For more details, please refer to the \em "Functionality common for OCC and VTK viewers" chapter +of the GUI module's documentation. + +In this dialog: + +- \b Object 1 - first checked object. \b Selection button allows picking it in the viewer or in the object browser. +- \b Object 2 - second checked object. \b Selection button allows picking it in the viewer or in the object browser. +- Deflection coefficient specifies the quality of shapes tessellation. +- Detect gaps - when switched on, allows detecting gaps between shapes. +- Tolerance - specifies a distance between shapes used for detecting gaps. +- Compute intersections - press this button to compute interferences. +- Sub-shapes of Object 1 - list of sub-shapes from the first source shape that localize the intersection. +- Sub-shapes of Object 2 - list of sub-shapes from the second source shape that localize the intersection. +- \b Apply and Apply and Close buttons are used to store selected intersected shapes in the study for +further analysis (see below). + +\note Quality of the result depends on the quality of triangulation. Changing a value of the deflection coefficient +parameter can strongly affect the result. On the other hand, small values of deflection coefficient might lead to +some performance loss of the algorithm, as number of triangles of the tesselation mesh depends on this parameter. + +It is possible to store sub-shapes selected by the user in the study, for the further analysis. +The selection will be published as a compound containing intersected sub-shapes from both source objects. + +TUI Command: geompy.FastIntersect(theShape1, theShape2, theTolerance = 0.0, theDeflection = 0.001), \n +where: +- \em theShape1 First shape. +- \em theShape2 Second shape. +- \em theTolerance When it is negative or equal to zero, the function detects intersections; + when it is positive, the function detects gaps. +- \em theDeflection Linear deflection for shapes; if deflection <= 0, default deflection 0.001 is used + +Result: Boolean + two lists of IDs of sub-shapes (from input shapes) that localize the intersection. + +See also a \ref tui_fast_intersection_page "TUI example". + +*/ \ No newline at end of file diff --git a/doc/salome/gui/GEOM/input/tui_fast_intersection.doc b/doc/salome/gui/GEOM/input/tui_fast_intersection.doc new file mode 100644 index 000000000..05708da41 --- /dev/null +++ b/doc/salome/gui/GEOM/input/tui_fast_intersection.doc @@ -0,0 +1,6 @@ +/*! + +\page tui_fast_intersection_page Fast intersection +\tui_script{fast_intersection.py} + +*/ diff --git a/doc/salome/gui/GEOM/input/tui_measurement_tools.doc b/doc/salome/gui/GEOM/input/tui_measurement_tools.doc index 583f3de0f..6e83325c3 100644 --- a/doc/salome/gui/GEOM/input/tui_measurement_tools.doc +++ b/doc/salome/gui/GEOM/input/tui_measurement_tools.doc @@ -19,6 +19,7 @@

  • \subpage tui_check_compound_of_blocks_page
  • \subpage tui_get_non_blocks_page
  • \subpage tui_check_self_intersections_page
  • +
  • \subpage tui_fast_intersection_page
  • */ diff --git a/doc/salome/gui/GEOM/input/tui_test_measures.doc b/doc/salome/gui/GEOM/input/tui_test_measures.doc index 90dafb538..b954b7f60 100644 --- a/doc/salome/gui/GEOM/input/tui_test_measures.doc +++ b/doc/salome/gui/GEOM/input/tui_test_measures.doc @@ -14,9 +14,12 @@ \until CheckShape \anchor swig_CheckShape -\until MakeCompound +\until Detect Self-intersections \anchor swig_CheckSelfIntersections +\until Detect Fast intersection + +\anchor swig_FastIntersection \until WhatIs \anchor swig_WhatIs diff --git a/doc/salome/gui/GEOM/input/using_measurement_tools.doc b/doc/salome/gui/GEOM/input/using_measurement_tools.doc index 40e38c664..2672156cd 100644 --- a/doc/salome/gui/GEOM/input/using_measurement_tools.doc +++ b/doc/salome/gui/GEOM/input/using_measurement_tools.doc @@ -29,6 +29,7 @@
  • \subpage check_compound_of_blocks_page "Check compound of blocks"
  • \subpage get_non_blocks_page "Get non blocks"
  • \subpage check_self_intersections_page "Detect Self-intersections"
  • +
  • \subpage fast_intersection_page "Fast intersection"
  • \n Our TUI Scripts show how to use diff --git a/idl/GEOM_Gen.idl b/idl/GEOM_Gen.idl index 78e9bfca2..6a38a71db 100644 --- a/idl/GEOM_Gen.idl +++ b/idl/GEOM_Gen.idl @@ -4330,6 +4330,26 @@ module GEOM in long theCheckLevel, out ListOfLong theIntersections); + /*! + * \brief Detect intersections of the given shapes with algorithm based on mesh intersections. + * \param theShape1 First source object + * \param theShape2 Second source object + * \param theTolerance Specifies a distance between shapes used for detecting gaps: + * - if \a theTolerance <= 0, algorithm detects intersections + * - if \a theTolerance > 0, algorithm detects gaps + * \param theDeflection Linear deflection coefficient that specifies quality of tesselation: + * - if \a theDeflection <= 0, default deflection 0.001 is used + * \param theIntersections1 Output: contains list of sub-shapes IDs from 1st shape that localize intersection + * \param theIntersections2 Output: contains list of sub-shapes IDs from 2nd shape that localize intersection + * \return TRUE, if the are intersections (gaps) between source shapes + */ + boolean FastIntersect (in GEOM_Object theShape1, + in GEOM_Object theShape2, + in double theTolerance, + in float theDeflection, + out ListOfLong theIntersections1, + out ListOfLong theIntersections2); + /*! * \brief Check if the given shape can be an argument for MakeSolid operation * \param theShape Shape to be described. diff --git a/resources/CMakeLists.txt b/resources/CMakeLists.txt index 60ea6bd8a..c555dbd48 100755 --- a/resources/CMakeLists.txt +++ b/resources/CMakeLists.txt @@ -259,6 +259,7 @@ SET( _res_files check_blocks_compound.png get_non_blocks.png check_self_intersections.png + fast_intersect.png free_faces.png propagate.png redo.png diff --git a/resources/fast_intersect.png b/resources/fast_intersect.png new file mode 100644 index 0000000000000000000000000000000000000000..736adde330afcdea091e81574c170549bebfbb38 GIT binary patch literal 814 zcmV+}1JV46P)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D02p*dSaefwW^{L9 za%BK;VQFr3E^cLXAT%y8E;9S!r^WyP0-s4lK~y+TV;Ew((y@Bl{Exb`h<>68DX;FP|9tO=cO zMUr|yYUj-T?^Lz^e{|QL|Ao_!{BtUqHIc=q&>m(f3Sf<>Ny0FU2+SJa`JXAcA`fZ| z1aNp|$+IT+f54^zFHY|J&kQm!y7@ZL7)FR`Ag{)E?8d5r0A`78`_G)%1HnFd&S2Bb zV!J~1@)!PB$eQ_ID0LFh)?Tcd(J{~w2*ZGwDY9W5*ueDk`3lpgKm0Rm*3V0F-~RXi@#FvhpE>jY|KWAd|1X+&9d2Mn$4OKJ!)s?i&4Pfowi5*)uUKc# z{clmY^nXg{k^ftEegYc?GIZOvfB)BZoknq`Li$v&VN9{D_ZaL$d7wr?KvYz_pkdD3 z=WOXyfUyX{!r9aRw=cf@f6t!(|CcZS@_#DOh+z}$ij0MpeR zWCKB%J#F&;;tA)$vENj=?cvnw?K6RqxVgXo%IVIob5Hm}s(PW?F#&5}sS#W1#NX(K z3IK6kp`OW8CP9^u4p;)p%)r?(W#V73feD@G#r0gd sq0$rpT^m6LbAJUOiwPn?cfh~^02tB|?lFn4{Qv*}07*qoM6N<$f-LKn&j0`b literal 0 HcmV?d00001 diff --git a/src/GEOMGUI/GEOM_images.ts b/src/GEOMGUI/GEOM_images.ts index 43fa10a06..6877d9c7c 100644 --- a/src/GEOMGUI/GEOM_images.ts +++ b/src/GEOMGUI/GEOM_images.ts @@ -255,6 +255,10 @@ ICON_DLG_CHECK_SELF_INTERSECTIONS check_self_intersections.png + + ICON_DLG_FAST_CHECK_INTERSECTIONS + fast_intersect.png + ICON_DLG_CIRCLE_PNTS circle3points.png @@ -883,6 +887,10 @@ ICO_CHECK_SELF_INTERSECTIONS check_self_intersections.png + + ICO_FAST_CHECK_INTERSECTIONS + fast_intersect.png + ICO_CHECK_FREE_BNDS free_bound.png diff --git a/src/GEOMGUI/GEOM_msg_en.ts b/src/GEOMGUI/GEOM_msg_en.ts index 45b178e5e..86e1622a7 100644 --- a/src/GEOMGUI/GEOM_msg_en.ts +++ b/src/GEOMGUI/GEOM_msg_en.ts @@ -423,6 +423,10 @@ Please, select face, shell or solid and try again GEOM_CHECK_SELF_INTERSECTIONS Detect Self-intersections + + GEOM_FAST_CHECK_INTERSECTIONS + Fast intersection + GEOM_CIRCLE Circle @@ -2500,6 +2504,10 @@ Please, select face, shell or solid and try again MEN_CHECK_SELF_INTERSECTIONS Detect Self-intersections + + MEN_FAST_CHECK_INTERSECTIONS + Fast intersection + MEN_CHECK_FREE_BNDS Check Free Boundaries @@ -3505,6 +3513,10 @@ Please, select face, shell or solid and try again Detect Self-intersections + STB_FAST_CHECK_INTERSECTIONS + Fast intersection + + STB_CHECK_FREE_BNDS Check free boundaries @@ -4116,6 +4128,10 @@ Please, select face, shell or solid and try again TOP_CHECK_SELF_INTERSECTIONS Detect Self-intersections + + TOP_FAST_CHECK_INTERSECTIONS + Fast intersection + TOP_CHECK_FREE_BNDS Check free boundaries @@ -7138,6 +7154,37 @@ Do you want to create new material? All interferences + + MeasureGUI_FastCheckIntersectionsDlg + + GEOM_FAST_CHECK_INT_DEFLECT + Deflection coefficient + + + GEOM_FAST_CHECK_INT_DETECT_GAPS + Detect gaps with tolerance + + + GEOM_FAST_CHECK_INT_SUBSHAPES + Sub-shapes of Object %1: + + + GEOM_FAST_CHECK_INT_COMPUTE + Compute intersections + + + GEOM_FAST_INTERSECTION_NAME + Fast_intersection + + + GEOM_FAST_INTERSECTION_FAILS + No intersections + + + GEOM_FAST_CHECK_OBJ + Objects And Results + + TransformationGUI_ExtensionDlg diff --git a/src/GEOMGUI/GEOM_msg_fr.ts b/src/GEOMGUI/GEOM_msg_fr.ts index 0d42a5b67..62edf1628 100644 --- a/src/GEOMGUI/GEOM_msg_fr.ts +++ b/src/GEOMGUI/GEOM_msg_fr.ts @@ -431,6 +431,10 @@ Choisissez une face, une coque ou un solide et essayez de nouveau GEOM_CHECK_SELF_INTERSECTIONS Détecter les auto-intersections + + GEOM_FAST_CHECK_INTERSECTIONS + Fast intersection + GEOM_CHECK_SELF_INTERSECTIONS_FAILED La détection d'auto-intersections a échoué @@ -2464,6 +2468,10 @@ Choisissez une face, une coque ou un solide et essayez de nouveau MEN_CHECK_SELF_INTERSECTIONS Détections des auto-intersections + + MEN_FAST_CHECK_INTERSECTIONS + Fast intersection + MEN_CHECK_FREE_BNDS Contrôler les contours libres @@ -3452,6 +3460,10 @@ Choisissez une face, une coque ou un solide et essayez de nouveau STB_CHECK_SELF_INTERSECTIONS Détecte les auto-intersections + + STB_FAST_CHECK_INTERSECTIONS + Fast intersection + STB_CHECK_FREE_BNDS Vérifier les contours libres @@ -4060,6 +4072,10 @@ Choisissez une face, une coque ou un solide et essayez de nouveau TOP_CHECK_SELF_INTERSECTIONS Détection des auto-intersections + + TOP_FAST_CHECK_INTERSECTIONS + Fast intersection + TOP_CHECK_FREE_BNDS Valider les contours libres @@ -6999,4 +7015,160 @@ Voulez-vous en créer un nouveau ? V-Isoligne + + MeasureGUI_CheckSelfIntersectionsDlg + + GEOM_CHECK_INTE_INTERSECTIONS + Self-intersections + + + GEOM_CHECK_INTE_SUBSHAPES + Sub-shapes + + + GEOM_CHECK_INTE_CHECK_LEVEL + Level of check + + + GEOM_CHECK_INTE_SUMMARY + Summary + + + GEOM_CHECK_INTE_COMPUTE + Compute self-intersections + + + GEOM_SELF_INTERSECTION_NAME + Self_intersection + + + GEOM_NO_SELF_INTERSECTIONS + There are no self-intersections in the shape + + + GEOM_SELF_INTERSECTIONS_FOUND + Some self-intersections detected + + + GEOM_CHECK_SELF_INTERSECTIONS_FAILED + Detection of self-intersections failed + + + GEOM_CHECK_SELF_INTERSECTIONS_ERRORS + Warning: there were errors during the operation, so the list may be incomplete. + + + GEOM_CHECK_INTE_V_V + Vertex to Vertex + + + GEOM_CHECK_INTE_V_E + Vertex to Edge + all above + + + GEOM_CHECK_INTE_E_E + Edge to Edge + all above + + + GEOM_CHECK_INTE_V_F + Vertex to Face + all above + + + GEOM_CHECK_INTE_E_F + Edge to Face + all above + + + GEOM_CHECK_INTE_ALL + All interferences + + + + MeasureGUI_FastCheckIntersectionsDlg + + GEOM_FAST_CHECK_INT_DEFLECT + Deflection coefficient + + + GEOM_FAST_CHECK_INT_DETECT_GAPS + Detect gaps with tolerance + + + GEOM_FAST_CHECK_INT_SUBSHAPES + Sub-shapes of Object %1: + + + GEOM_FAST_CHECK_INT_COMPUTE + Compute intersections + + + GEOM_FAST_INTERSECTION_NAME + Fast_intersection + + + GEOM_FAST_INTERSECTION_FAILS + No intersections + + + GEOM_FAST_CHECK_OBJ + Objects And Results + + + + TransformationGUI_ExtensionDlg + + GEOM_EXTENSION_TITLE + Extension of Edge or Face + + + GEOM_EXTENSION + Extension + + + GEOM_EXTENSION_MIN + First Parameter + + + GEOM_EXTENSION_MAX + Last Parameter + + + GEOM_EXTENSION_MIN_U + First U-Parameter + + + GEOM_EXTENSION_MAX_U + Last U-Parameter + + + GEOM_EXTENSION_MIN_V + First V-Parameter + + + GEOM_EXTENSION_MAX_V + Last V-Parameter + + + GEOM_EXTENSION_EDGE_NAME + ExtendedEdge + + + GEOM_EXTENSION_FACE_NAME + ExtendedFace + + + + EntityGUI_SurfFromFaceDlg + + GEOM_SURF_FROM_FACE_TITLE + Surface From Face Construction + + + GEOM_SURF_FROM_FACE + Surface From Face + + + GEOM_SURF_FROM_FACE_NAME + SurfaceFromFace + + diff --git a/src/GEOMGUI/GEOM_msg_ja.ts b/src/GEOMGUI/GEOM_msg_ja.ts index d7d25aab4..8ef05204b 100644 --- a/src/GEOMGUI/GEOM_msg_ja.ts +++ b/src/GEOMGUI/GEOM_msg_ja.ts @@ -411,6 +411,10 @@ GEOM_CHECK_SELF_INTERSECTIONS 自己交差の検出 + + GEOM_FAST_CHECK_INTERSECTIONS + Fast intersection + GEOM_CHECK_SELF_INTERSECTIONS_FAILED 自己交差の検出に失敗しました @@ -2447,6 +2451,10 @@ MEN_CHECK_SELF_INTERSECTIONS 自己交差の確認 + + MEN_FAST_CHECK_INTERSECTIONS + Fast intersection + MEN_CHECK_FREE_BNDS 自由境界の確認 @@ -3439,6 +3447,10 @@ STB_CHECK_SELF_INTERSECTIONS 自己交差の確認 + + STB_FAST_CHECK_INTERSECTIONS + Fast intersection + STB_CHECK_FREE_BNDS 自由境界をチェック @@ -4047,6 +4059,10 @@ TOP_CHECK_SELF_INTERSECTIONS 自己交差の確認 + + TOP_FAST_CHECK_INTERSECTIONS + Fast intersection + TOP_CHECK_FREE_BNDS 自由境界を確認 @@ -6976,4 +6992,160 @@ V-Isoline + + MeasureGUI_CheckSelfIntersectionsDlg + + GEOM_CHECK_INTE_INTERSECTIONS + Self-intersections + + + GEOM_CHECK_INTE_SUBSHAPES + Sub-shapes + + + GEOM_CHECK_INTE_CHECK_LEVEL + Level of check + + + GEOM_CHECK_INTE_SUMMARY + Summary + + + GEOM_CHECK_INTE_COMPUTE + Compute self-intersections + + + GEOM_SELF_INTERSECTION_NAME + Self_intersection + + + GEOM_NO_SELF_INTERSECTIONS + There are no self-intersections in the shape + + + GEOM_SELF_INTERSECTIONS_FOUND + Some self-intersections detected + + + GEOM_CHECK_SELF_INTERSECTIONS_FAILED + Detection of self-intersections failed + + + GEOM_CHECK_SELF_INTERSECTIONS_ERRORS + Warning: there were errors during the operation, so the list may be incomplete. + + + GEOM_CHECK_INTE_V_V + Vertex to Vertex + + + GEOM_CHECK_INTE_V_E + Vertex to Edge + all above + + + GEOM_CHECK_INTE_E_E + Edge to Edge + all above + + + GEOM_CHECK_INTE_V_F + Vertex to Face + all above + + + GEOM_CHECK_INTE_E_F + Edge to Face + all above + + + GEOM_CHECK_INTE_ALL + All interferences + + + + MeasureGUI_FastCheckIntersectionsDlg + + GEOM_FAST_CHECK_INT_DEFLECT + Deflection coefficient + + + GEOM_FAST_CHECK_INT_DETECT_GAPS + Detect gaps with tolerance + + + GEOM_FAST_CHECK_INT_SUBSHAPES + Sub-shapes of Object %1: + + + GEOM_FAST_CHECK_INT_COMPUTE + Compute intersections + + + GEOM_FAST_INTERSECTION_NAME + Fast_intersection + + + GEOM_FAST_INTERSECTION_FAILS + No intersections + + + GEOM_FAST_CHECK_OBJ + Objects And Results + + + + TransformationGUI_ExtensionDlg + + GEOM_EXTENSION_TITLE + Extension of Edge or Face + + + GEOM_EXTENSION + Extension + + + GEOM_EXTENSION_MIN + First Parameter + + + GEOM_EXTENSION_MAX + Last Parameter + + + GEOM_EXTENSION_MIN_U + First U-Parameter + + + GEOM_EXTENSION_MAX_U + Last U-Parameter + + + GEOM_EXTENSION_MIN_V + First V-Parameter + + + GEOM_EXTENSION_MAX_V + Last V-Parameter + + + GEOM_EXTENSION_EDGE_NAME + ExtendedEdge + + + GEOM_EXTENSION_FACE_NAME + ExtendedFace + + + + EntityGUI_SurfFromFaceDlg + + GEOM_SURF_FROM_FACE_TITLE + Surface From Face Construction + + + GEOM_SURF_FROM_FACE + Surface From Face + + + GEOM_SURF_FROM_FACE_NAME + SurfaceFromFace + + diff --git a/src/GEOMGUI/GeometryGUI.cxx b/src/GEOMGUI/GeometryGUI.cxx index a8e6f6bca..883347659 100644 --- a/src/GEOMGUI/GeometryGUI.cxx +++ b/src/GEOMGUI/GeometryGUI.cxx @@ -638,6 +638,7 @@ void GeometryGUI::OnGUIEvent( int id, const QVariant& theParam ) case GEOMOp::OpGetNonBlocks: // MENU MEASURE - Get NON BLOCKS case GEOMOp::OpPointCoordinates: // MENU MEASURE - POINT COORDINATES case GEOMOp::OpCheckSelfInters: // MENU MEASURE - CHECK SELF INTERSECTIONS + case GEOMOp::OpFastCheckInters: // MENU MEASURE - FAST CHECK INTERSECTIONS case GEOMOp::OpManageDimensions: // MENU MEASURE - MANAGE DIMENSIONS case GEOMOp::OpShowAllDimensions: // POPUP MENU - SHOW ALL DIMENSIONS case GEOMOp::OpHideAllDimensions: // POPUP MENU - HIDE ALL DIMENSIONS @@ -1016,6 +1017,7 @@ void GeometryGUI::initialize( CAM_Application* app ) createGeomAction( GEOMOp::OpCheckCompound, "CHECK_COMPOUND" ); createGeomAction( GEOMOp::OpGetNonBlocks, "GET_NON_BLOCKS" ); createGeomAction( GEOMOp::OpCheckSelfInters, "CHECK_SELF_INTERSECTIONS" ); + createGeomAction( GEOMOp::OpFastCheckInters, "FAST_CHECK_INTERSECTIONS" ); #ifdef _DEBUG_ // PAL16821 createGeomAction( GEOMOp::OpCheckGeom, "CHECK_GEOMETRY" ); @@ -1273,6 +1275,7 @@ void GeometryGUI::initialize( CAM_Application* app ) createMenu( GEOMOp::OpCheckCompound, measurId, -1 ); createMenu( GEOMOp::OpGetNonBlocks, measurId, -1 ); createMenu( GEOMOp::OpCheckSelfInters, measurId, -1 ); + createMenu( GEOMOp::OpFastCheckInters, measurId, -1 ); int toolsId = createMenu( tr( "MEN_TOOLS" ), -1, -1, 50 ); #if defined(_DEBUG_) || defined(_DEBUG) // PAL16821 @@ -1420,6 +1423,7 @@ void GeometryGUI::initialize( CAM_Application* app ) createTool( GEOMOp::OpCheckCompound, measureTbId ); createTool( GEOMOp::OpGetNonBlocks, measureTbId ); createTool( GEOMOp::OpCheckSelfInters, measureTbId ); + createTool( GEOMOp::OpFastCheckInters, measureTbId ); int picturesTbId = createTool( tr( "TOOL_PICTURES" ), QString( "GEOMPictures" ) ); createTool( GEOMOp::OpPictureImport, picturesTbId ); diff --git a/src/GEOMGUI/GeometryGUI_Operations.h b/src/GEOMGUI/GeometryGUI_Operations.h index 7243340f4..8b01f7a0f 100644 --- a/src/GEOMGUI/GeometryGUI_Operations.h +++ b/src/GEOMGUI/GeometryGUI_Operations.h @@ -194,6 +194,7 @@ namespace GEOMOp { OpManageDimensions = 5014, // MENU MEASURES - MANAGE DIMENSIONS OpShowAllDimensions = 5015, // POPUP MENU - SHOW ALL DIMENSIONS OpHideAllDimensions = 5016, // POPUP MENU - HIDE ALL DIMENSIONS + OpFastCheckInters = 5017, // MENU MEASURES - FAST CHECK INTERSECTIONS // GroupGUI --------------------//-------------------------------- OpGroupCreate = 6000, // MENU GROUP - CREATE OpGroupEdit = 6001, // MENU GROUP - EDIT diff --git a/src/GEOMImpl/CMakeLists.txt b/src/GEOMImpl/CMakeLists.txt index 29436dabc..2a8896281 100755 --- a/src/GEOMImpl/CMakeLists.txt +++ b/src/GEOMImpl/CMakeLists.txt @@ -30,6 +30,7 @@ INCLUDE_DIRECTORIES( ${PROJECT_SOURCE_DIR}/src/BlockFix ${PROJECT_SOURCE_DIR}/src/GEOMAlgo ${PROJECT_SOURCE_DIR}/src/GEOMUtils + ${PROJECT_SOURCE_DIR}/src/OCC2VTK ${PROJECT_SOURCE_DIR}/src/SKETCHER ${PROJECT_SOURCE_DIR}/src/ARCHIMEDE ${PROJECT_SOURCE_DIR}/src/XAO @@ -48,7 +49,7 @@ SET(_link_LIBRARIES ${CAS_TKFeat} ${CAS_TKFillet} ${PYTHON_LIBRARIES} - ShHealOper GEOMbasic BlockFix GEOMAlgo GEOMUtils GEOMSketcher GEOMArchimede XAO + ShHealOper GEOMbasic BlockFix GEOMAlgo GEOMUtils GEOMSketcher GEOMArchimede XAO OCC2VTK ${KERNEL_SALOMELocalTrace} ) diff --git a/src/GEOMImpl/GEOMImpl_IMeasureOperations.cxx b/src/GEOMImpl/GEOMImpl_IMeasureOperations.cxx index fb2320ea5..3d7601a76 100644 --- a/src/GEOMImpl/GEOMImpl_IMeasureOperations.cxx +++ b/src/GEOMImpl/GEOMImpl_IMeasureOperations.cxx @@ -30,6 +30,7 @@ #include #include #include +#include #include @@ -48,6 +49,7 @@ #include #include #include +#include #include #include #include @@ -1575,6 +1577,88 @@ bool GEOMImpl_IMeasureOperations::CheckSelfIntersections return isGood; } +//============================================================================= +/*! + * FastIntersect + */ +//============================================================================= +bool GEOMImpl_IMeasureOperations::FastIntersect (Handle(GEOM_Object) theShape1, Handle(GEOM_Object) theShape2, + double theTolerance, float theDeflection, + Handle(TColStd_HSequenceOfInteger)& theIntersections1, + Handle(TColStd_HSequenceOfInteger)& theIntersections2) +{ + SetErrorCode(KO); + bool isGood = false; + + if (theIntersections1.IsNull()) + theIntersections1 = new TColStd_HSequenceOfInteger; + else + theIntersections1->Clear(); + + if (theIntersections2.IsNull()) + theIntersections2 = new TColStd_HSequenceOfInteger; + else + theIntersections2->Clear(); + + if (theShape1.IsNull() || theShape2.IsNull()) { + SetErrorCode("Objects have NULL Shape"); + return isGood; + } + + if (theShape1 == theShape2) { + SetErrorCode("Objects are equal"); + return isGood; + } + Handle(GEOM_Function) aRefShape1 = theShape1->GetLastFunction(); + Handle(GEOM_Function) aRefShape2 = theShape2->GetLastFunction(); + if (aRefShape1.IsNull() || aRefShape2.IsNull()) return isGood; + + TopoDS_Shape aShape1 = aRefShape1->GetValue(); + TopoDS_Shape aShape2 = aRefShape2->GetValue(); + if (aShape1.IsNull() || aShape2.IsNull()) return isGood; + + // 0. Prepare data + TopoDS_Shape aScopy1, aScopy2; + GEOMAlgo_AlgoTools::CopyShape(aShape1, aScopy1); + GEOMAlgo_AlgoTools::CopyShape(aShape2, aScopy2); + + float aDeflection = (theDeflection <= 0.) ? 0.001 : theDeflection; + GEOM::MeshShape(aScopy1, aDeflection); + GEOM::MeshShape(aScopy2, aDeflection); + // + // Map sub-shapes and their indices + TopTools_IndexedMapOfShape anIndices1, anIndices2; + TopExp::MapShapes(aScopy1, anIndices1); + TopExp::MapShapes(aScopy2, anIndices2); + + BOPCol_ListOfShape aLCS1, aLCS2; + aLCS1.Append(aScopy1); aLCS2.Append(aScopy2); + // + BRepExtrema_ShapeProximity aBSP; // checker of fast interferences + aBSP.LoadShape1(aScopy1); aBSP.LoadShape2(aScopy2); + aBSP.SetTolerance((theTolerance <= 0.) ? 0.0 : theTolerance); + + // 1. Launch the checker + aBSP.Perform(); + + // 2. Get sets of IDs of overlapped faces + for (BRepExtrema_OverlappedSubShapes::Iterator anIt1 (aBSP.OverlapSubShapes1()); anIt1.More(); anIt1.Next()) { + const TopoDS_Shape& aS1 = aBSP.GetSubShape1(anIt1.Key()); + theIntersections1->Append(anIndices1.FindIndex(aS1)); + } + + for (BRepExtrema_OverlappedSubShapes::Iterator anIt2 (aBSP.OverlapSubShapes2()); anIt2.More(); anIt2.Next()) { + const TopoDS_Shape& aS2 = aBSP.GetSubShape2(anIt2.Key()); + theIntersections2->Append(anIndices2.FindIndex(aS2)); + } + + isGood = !theIntersections1->IsEmpty() && !theIntersections1->IsEmpty(); + + if (aBSP.IsDone()) + SetErrorCode(OK); + + return isGood; +} //============================================================================= /*! * IsGoodForSolid diff --git a/src/GEOMImpl/GEOMImpl_IMeasureOperations.hxx b/src/GEOMImpl/GEOMImpl_IMeasureOperations.hxx index 3b8ae3d42..9712e33c2 100644 --- a/src/GEOMImpl/GEOMImpl_IMeasureOperations.hxx +++ b/src/GEOMImpl/GEOMImpl_IMeasureOperations.hxx @@ -157,6 +157,11 @@ class GEOMImpl_IMeasureOperations : public GEOM_IOperations { Standard_EXPORT bool CheckSelfIntersections (Handle(GEOM_Object) theShape, const SICheckLevel theCheckLevel, Handle(TColStd_HSequenceOfInteger)& theIntersections); + + Standard_EXPORT bool FastIntersect (Handle(GEOM_Object) theShape1, Handle(GEOM_Object) theShape2, + double tolerance, float deflection, + Handle(TColStd_HSequenceOfInteger)& theIntersections1, + Handle(TColStd_HSequenceOfInteger)& theIntersections2); Standard_EXPORT TCollection_AsciiString IsGoodForSolid (Handle(GEOM_Object) theShape); diff --git a/src/GEOM_I/GEOM_IMeasureOperations_i.cc b/src/GEOM_I/GEOM_IMeasureOperations_i.cc index 0d4a89eff..e8a8272a8 100644 --- a/src/GEOM_I/GEOM_IMeasureOperations_i.cc +++ b/src/GEOM_I/GEOM_IMeasureOperations_i.cc @@ -765,6 +765,59 @@ CORBA::Boolean GEOM_IMeasureOperations_i::CheckSelfIntersections (GEOM::GEOM_Obj return isGood; } +//============================================================================= +/*! + * FastIntersect + */ +//============================================================================= +CORBA::Boolean GEOM_IMeasureOperations_i::FastIntersect (GEOM::GEOM_Object_ptr theShape1, + GEOM::GEOM_Object_ptr theShape2, + CORBA::Double theTolerance, + CORBA::Float theDeflection, + GEOM::ListOfLong_out theIntersections1, + GEOM::ListOfLong_out theIntersections2) +{ + // Set a not done flag + GetOperations()->SetNotDone(); + + bool isGood = false; + + // Allocate the CORBA arrays + GEOM::ListOfLong_var anIntegersArray1 = new GEOM::ListOfLong(); + GEOM::ListOfLong_var anIntegersArray2 = new GEOM::ListOfLong(); + + // Get the reference shape + Handle(GEOM_Object) aShape1 = GetObjectImpl(theShape1); + Handle(GEOM_Object) aShape2 = GetObjectImpl(theShape2); + + if (!aShape1.IsNull() && !aShape2.IsNull()) { + Handle(TColStd_HSequenceOfInteger) anIntegers1 = new TColStd_HSequenceOfInteger; + Handle(TColStd_HSequenceOfInteger) anIntegers2 = new TColStd_HSequenceOfInteger; + + // Detect intersections + isGood = GetOperations()->FastIntersect + (aShape1, aShape2, theTolerance, theDeflection, anIntegers1, anIntegers2); + + int nbInts1 = anIntegers1->Length(); + int nbInts2 = anIntegers2->Length(); + + anIntegersArray1->length(nbInts1); + anIntegersArray2->length(nbInts2); + + for (int ii = 0; ii < nbInts1; ii++) { + anIntegersArray1[ii] = anIntegers1->Value(ii + 1); + } + for (int ii = 0; ii < nbInts2; ii++) { + anIntegersArray2[ii] = anIntegers2->Value(ii + 1); + } + } + + // Initialize out-parameters with local arrays + theIntersections1 = anIntegersArray1._retn(); + theIntersections2 = anIntegersArray2._retn(); + return isGood; +} + //============================================================================= /*! * IsGoodForSolid diff --git a/src/GEOM_I/GEOM_IMeasureOperations_i.hh b/src/GEOM_I/GEOM_IMeasureOperations_i.hh index 391de3f48..6f595d521 100644 --- a/src/GEOM_I/GEOM_IMeasureOperations_i.hh +++ b/src/GEOM_I/GEOM_IMeasureOperations_i.hh @@ -100,6 +100,13 @@ class GEOM_I_EXPORT GEOM_IMeasureOperations_i : CORBA::Long theCheckLevel, GEOM::ListOfLong_out theIntersections); + CORBA::Boolean FastIntersect (GEOM::GEOM_Object_ptr theShape1, + GEOM::GEOM_Object_ptr theShape2, + CORBA::Double theTolerance, + CORBA::Float theDeflection, + GEOM::ListOfLong_out theIntersections1, + GEOM::ListOfLong_out theIntersections2); + char* IsGoodForSolid (GEOM::GEOM_Object_ptr theShape); char* WhatIs (GEOM::GEOM_Object_ptr theShape); diff --git a/src/GEOM_SWIG/GEOM_TestMeasures.py b/src/GEOM_SWIG/GEOM_TestMeasures.py index 2aed6d6a5..22657306d 100644 --- a/src/GEOM_SWIG/GEOM_TestMeasures.py +++ b/src/GEOM_SWIG/GEOM_TestMeasures.py @@ -56,6 +56,12 @@ def TestMeasureOperations (geompy, math): if geompy.CheckSelfIntersections(Compound_1) == True: raise RuntimeError, "Existing self-intersection is not detected" + ####### Detect Fast intersection ####### + + cylinder = geompy.MakeCylinderRH(100, 300) + if geompy.FastIntersect(box, cylinder) == False: + raise RuntimeError, "Existing intersection is not detected" + ####### WhatIs ####### Descr = geompy.WhatIs(box) diff --git a/src/GEOM_SWIG/geomBuilder.py b/src/GEOM_SWIG/geomBuilder.py index b5e1ca808..fd3cecc0e 100755 --- a/src/GEOM_SWIG/geomBuilder.py +++ b/src/GEOM_SWIG/geomBuilder.py @@ -4869,7 +4869,7 @@ class geomBuilder(object, GEOM._objref_GEOM_Gen): # @param theShape Shape to find free faces in. # @return List of IDs of all free faces, contained in theShape. # - # @ref tui_measurement_tools_page "Example" + # @ref tui_free_faces_page "Example" @ManageTransactions("ShapesOp") def GetFreeFacesIDs(self,theShape): """ @@ -7000,7 +7000,7 @@ class geomBuilder(object, GEOM._objref_GEOM_Gen): # \n \a theClosedWires: Closed wires on the free boundary of the given shape. # \n \a theOpenWires: Open wires on the free boundary of the given shape. # - # @ref tui_measurement_tools_page "Example" + # @ref tui_free_boundaries_page "Example" @ManageTransactions("HealOp") def GetFreeBoundary(self, theObject, theName=None): """ @@ -10008,7 +10008,7 @@ class geomBuilder(object, GEOM._objref_GEOM_Gen): ## Get point coordinates # @return [x, y, z] # - # @ref tui_measurement_tools_page "Example" + # @ref tui_point_coordinates_page "Example" @ManageTransactions("MeasuOp") def PointCoordinates(self,Point): """ @@ -10084,7 +10084,7 @@ class geomBuilder(object, GEOM._objref_GEOM_Gen): # theSurfArea: Area of surface of the given shape.\n # theVolume: Volume of the given shape. # - # @ref tui_measurement_tools_page "Example" + # @ref tui_basic_properties_page "Example" @ManageTransactions("MeasuOp") def BasicProperties(self,theShape): """ @@ -10113,7 +10113,7 @@ class geomBuilder(object, GEOM._objref_GEOM_Gen): # Ymin,Ymax: Limits of shape along OY axis. # Zmin,Zmax: Limits of shape along OZ axis. # - # @ref tui_measurement_tools_page "Example" + # @ref tui_bounding_box_page "Example" @ManageTransactions("MeasuOp") def BoundingBox (self, theShape, precise=False): """ @@ -10143,7 +10143,7 @@ class geomBuilder(object, GEOM._objref_GEOM_Gen): # # @return New GEOM.GEOM_Object, containing the created box. # - # @ref tui_measurement_tools_page "Example" + # @ref tui_bounding_box_page "Example" @ManageTransactions("MeasuOp") def MakeBoundingBox (self, theShape, precise=False, theName=None): """ @@ -10171,7 +10171,7 @@ class geomBuilder(object, GEOM._objref_GEOM_Gen): # I(1-3)(1-3): Components of the inertia matrix of the given shape. # Ix,Iy,Iz: Moments of inertia of the given shape. # - # @ref tui_measurement_tools_page "Example" + # @ref tui_inertia_page "Example" @ManageTransactions("MeasuOp") def Inertia(self,theShape): """ @@ -10214,7 +10214,7 @@ class geomBuilder(object, GEOM._objref_GEOM_Gen): # @param theShape1,theShape2 Shapes to find minimal distance between. # @return Value of the minimal distance between the given shapes. # - # @ref tui_measurement_tools_page "Example" + # @ref tui_min_distance_page "Example" @ManageTransactions("MeasuOp") def MinDistance(self, theShape1, theShape2): """ @@ -10236,7 +10236,7 @@ class geomBuilder(object, GEOM._objref_GEOM_Gen): # @return Value of the minimal distance between the given shapes, in form of list # [Distance, DX, DY, DZ]. # - # @ref swig_all_measure "Example" + # @ref tui_min_distance_page "Example" @ManageTransactions("MeasuOp") def MinDistanceComponents(self, theShape1, theShape2): """ @@ -10260,7 +10260,7 @@ class geomBuilder(object, GEOM._objref_GEOM_Gen): # @return The number of found solutions (-1 in case of infinite number of # solutions) and a list of (X, Y, Z) coordinates for all couples of points. # - # @ref tui_measurement_tools_page "Example" + # @ref tui_min_distance_page "Example" @ManageTransactions("MeasuOp") def ClosestPoints (self, theShape1, theShape2): """ @@ -10284,7 +10284,7 @@ class geomBuilder(object, GEOM._objref_GEOM_Gen): # with their orientations, otherwise the minimum angle is computed. # @return Value of the angle between the given shapes in degrees. # - # @ref tui_measurement_tools_page "Example" + # @ref tui_angle_page "Example" @ManageTransactions("MeasuOp") def GetAngle(self, theShape1, theShape2): """ @@ -10311,7 +10311,7 @@ class geomBuilder(object, GEOM._objref_GEOM_Gen): # with their orientations, otherwise the minimum angle is computed. # @return Value of the angle between the given shapes in radians. # - # @ref tui_measurement_tools_page "Example" + # @ref tui_angle_page "Example" @ManageTransactions("MeasuOp") def GetAngleRadians(self, theShape1, theShape2): """ @@ -10339,7 +10339,7 @@ class geomBuilder(object, GEOM._objref_GEOM_Gen): # if False, the opposite vector to the normal vector is used. # @return Value of the angle between the given vectors in degrees. # - # @ref tui_measurement_tools_page "Example" + # @ref tui_angle_page "Example" @ManageTransactions("MeasuOp") def GetAngleVectors(self, theShape1, theShape2, theFlag = True): """ @@ -10532,7 +10532,7 @@ class geomBuilder(object, GEOM._objref_GEOM_Gen): # EdgeMin,EdgeMax: Min and max tolerances of the edges.\n # VertMin,VertMax: Min and max tolerances of the vertices. # - # @ref tui_measurement_tools_page "Example" + # @ref tui_tolerance_page "Example" @ManageTransactions("MeasuOp") def Tolerance(self,theShape): """ @@ -10556,7 +10556,7 @@ class geomBuilder(object, GEOM._objref_GEOM_Gen): # @param theShape Shape to be described. # @return Description of the given shape. # - # @ref tui_measurement_tools_page "Example" + # @ref tui_whatis_page "Example" @ManageTransactions("MeasuOp") def WhatIs(self,theShape): """ @@ -10643,7 +10643,7 @@ class geomBuilder(object, GEOM._objref_GEOM_Gen): # # @return New GEOM.GEOM_Object, containing the created point. # - # @ref tui_measurement_tools_page "Example" + # @ref tui_center_of_mass_page "Example" @ManageTransactions("MeasuOp") def MakeCDG(self, theShape, theName=None): """ @@ -10789,7 +10789,7 @@ class geomBuilder(object, GEOM._objref_GEOM_Gen): # @return If theReturnStatus is equal to 1 the description is returned. # Otherwise doesn't return anything. # - # @ref tui_measurement_tools_page "Example" + # @ref tui_check_shape_page "Example" @ManageTransactions("MeasuOp") def PrintShapeErrors(self, theShape, theShapeErrors, theReturnStatus = 0): """ @@ -10829,7 +10829,7 @@ class geomBuilder(object, GEOM._objref_GEOM_Gen): # If theReturnStatus is equal to 2 the list of error data is # returned along with IsValid flag. # - # @ref tui_measurement_tools_page "Example" + # @ref tui_check_shape_page "Example" @ManageTransactions("MeasuOp") def CheckShape(self,theShape, theIsCheckGeom = 0, theReturnStatus = 0): """ @@ -10884,7 +10884,7 @@ class geomBuilder(object, GEOM._objref_GEOM_Gen): # - GEOM.SI_ALL(5) - all interferences. # @return TRUE, if the shape contains no self-intersections. # - # @ref tui_measurement_tools_page "Example" + # @ref tui_check_self_intersections_page "Example" @ManageTransactions("MeasuOp") def CheckSelfIntersections(self, theShape, theCheckLevel = GEOM.SI_ALL): """ @@ -10909,6 +10909,43 @@ class geomBuilder(object, GEOM._objref_GEOM_Gen): RaiseIfFailed("CheckSelfIntersections", self.MeasuOp) return IsValid + ## Detect intersections of the given shapes with algorithm based on mesh intersections. + # @param theShape1 First source object + # @param theShape2 Second source object + # @param theTolerance Specifies a distance between shapes used for detecting gaps: + # - if \a theTolerance <= 0, algorithm detects intersections (default behavior) + # - if \a theTolerance > 0, algorithm detects gaps + # @param theDeflection Linear deflection coefficient that specifies quality of tesselation: + # - if \a theDeflection <= 0, default deflection 0.001 is used + # @return TRUE, if there are intersections (gaps) between source shapes + # @return List of sub-shapes IDs from 1st shape that localize intersection. + # @return List of sub-shapes IDs from 2nd shape that localize intersection. + # + # @ref tui_fast_intersection_page "Example" + @ManageTransactions("MeasuOp") + def FastIntersect(self, theShape1, theShape2, theTolerance = 0.0, theDeflection = 0.001): + """ + Detect intersections of the given shapes with algorithm based on mesh intersections. + + Parameters: + theShape1 First source object + theShape2 Second source object + theTolerance Specifies a distance between shapes used for detecting gaps: + - if theTolerance <= 0, algorithm detects intersections (default behavior) + - if theTolerance > 0, algorithm detects gaps + theDeflection Linear deflection coefficient that specifies quality of tesselation: + - if theDeflection <= 0, default deflection 0.001 is used + + Returns: + TRUE, if there are intersections (gaps) between source shapes + List of sub-shapes IDs from 1st shape that localize intersection. + List of sub-shapes IDs from 2nd shape that localize intersection. + """ + # Example: see GEOM_TestMeasures.py + IsOk, Res1, Res2 = self.MeasuOp.FastIntersect(theShape1, theShape2, theTolerance, theDeflection) + RaiseIfFailed("FastIntersect", self.MeasuOp) + return IsOk, Res1, Res2 + ## Get position (LCS) of theShape. # # Origin of the LCS is situated at the shape's center of mass. @@ -11710,7 +11747,7 @@ class geomBuilder(object, GEOM._objref_GEOM_Gen): # @return TRUE, if the given shape is a compound of blocks. # If theCompound is not valid, prints all discovered errors. # - # @ref tui_measurement_tools_page "Example 1" + # @ref tui_check_compound_of_blocks_page "Example 1" # \n @ref swig_CheckCompoundOfBlocks "Example 2" @ManageTransactions("BlocksOp") def CheckCompoundOfBlocks(self,theCompound): @@ -11749,7 +11786,7 @@ class geomBuilder(object, GEOM._objref_GEOM_Gen): # presence of non-quadrangular faces). The second object is a # group of all non quadrangular faces. # - # @ref tui_measurement_tools_page "Example 1" + # @ref tui_get_non_blocks_page "Example 1" # \n @ref swig_GetNonBlocks "Example 2" @ManageTransactions("BlocksOp") def GetNonBlocks (self, theShape, theName=None): diff --git a/src/MeasureGUI/CMakeLists.txt b/src/MeasureGUI/CMakeLists.txt index 8f57e40ad..fe15eedc0 100755 --- a/src/MeasureGUI/CMakeLists.txt +++ b/src/MeasureGUI/CMakeLists.txt @@ -97,6 +97,7 @@ SET(MeasureGUI_HEADERS MeasureGUI_CheckCompoundOfBlocksDlg.h MeasureGUI_GetNonBlocksDlg.h MeasureGUI_CheckSelfIntersectionsDlg.h + MeasureGUI_FastCheckIntersectionsDlg.h MeasureGUI_PointDlg.h MeasureGUI_ManageDimensionsDlg.h MeasureGUI_CreateDimensionDlg.h @@ -123,6 +124,7 @@ SET(_moc_HEADERS MeasureGUI_CheckCompoundOfBlocksDlg.h MeasureGUI_GetNonBlocksDlg.h MeasureGUI_CheckSelfIntersectionsDlg.h + MeasureGUI_FastCheckIntersectionsDlg.h MeasureGUI_PointDlg.h MeasureGUI_ManageDimensionsDlg.h MeasureGUI_CreateDimensionDlg.h @@ -154,6 +156,7 @@ SET(MeasureGUI_SOURCES MeasureGUI_CheckCompoundOfBlocksDlg.cxx MeasureGUI_GetNonBlocksDlg.cxx MeasureGUI_CheckSelfIntersectionsDlg.cxx + MeasureGUI_FastCheckIntersectionsDlg.cxx MeasureGUI_PointDlg.cxx MeasureGUI_ManageDimensionsDlg.cxx MeasureGUI_CreateDimensionDlg.cxx diff --git a/src/MeasureGUI/MeasureGUI.cxx b/src/MeasureGUI/MeasureGUI.cxx index 3f5358745..1c5d61b95 100644 --- a/src/MeasureGUI/MeasureGUI.cxx +++ b/src/MeasureGUI/MeasureGUI.cxx @@ -50,6 +50,7 @@ #include "MeasureGUI_CheckCompoundOfBlocksDlg.h" // Method CHECKCOMPOUND #include "MeasureGUI_GetNonBlocksDlg.h" // Method GET NON BLOCKS #include "MeasureGUI_CheckSelfIntersectionsDlg.h" // Method CHECK SELF INTERSCTIONS +#include "MeasureGUI_FastCheckIntersectionsDlg.h" // Method FAST CHECK INTERSCTIONS #include "MeasureGUI_PointDlg.h" // Method POINTCOORDINATES #include "MeasureGUI_ManageDimensionsDlg.h" // Method MANAGEDIMENSIONS @@ -125,6 +126,9 @@ bool MeasureGUI::OnGUIEvent( int theCommandID, SUIT_Desktop* parent ) case GEOMOp::OpCheckSelfInters: dlg = new MeasureGUI_CheckSelfIntersectionsDlg( getGeometryGUI(), parent ); break; // CHECK SELF INTERSCTIONS + case GEOMOp::OpFastCheckInters: + dlg = new MeasureGUI_FastCheckIntersectionsDlg( getGeometryGUI(), parent ); + break; // FAST CHECK INTERSCTIONS case GEOMOp::OpPointCoordinates: dlg = new MeasureGUI_PointDlg( getGeometryGUI(), parent ); break; // POINT COORDINATES diff --git a/src/MeasureGUI/MeasureGUI_FastCheckIntersectionsDlg.cxx b/src/MeasureGUI/MeasureGUI_FastCheckIntersectionsDlg.cxx new file mode 100644 index 000000000..a9ba9622f --- /dev/null +++ b/src/MeasureGUI/MeasureGUI_FastCheckIntersectionsDlg.cxx @@ -0,0 +1,696 @@ +// Copyright (C) 2007-2014 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +// GEOM GEOMGUI : GUI for Geometry component +// File : MeasureGUI_FastCheckIntersectionsDlg.cxx + +#include "MeasureGUI_FastCheckIntersectionsDlg.h" +#include "MeasureGUI.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#define TEXTEDIT_FONT_FAMILY "Courier" +#define TEXTEDIT_FONT_SIZE 11 +//================================================================================= +// class : MeasureGUI_FastCheckIntersectionsDlg() +// purpose : Constructs a MeasureGUI_FastCheckIntersectionsDlg which is a child of 'parent', with the +// name 'name' and widget flags set to 'f'. +// The dialog will by default be modeless, unless you set 'modal' to +// true to construct a modal dialog. +//================================================================================= +MeasureGUI_FastCheckIntersectionsDlg::MeasureGUI_FastCheckIntersectionsDlg (GeometryGUI* GUI, QWidget* parent) + : GEOMBase_Skeleton (GUI, parent, false), + mySelButton1 (0), + mySelButton2 (0), + myEditObjName1 (0), + myEditObjName2 (0), + myDetGaps (0), + myTolerance (0), + myDeflection (0), + myComputeButton (0), + myShapeList1 (0), + myShapeList2 (0) +{ + SUIT_ResourceMgr* aResMgr = SUIT_Session::session()->resourceMgr(); + QPixmap image0 (aResMgr->loadPixmap("GEOM", tr("ICON_DLG_FAST_CHECK_INTERSECTIONS"))); + QPixmap image1 (aResMgr->loadPixmap("GEOM", tr("ICON_SELECT"))); + + setWindowTitle(tr("GEOM_FAST_CHECK_INTERSECTIONS")); + + /***************************************************************/ + mainFrame()->GroupConstructors->setTitle(tr("GEOM_FAST_CHECK_INTERSECTIONS")); + mainFrame()->RadioButton1->setIcon(image0); + mainFrame()->RadioButton2->setAttribute( Qt::WA_DeleteOnClose ); + mainFrame()->RadioButton2->close(); + mainFrame()->RadioButton3->setAttribute( Qt::WA_DeleteOnClose ); + mainFrame()->RadioButton3->close(); + + QGroupBox *aGrp = new QGroupBox(tr("GEOM_FAST_CHECK_OBJ")); + QLabel *anObjLbl1 = new QLabel(tr("GEOM_OBJECT_I").arg("1")); + QLabel *anObjLbl2 = new QLabel(tr("GEOM_OBJECT_I").arg("2")); + QLabel *aShapeLbl1 = new QLabel(tr("GEOM_FAST_CHECK_INT_SUBSHAPES").arg("1")); + QLabel *aShapeLbl2 = new QLabel(tr("GEOM_FAST_CHECK_INT_SUBSHAPES").arg("2")); + QLabel *aDeflectLbl = new QLabel(tr("GEOM_FAST_CHECK_INT_DEFLECT")); + QFont aFont (TEXTEDIT_FONT_FAMILY, TEXTEDIT_FONT_SIZE); + + aFont.setStyleHint(QFont::TypeWriter, QFont::PreferAntialias); + + mySelButton1 = new QPushButton; + mySelButton1->setIcon(image1); + mySelButton1->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + mySelButton2 = new QPushButton; + mySelButton2->setIcon(image1); + mySelButton2->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + + myEditObjName1 = new QLineEdit; + myEditObjName1->setReadOnly(true); + myEditObjName2 = new QLineEdit; + myEditObjName2->setReadOnly(true); + + myDetGaps = new QCheckBox( tr( "GEOM_FAST_CHECK_INT_DETECT_GAPS" )); + myTolerance = new SalomeApp_DoubleSpinBox; + myDeflection = new SalomeApp_DoubleSpinBox; + myShapeList1 = new QListWidget; + myShapeList2 = new QListWidget; + myShapeList1->setSelectionMode(QAbstractItemView::ExtendedSelection); + myShapeList2->setSelectionMode(QAbstractItemView::ExtendedSelection); + + myComputeButton = new QPushButton(tr("GEOM_FAST_CHECK_INT_COMPUTE")); + + QGridLayout *aGrpLayout = new QGridLayout(aGrp); + aGrpLayout->setMargin(9); + aGrpLayout->setSpacing(6); + aGrpLayout->addWidget(anObjLbl1, 0, 0); + aGrpLayout->addWidget(mySelButton1, 0, 1); + aGrpLayout->addWidget(myEditObjName1, 0, 2); + aGrpLayout->addWidget(anObjLbl2, 1, 0); + aGrpLayout->addWidget(mySelButton2, 1, 1); + aGrpLayout->addWidget(myEditObjName2, 1, 2); + aGrpLayout->addWidget(aDeflectLbl, 2, 0); + aGrpLayout->addWidget(myDeflection, 2, 1, 1, 2); + aGrpLayout->addWidget(myDetGaps, 3, 0); + aGrpLayout->addWidget(myTolerance, 3, 1, 1, 2); + aGrpLayout->addWidget(myComputeButton, 4, 0, 1, 3); + + QGridLayout *aGrpLayout2 = new QGridLayout(); + aGrpLayout->addLayout(aGrpLayout2, 5, 0, 1, 3); + aGrpLayout2->addWidget(aShapeLbl1, 0, 0); + aGrpLayout2->addWidget(aShapeLbl2, 0, 1); + aGrpLayout2->addWidget(myShapeList1, 1, 0); + aGrpLayout2->addWidget(myShapeList2, 1, 1); + + QVBoxLayout* layout = new QVBoxLayout (centralWidget()); + layout->setMargin(0); layout->setSpacing(6); + layout->addWidget(aGrp); + + /***************************************************************/ + + myHelpFileName = "fast_intersection_page.html"; + + // Initialisation + Init(); +} + +//================================================================================= +// function : ~MeasureGUI_FastCheckIntersectionsDlg() +// purpose : Destroys the object and frees any allocated resources +//================================================================================= +MeasureGUI_FastCheckIntersectionsDlg::~MeasureGUI_FastCheckIntersectionsDlg() +{ +} + +//================================================================================= +// function : Init() +// purpose : +//================================================================================= +void MeasureGUI_FastCheckIntersectionsDlg::Init() +{ + myObj1.nullify(); + myObj2.nullify(); + myEditObjName1->setText(""); + myEditObjName2->setText(""); + myEditObjName1->setEnabled(true); + myEditObjName2->setEnabled(false); + + myDetGaps->setChecked(false); + double SpecificStep = 0.001; + double prec = Precision::Confusion(); + initSpinBox(myTolerance, prec, MAX_NUMBER, SpecificStep); + myTolerance->setValue(SpecificStep); + myTolerance->setEnabled(false); + + // Obtain deflection from preferences + SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr(); + const char* quantity = "deflection_coeff"; + double aDeflection = resMgr->doubleValue("Geometry", quantity, 0.00001); + initSpinBox(myDeflection, prec, 1.0, aDeflection); + myDeflection->setValue(aDeflection); + + myEditCurrentArgument = myEditObjName1; + + connect(myGeomGUI, SIGNAL(SignalDeactivateActiveDialog()), + this, SLOT(DeactivateActiveDialog())); + connect(myGeomGUI, SIGNAL(SignalCloseAllDialogs()), + this, SLOT(ClickOnCancel())); + connect(buttonOk(), SIGNAL(clicked()), this, SLOT(ClickOnOk())); + connect(buttonApply(), SIGNAL(clicked()), this, SLOT(ClickOnApply())); + connect(mySelButton1, SIGNAL(clicked()), + this, SLOT(SetEditCurrentArgument())); + connect(mySelButton2, SIGNAL(clicked()), + this, SLOT(SetEditCurrentArgument())); + connect(myDetGaps, SIGNAL(toggled(bool)), this, SLOT(OnGaps(bool))); + connect( myTolerance, SIGNAL(valueChanged(double)), this, SLOT(clear())); + connect( myDeflection, SIGNAL(valueChanged(double)), this, SLOT(clear())); + connect(myShapeList1, SIGNAL(itemSelectionChanged()), + SLOT(onSubShapesListSelectionChanged())); + connect(myShapeList2, SIGNAL(itemSelectionChanged()), + SLOT(onSubShapesListSelectionChanged())); + connect(myComputeButton, SIGNAL(clicked()), this, SLOT(onCompute())); + + LightApp_SelectionMgr* aSel = myGeomGUI->getApp()->selectionMgr(); + + connect(aSel, SIGNAL(currentSelectionChanged()), + this, SLOT(SelectionIntoArgument())); + + initName(tr("GEOM_FAST_INTERSECTION_NAME")); + buttonOk()->setEnabled(false); + buttonApply()->setEnabled(false); + myComputeButton->setEnabled(false); + activateSelection(); + + mySelButton1->click(); + SelectionIntoArgument(); +} + +//================================================================================= +// function : clear +// purpose : +//================================================================================= +void MeasureGUI_FastCheckIntersectionsDlg::clear() +{ + disconnect(myShapeList1, SIGNAL(itemSelectionChanged()), this, 0); + disconnect(myShapeList2, SIGNAL(itemSelectionChanged()), this, 0); + myShapeList1->clear(); + myShapeList2->clear(); + connect(myShapeList1, SIGNAL(itemSelectionChanged()), + SLOT(onSubShapesListSelectionChanged())); + connect(myShapeList2, SIGNAL(itemSelectionChanged()), + SLOT(onSubShapesListSelectionChanged())); + erasePreview(); + buttonOk()->setEnabled(false); + buttonApply()->setEnabled(false); + myComputeButton->setEnabled(true); +} + +//================================================================================= +// function : onCompute +// purpose : +//================================================================================= +void MeasureGUI_FastCheckIntersectionsDlg::onCompute() +{ + myShapeList1->clear(); + myShapeList2->clear(); + + if (!findIntersections()) { + myShapeList1->addItem(tr("GEOM_FAST_INTERSECTION_FAILS")); + myShapeList1->setEnabled(false); + myShapeList2->addItem(tr("GEOM_FAST_INTERSECTION_FAILS")); + myShapeList2->setEnabled(false); + return; + } + + myShapeList1->setEnabled(true); + myShapeList2->setEnabled(true); + QStringList aSubShapeList1, aSubShapeList2; + TopoDS_Shape aSelShape1, aSelShape2; + if (myObj1 && GEOMBase::GetShape(myObj1.get(), aSelShape1) && myObj2 + && GEOMBase::GetShape(myObj2.get(), aSelShape2)) { + TopTools_IndexedMapOfShape anIndices1, anIndices2; + TopExp::MapShapes(aSelShape1, anIndices1); + TopExp::MapShapes(aSelShape2, anIndices2); + + //Sub-shapes of 1st Object + for (int i = 0; i < myInters1->length(); i++) { + TopoDS_Shape aSubShape = anIndices1.FindKey(myInters1[i]); + QString aType = GEOMBase::GetShapeTypeString(aSubShape); + if (!aType.isEmpty()) + aSubShapeList1.append(QString("%1_%2").arg(aType).arg(myInters1[i])); + } + myShapeList1->addItems(aSubShapeList1); + myShapeList1->selectAll(); + + //Sub-shapes of second Object + for (int i = 0; i < myInters2->length(); i++) { + TopoDS_Shape aSubShape = anIndices2.FindKey(myInters2[i]); + QString aType = GEOMBase::GetShapeTypeString(aSubShape); + if (!aType.isEmpty()) + aSubShapeList2.append(QString("%1_%2").arg(aType).arg(myInters2[i])); + } + myShapeList2->addItems(aSubShapeList2); + myShapeList2->selectAll(); + } + + buttonOk()->setEnabled(true); + buttonApply()->setEnabled(true); + myComputeButton->setEnabled(false); +} + +//================================================================================= +// function : ActivateThisDialog +// purpose : +//================================================================================= +void MeasureGUI_FastCheckIntersectionsDlg::ActivateThisDialog() +{ + GEOMBase_Skeleton::ActivateThisDialog(); + + LightApp_SelectionMgr* aSel = myGeomGUI->getApp()->selectionMgr(); + if ( aSel ) + connect( aSel, SIGNAL( currentSelectionChanged() ), this, SLOT( SelectionIntoArgument() ) ); + + activateSelection(); + DISPLAY_PREVIEW_MACRO +} + +//================================================================================= +// function : DeactivateActiveDialog() +// purpose : public slot to deactivate if active +//================================================================================= +void MeasureGUI_FastCheckIntersectionsDlg::DeactivateActiveDialog() +{ + GEOMBase_Skeleton::DeactivateActiveDialog(); +} + +//================================================================================= +// function : activateSelection +// purpose : +//================================================================================= +void MeasureGUI_FastCheckIntersectionsDlg::activateSelection() +{ + TColStd_MapOfInteger aTypes; + aTypes.Add(GEOM_COMPOUND ); + aTypes.Add(GEOM_SOLID ); + aTypes.Add(GEOM_SHELL); + aTypes.Add(GEOM_FACE); + globalSelection(aTypes); + + std::list needTypes; + needTypes.push_back( TopAbs_FACE ), needTypes.push_back( TopAbs_SHELL ), needTypes.push_back( TopAbs_SOLID ), needTypes.push_back( TopAbs_COMPOUND ); + localSelection(GEOM::GEOM_Object::_nil(), needTypes ); + +} + +//================================================================================= +// function : ClickOnOk() +// purpose : +//================================================================================= +void MeasureGUI_FastCheckIntersectionsDlg::ClickOnOk() +{ + if ( ClickOnApply() ) + ClickOnCancel(); +} + +//================================================================================= +// function : ClickOnApply() +// purpose : +//================================================================================= +bool MeasureGUI_FastCheckIntersectionsDlg::ClickOnApply() +{ + if ( !onAccept() ) + return false; + + clear(); + initName(); + return true; +} + +//================================================================================= +// function : extractPrefix +// purpose : +//================================================================================= +bool MeasureGUI_FastCheckIntersectionsDlg::extractPrefix() const +{ + return true; +} + +//================================================================================= +// function : createOperation +// purpose : +//================================================================================= +GEOM::GEOM_IOperations_ptr MeasureGUI_FastCheckIntersectionsDlg::createOperation() +{ + return getGeomEngine()->GetIMeasureOperations( getStudyId() ); +} + +//================================================================================= +// function : isValid +// purpose : +//================================================================================= +bool MeasureGUI_FastCheckIntersectionsDlg::isValid( QString& ) +{ + return myObj1 && myObj2; +} + +//================================================================================= +// function : SetEditCurrentArgument +// purpose : +//================================================================================= +void MeasureGUI_FastCheckIntersectionsDlg::SetEditCurrentArgument() +{ + QPushButton* send = (QPushButton*)sender(); + + if (send == mySelButton1) { + myEditCurrentArgument = myEditObjName1; + + mySelButton2->setDown(false); + myEditObjName2->setEnabled(false); + myObj1.nullify(); + } + else { + myEditCurrentArgument = myEditObjName2; + + mySelButton1->setDown(false); + myEditObjName1->setEnabled(false); + myObj2.nullify(); + } + + disconnect(myGeomGUI->getApp()->selectionMgr(), 0, this, 0); + activateSelection(); + connect(myGeomGUI->getApp()->selectionMgr(), SIGNAL(currentSelectionChanged()), + this, SLOT(SelectionIntoArgument())); + + // enable line edit + myEditCurrentArgument->setEnabled(true); + myEditCurrentArgument->setFocus(); + // after setFocus(), because it will be setDown(false) when loses focus + send->setDown(true); + + SelectionIntoArgument(); +} + +//================================================================================= +// function : OnGaps() +// purpose : +//================================================================================= +void MeasureGUI_FastCheckIntersectionsDlg::OnGaps(bool cheked) +{ + clear(); + myTolerance->setEnabled(cheked); +} +//================================================================================= +// function : SelectionIntoArgument +// purpose : +//================================================================================= +void MeasureGUI_FastCheckIntersectionsDlg::SelectionIntoArgument() +{ + myEditCurrentArgument->setText(""); + // Clear the dialog. + clear(); + + QList typesLst; + typesLst << TopAbs_FACE << TopAbs_SHELL << TopAbs_SOLID << TopAbs_COMPOUND; + GEOM::GeomObjPtr aSelectedObject = getSelected( typesLst ); + + // clear selection + disconnect(myGeomGUI->getApp()->selectionMgr(), 0, this, 0); + myGeomGUI->getApp()->selectionMgr()->clearSelected(); + connect(myGeomGUI->getApp()->selectionMgr(), SIGNAL(currentSelectionChanged()), + this, SLOT(SelectionIntoArgument())); + + if (myEditCurrentArgument == myEditObjName1) { + myObj1 = aSelectedObject; + if (myObj1 && !myObj2) + mySelButton2->click(); + } + else { + myObj2 = aSelectedObject; + if (myObj2 && !myObj1) + mySelButton1->click(); + } + myEditObjName1->setText(myObj1 ? GEOMBase::GetName(myObj1.get()) : ""); + myEditObjName2->setText(myObj2 ? GEOMBase::GetName(myObj2.get()) : ""); +} + +//================================================================================= +// function : enterEvent +// purpose : +//================================================================================= +void MeasureGUI_FastCheckIntersectionsDlg::enterEvent(QEvent *) +{ + if (!mainFrame()->GroupConstructors->isEnabled()) + ActivateThisDialog(); +} + +//================================================================================= +// function : findIntersections +// purpose : +//================================================================================= +bool MeasureGUI_FastCheckIntersectionsDlg::findIntersections() +{ + if (!myObj1 || !myObj2) + return false; + + GEOM::GEOM_IMeasureOperations_var anOper = + GEOM::GEOM_IMeasureOperations::_narrow(getOperation()); + bool isOK = true; + + bool HasInte; + try { + HasInte = anOper->FastIntersect(myObj1.get(), myObj2.get(), getTolerance(), getDeflection(), myInters1, myInters2); + } + catch (const SALOME::SALOME_Exception& e) { + SalomeApp_Tools::QtCatchCorbaException(e); + isOK = false; + } + + bool isDone = anOper->IsDone(); + if (!isDone) { + CORBA::String_var aMsg = anOper->GetErrorCode(); + SUIT_MessageBox::warning(this, + QObject::tr("WRN_WARNING"), + QObject::tr(aMsg.in())); + } + + if ( !HasInte || myInters1->length() == 0 || myInters2->length() == 0) + isOK = false; + + return isOK; +} + +//================================================================================= +// function : onSubShapesListSelectionChanged +// purpose : +//================================================================================= +void MeasureGUI_FastCheckIntersectionsDlg::onSubShapesListSelectionChanged() +{ + erasePreview(); + previewSubShapesListSelection(myShapeList1); + previewSubShapesListSelection(myShapeList2); +} + +//================================================================================= +// function : previewSubShapesListSelection +// purpose : +//================================================================================= +void MeasureGUI_FastCheckIntersectionsDlg::previewSubShapesListSelection(QListWidget* theWidget) +{ + GEOM::ListOfLong_var anInters; + GEOM::GeomObjPtr anObj; + + if (theWidget == myShapeList1) { // Sub-Shapes of Object 1 + anObj = myObj1; + anInters = myInters1; + } + else { + if (theWidget == myShapeList2) { // Sub-Shapes of Object 2 + anObj = myObj2; + anInters = myInters2; + } + else return; + } + // Selected IDs + QList aIds; + for (int i = 0, n = theWidget->count(); i < n; i++) { + if (theWidget->item(i)->isSelected()) + aIds.append(i); + } + if (aIds.count() < 1) + return; + + TopoDS_Shape aSelShape; + TopoDS_Shape aSubShape; + TopTools_IndexedMapOfShape anIndices; + if (anObj && GEOMBase::GetShape(anObj.get(), aSelShape)) { + SALOME_Prs* aPrs = 0; + TopExp::MapShapes(aSelShape, anIndices); + QList::iterator it; + for (it = aIds.begin(); it != aIds.end(); ++it) { + aSubShape = anIndices.FindKey(anInters[(*it)]); + try { + getDisplayer()->SetColor(Quantity_NOC_RED); + getDisplayer()->SetWidth(3); + getDisplayer()->SetToActivate(false); + aPrs = !aSubShape.IsNull() ? getDisplayer()->BuildPrs(aSubShape) : 0; + if (aPrs) + displayPreview(aPrs, true); + } + catch (const SALOME::SALOME_Exception& e) { + SalomeApp_Tools::QtCatchCorbaException(e); + } + } + } +} + +//================================================================================= +// function : getLstObjFromListSelection +// purpose : +//================================================================================= +GEOM::ListOfGO_var MeasureGUI_FastCheckIntersectionsDlg::getLstObjFromListSelection(QListWidget* theWidget) +{ + GEOM::ListOfLong_var anInters; + GEOM::GeomObjPtr anObj; + GEOM::ListOfGO_var anObjLst = new GEOM::ListOfGO(); + + if (theWidget == myShapeList1) { // Sub-Shapes of Object 1 + anObj = myObj1; + anInters = myInters1; + } + else { + if (theWidget == myShapeList2) { // Sub-Shapes of Object 2 + anObj = myObj2; + anInters = myInters2; + } + else + return anObjLst; + } + //Add in study myObj if local selection + GEOMBase::PublishSubObject( anObj.get() ); + // Collect the map of indices and already publised objects + TColStd_IndexedMapOfInteger aMapIndex; + ObjectList aObjLstExist; + for (int i = 0, n = theWidget->count(); i < n; i++) { + if (theWidget->item(i)->isSelected()) { + GEOM::GEOM_Object_var aTmpObj = GEOMBase_Helper::findObjectInFather(anObj.get(), anInters[i]); + if (aTmpObj->_is_nil()) + aMapIndex.Add(anInters[i]); + else + aObjLstExist.push_back( GEOM::GEOM_Object::_duplicate(aTmpObj)); + } + } + + if (aMapIndex.IsEmpty() && aObjLstExist.empty()) + return anObjLst; + + // Create objects. + GEOM::ListOfLong_var anArray = new GEOM::ListOfLong; + const int aNbShapes = aMapIndex.Extent(); + anArray->length(aNbShapes); + for (int i = 1; i <= aNbShapes; i++) { + anArray[i - 1] = aMapIndex.FindKey(i); + } + + if (myShapesOper->_is_nil()) + myShapesOper = getGeomEngine()->GetIShapesOperations(getStudyId()); + + GEOM::ListOfGO_var aObjLstCreate = myShapesOper->MakeSubShapes(anObj.get(), anArray); + + //Collect all objects in list + anObjLst->length(aObjLstCreate->length() + aObjLstExist.size()); + + ObjectList::iterator anIter; + int i; + for (i=0, anIter = aObjLstExist.begin(); anIter != aObjLstExist.end(); i++, ++anIter) { + anObjLst[i] = *anIter; + } + for (int j = 0; j < aObjLstCreate->length(); j++) { + anObjLst[aObjLstExist.size()+j]=aObjLstCreate[j]; + } + return anObjLst._retn(); +} + +//================================================================================= +// function : execute +// purpose : +//================================================================================= +bool MeasureGUI_FastCheckIntersectionsDlg::execute(ObjectList& objects) +{ + GEOM::ListOfGO_var aList1 = getLstObjFromListSelection(myShapeList1); + GEOM::ListOfGO_var aList2 = getLstObjFromListSelection(myShapeList2); + GEOM::ListOfGO_var aCompList = new GEOM::ListOfGO(); + const int nbObj = aList1->length() + aList2->length(); + if (nbObj <= 0) + return true; + + //Collect general intersection list + aCompList->length(nbObj); + int i; + for (i = 0; i < aList1->length(); i++) { + GEOMBase::PublishSubObject( aList1[i] ); + aCompList[i]=aList1[i]; + } + for (int j = 0; j < aList2->length(); j++) { + GEOMBase::PublishSubObject( aList2[j] ); + aCompList[i+j]=aList2[j]; + } + + // make compound + objects.push_back(myShapesOper->MakeCompound(aCompList)); + return true; +} + +//================================================================================= +// function : getDeflection +// purpose : +//================================================================================= +float MeasureGUI_FastCheckIntersectionsDlg::getDeflection() +{ + return (float)myDeflection->value(); +} + +//================================================================================= +// function : getTolerance +// purpose : +//================================================================================= +double MeasureGUI_FastCheckIntersectionsDlg::getTolerance() +{ + double aVal = myTolerance->value(); + if (!myDetGaps->isChecked() || aVal < 0.0) + return 0.0; + return aVal; +} diff --git a/src/MeasureGUI/MeasureGUI_FastCheckIntersectionsDlg.h b/src/MeasureGUI/MeasureGUI_FastCheckIntersectionsDlg.h new file mode 100644 index 000000000..745911a8a --- /dev/null +++ b/src/MeasureGUI/MeasureGUI_FastCheckIntersectionsDlg.h @@ -0,0 +1,98 @@ +// Copyright (C) 2007-2014 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +// GEOM GEOMGUI : GUI for Geometry component +// File : MeasureGUI_FastCheckIntersectionsDlg.h + +#ifndef MEASUREGUI_FASTCHECKINTERDLG_H +#define MEASUREGUI_FASTCHECKINTERDLG_H + +#include + +class QListWidget; + +//================================================================================= +// class : MeasureGUI_FastCheckIntersectionsDlg +// purpose : +//================================================================================= + +class MeasureGUI_FastCheckIntersectionsDlg : public GEOMBase_Skeleton +{ + Q_OBJECT + +public: + + MeasureGUI_FastCheckIntersectionsDlg(GeometryGUI*, QWidget*); + ~MeasureGUI_FastCheckIntersectionsDlg(); + +protected: + // redefined from GEOMBase_Helper + virtual GEOM::GEOM_IOperations_ptr createOperation(); + virtual bool isValid(QString &); + virtual bool execute(ObjectList &); + virtual bool extractPrefix() const; + +private slots: + + void onSubShapesListSelectionChanged(); + void clear(); + void onCompute(); + void ClickOnOk(); + bool ClickOnApply(); + void ActivateThisDialog(); + void DeactivateActiveDialog(); + void SelectionIntoArgument(); + void SetEditCurrentArgument(); + void OnGaps(bool); + +private: + + void Init(); + void activateSelection(); + void enterEvent(QEvent *); + bool findIntersections(); + float getDeflection(); + double getTolerance(); + void previewSubShapesListSelection(QListWidget*); + GEOM::ListOfGO_var getLstObjFromListSelection(QListWidget*); + +private: + + QPushButton *mySelButton1; + QPushButton *mySelButton2; + QLineEdit *myEditObjName1; + QLineEdit *myEditObjName2; + QLineEdit *myEditCurrentArgument; + QCheckBox *myDetGaps; + SalomeApp_DoubleSpinBox *myTolerance; + SalomeApp_DoubleSpinBox *myDeflection; + QPushButton *myComputeButton; + QListWidget *myShapeList1; + QListWidget *myShapeList2; + GEOM::GeomObjPtr myObj1; + GEOM::GeomObjPtr myObj2; + GEOM::ListOfLong_var myInters1; + GEOM::ListOfLong_var myInters2; + GEOM::GEOM_IShapesOperations_var myShapesOper; +}; + +#endif // MEASUREGUI_FASTCHECKINTERDLG_H -- 2.39.2