From 46478ffe32cfca537a35b744700e082f59ec4c4c Mon Sep 17 00:00:00 2001 From: nbv Date: Fri, 19 Oct 2018 16:38:02 +0300 Subject: [PATCH] 0030008: BRepMesh does not respect angular deflection in internal area of bspline surface 1. Check whether the mesh satisfies the required angular deflection has been amended. Namely normals (to the surface) in the ends of any not "frontier" link are made collinear (with the given angular tolerance). 2. New parameters AngleInterior and DeflectionInterior have been added in IMeshTools_Parameters structure. 3. In case of thin long faces with internal edges, add points of internal edges to control parameters using grabParamsOfInternalEdges() in order to avoid aberrations on its ends. Disable addition of parameters from boundary edges in case of BSpline surface. Deviation can be controlled through the deflection parameter. 4. Grab parameters from edges in case if there is just a single interval on BSpline surface along U and V direction. --- dox/dev_guides/upgrade/upgrade.md | 8 +- .../images/modeling_algos_image057.png | Bin 44819 -> 45695 bytes .../modeling_algos/modeling_algos.md | 18 +- .../BRepMesh_BoundaryParamsRangeSplitter.hxx | 5 + src/BRepMesh/BRepMesh_Deflection.cxx | 62 ++++--- src/BRepMesh/BRepMesh_Deflection.hxx | 17 +- ...Mesh_DelaunayDeflectionControlMeshAlgo.hxx | 48 ++++- ...BRepMesh_DelaunayNodeInsertionMeshAlgo.hxx | 3 +- src/BRepMesh/BRepMesh_IncrementalMesh.hxx | 15 +- src/BRepMesh/BRepMesh_ModelBuilder.cxx | 3 +- src/BRepMesh/BRepMesh_NURBSRangeSplitter.cxx | 167 +++++++++++++----- src/BRepMesh/BRepMesh_NURBSRangeSplitter.hxx | 19 +- src/IMeshTools/IMeshTools_Parameters.hxx | 12 +- src/MeshTest/MeshTest.cxx | 15 +- tests/bugs/iges/buc60820_1 | 2 +- tests/bugs/iges/buc60823 | 2 +- tests/bugs/iges/bug306 | 2 +- tests/bugs/mesh/bug25519 | 2 +- tests/bugs/mesh/bug30008_1 | 17 ++ tests/bugs/mesh/bug30008_2 | 32 ++++ tests/bugs/mesh/bug30167 | 2 +- tests/bugs/modalg_2/bug358 | 2 +- tests/bugs/moddata_2/fra62476_2 | 2 +- tests/mesh/data/advanced/B8 | 2 +- tests/mesh/data/standard/Q3 | 2 +- tests/mesh/data/standard/U2 | 2 +- 26 files changed, 354 insertions(+), 107 deletions(-) create mode 100644 tests/bugs/mesh/bug30008_1 create mode 100644 tests/bugs/mesh/bug30008_2 diff --git a/dox/dev_guides/upgrade/upgrade.md b/dox/dev_guides/upgrade/upgrade.md index 9df681aa6b..06fc1a0b36 100644 --- a/dox/dev_guides/upgrade/upgrade.md +++ b/dox/dev_guides/upgrade/upgrade.md @@ -1619,14 +1619,14 @@ Now methods *GeomConvert::ConcatG1*, *GeomConvert::ConcatC1*, *Geom2dConvert::Co @subsection upgrade_740_selection Changes in selection API and picked point calculation algorithm. -*SelectBasics_PickResult* structure has been extended, so that it now defines 3D point on detected entity in addition to Depth value along picking ray. +*SelectBasics_PickResult* structure has been extended, so that it now defines a 3D point on the detected entity in addition to Depth value along picking ray. *SelectMgr_SelectingVolumeManager::Overlap()* methods have been corrected to fill in *SelectBasics_PickResult* structure (depth and 3D point) instead of only depth value, so that custom *Select3D_SensitiveEntity* implementation should be updated accordingly (including *Select3D_SensitiveSet* subclasses). @subsection upgrade_740_ocafpersistence Document format version management improvement. -Previously Document format version after restoring by DocumentRetrievalDriver was propagated using static methods of corresponding units (like MDataStd or MNaming) to static variables of these units and after that became accessible to Drivers of these units. -Now Document format version is available to drivers via RelocationTable. The Relocation table now keeps HeaderData of the document and a format version can be extracted in next way: theRelocTable.GetHeaderData()->StorageVersion(). -Obsolete methods: *static void SetDocumentVersion (const Standard_Integer DocVersion)* and *static Standard_Integer DocumentVersion()* of *BinMDataStd*, *BinMNaming*, *XmlMDataStd* and *XmlMNaming* are removed. +Previously Document format version restored by *DocumentRetrievalDriver* was propagated using static methods of the corresponding units (like *MDataStd* or *MNaming*) to static variables of these units and after that became accessible to Drivers of these units. +Now Document format version is available to drivers via *RelocationTable*. The Relocation table now keeps *HeaderData* of the document and a format version can be extracted in the following way: *theRelocTable.GetHeaderData()->StorageVersion()*. +Obsolete methods: *static void SetDocumentVersion (const Standard_Integer DocVersion)* and *static Standard_Integer DocumentVersion()* have been removed from *BinMDataStd*, *BinMNaming*, *XmlMDataStd* and *XmlMNaming*. @subsection upgrade_740_changed_api_of_brepmesh BRepMesh - revision of the data model diff --git a/dox/user_guides/modeling_algos/images/modeling_algos_image057.png b/dox/user_guides/modeling_algos/images/modeling_algos_image057.png index d2aabb971cb632571e488c4f03f98ab1de0e9e63..450b8c6f1294a911770d087ce26652b703f87fdc 100644 GIT binary patch literal 45695 zcma%iWl$YWur_jV*Wm8%?(XjHkl+r%-QC?1ECfw(hu|6r?(Q1g?vnS`SKrTjs;E=D zoZXq}X?eQ)nJ5({X(V_&crY+9Bv}~=H83!UUNA85NmvNr&KxxTIPeATswOQ4Ry{#* z2wZ@yMHNNC!0HkZo=u^EYd9wvT~{zLJ z_1_DU3u8szZ|zWs;s*VDk?jBdMN0YE+1ba{ZTYBr1_oC%1+N@;nsmKf3%ISN9bz^Ze&p@IR6dnautgwQdCy9UpGh; zaPvo7@hPd_%$X!f1|mIb+yCWwkg4lA8iwfpZajzk>BYac`;|H1Vf1D`;L`Z*X8l#p zi9}}P-?S~vc-#)AzSVTjO;4K=1~B-)$yi$M0zZzqz2!2Tmy!w(csZ8NV94a3>7@!u3xsN?52M>pXWYE2}*!$kE5T=NaLbnNmgk^Nzc<-@ny(LI>B}=M4j{ zxjjXTT3Wp4t5>ZeAw<;({z(_3n=-?|cbGCG5W?&7SH`DLpBRqeTuQ+)#h^>kMAdNr z`;myd`wi#3fuXMM!|k$T*VPE$302e>`oG;!K>UDn|MH52&(;3+`jmbnaljcURuS}3 zB2feSeM^V>!Q$VRY`bdBenm6tH?}`tjZ!bQkmALiE&V*6DiW7ZXQ-$)GSfw)`1wz$ zY^GHlk%Qa7>pJY0xkf+xwm%+yJD#h%EZ#5Z!efbpP2T#q`B^M%?Cf3lzmDgtbQ^r` z&OR93cWo0q!_CglK5wD~2)G@f3fz|FIMC71)GCq4d(L7X1zWpI|4kv<;8}=_%%L5!-TA+HgF6GY$$BK??f9`fqQk@_+ySJ?XnQ z14zkxxx1bS+$M66$mis8kl2%lVEul8TSc7YBmBF?B+728L3RaM;`Pm<3cp?|OG!yN zbll7>JG5bOf|5)BlNsg!On}~?^wjU)_1@R%`T6-?0INz+@PE9SH#XMQg|oiCa$#p zR8(AlIr9v7oGEzp?R+|GI|sY~2wc_B&`?wJ&-!`-8${OSzsd8;dYrGle0TIaJ}fIR zYIfRG_PhWmE6SI(+#=`(N*lUx0d-Sd5bui$0a3YU?lJB_6 z(f>Nfy1?)D{X2r#9|vCB$a^=(v9rZ|FdpBb-FZBl^C*di_*tdu3WjE&tE-nIK4(*P zWPyBhpLT9@@WDikC&(H$_#p*c@;I>kqNZ@tu>s-i z;d$<0(xu}(IP|&^d$_LBv}iPgeFGS4G<{OKxCZ>vgT#&(nQDin+#yz-TS`ko#oi4s>BD%3qkCKj0fMOfJ=GMsE|cTpqotgtU>#1qZ-^7 zg;(F*at&?`v!`SF9ksVewlJw~Wb=m`e=eiVS8-@ITdSP8T3?vEY@5fMG|mqg+~3>1 zw^INGo=0?$BE)tSA#P{};^^XhIcrZXVF=lFc4&Wl-QlPE2;A0a)rs$eOB8|u2DJX zHl6&Hl|)EanmWBW!$xXWSeNGxYh7fa<5ud8INm!^=c$?j3K~ZEFoY0+pb<{WxiDEr z$iMBff(2cWEF@R~H1C3oX(@wElQLEfVXt(lT5Me$IWHPv;9@0_69 znL|ydLgXrf>4Kq9UmzCO;X-XsdFjo-8s&Q9-VWmUTU9wVbN=mH=V)*6Jc$1`a`xgY zX_P)*B|-cozntK|>~t8t67W3o98EU=?fmBD-V-T|*MrAEXwuriOem(M0jDM~!Cf@F zH@9+ACob<-Qnkl(FuA|phs-jC5=-8#i;#u^|7X&R(ja*7BvW`a^O}YZ_i}wH@zj1x zru12JS*Gl%5;&&p9Wyw=A{z`g z1kZ#uupEs(^4Gu*@EEv2lEB+8)%AurYRp{j*%k=-RD2&Br)!Ww^NiA}$5x|yS)A|C zojd`i9T@^#=2-z0^nIwb{g3I;JtLAO!DKK+*||^L^z2%FIX)%bm5=1Hdr;wve82qt z`>$9jl8;_XRc)T~wRYWkK{Gt)3POMF`U<$*);zbLeT0nR(godLBl2x8V0NDza+~(5 ze6QIo;BmBZ=7{`>R84%gg-_zzu4tf|iFL+8!bEhs`xe|(h|G6c;d(V-XNadMY|sSZ z(J6}hOx3`9OuzVOAe~`^Rp8PDVzTyfo;b`%syek9;^Hzjq5XF1Q*L7KJLQrbXkG)` z1*ZdXL{IyL!tD0E24X@2IAM%z! zG6P1-M#n}IIkv<Q1iAU87~gSNa6rm$ej=dh4YrbSWrjkS$O#ULQz&)ka~&@Jy%n4_u0j_Q98Tt4R= zWv#7CkKbp&0WT}7y3qzV0wCd9qL523790Xr9HMZ0FN=O+#IV>`sK7rzS+Ln#vGGR0 ze7_H=M{z!iqGm$PiBFl95W#>uCvH;UdL+UcghOfs7a{6+ZG@=wc$IF1@bp9=T&xRl z7=1U*A}hxuPM5}yI>7GGOl_*mVDrliis-UC!kx6qeBS%%QOY<0Sey}6y9|hzPg)M? zezLQ}Tn&=zn_X-M_;}A_0o{r`e_DpeNYje%sD0DwC!t}tAOO6Tg0q)_brJ(EFG!?2 z6&8#J)Fs@#6EwXUc*A94j)`7bDeexT2|vjW?1Orn#0k24WGyw53bfJ`NP*0PCzCC( zV@3tKl!WE>Ld%3+E6hv3&Crczk_Y71Q#jA^A=eE zu*zh3W&oH#)WI2;7u@#esOnD~-mUoUCsW3J$Cv>DGR-m>8w(yjI4Cbd3|I6s2}fOM zmMA4PkryGQ9c`W7*?>(0O~LekEU69RaaxL87WHFFJ~X?8EQq=06(z=bffFIForN5w ziWIP|=;mHT2N7#QcPH&;fj`q;*)*V^CHY=Md7^QDUnLjHp2o4}AnRK@Mjsak@w(IO zzP20s`{%e^k2kG+K4wgJe-r_-E^07eV-d>QOSl1>Fu-DYcz8HCKuNWJRA^(PF=(mLbpGB_2Y~4R>4hqY(7(mu{o?99vvMPU9tXM^#;e=SYHemXIJQ zSY8wjf%}LK_;ZP+$|MLZ^|r-GD7RcvDWh0PnXk?XO`&=k8k*{&S-1ppiHj$^?&zaQ zuN~g4x$bZMnjwe=10dTFO!qu#l1!iwEZ+T#e_W1g5RN)!Bt#6QMQdzN9MhaOTB<0Q3L?NRe9SKZe2@}3l%fy%hkyL^7B7d|;i}E+4H$9XmYs`@XZ{Eu^5L&$ae1xqy z5@|(tTD0%zCLI*~FT-=rn_sv_`Bnkg`5Q%XMua9%0*8o*=mWfnqw(9+g$zTwNy=cI zCaR`n*m4e%L#@1TX^xeTO=A&aJ-dxkIIhfw2))IEE^H7U22`a3q2{19CL65_YK{}$-x0^zR5B(sywqM$!0OXKxi$uveqAmgh={-Rz zEM-ZSeKms`!IWqm*qu=M$M9A0veI4y;`F|NU!q6trJ4DCycEU;`yi5L*Efr}4^T zC}#2JPk=!mn+?HI60yS0rV5FjN*3j!Z)Eg|Zj;W$MRILDUap~Qs)A*MQ|S%cess-2 zfAVoXe?GF$F!s-KCxZfPRe{MVBuMK3+}#8YO6$PNrO1&3hmDWARsmwUAq?L;BM&Z2 zfLNX{P-w`KE@+f%MAv~UD4DmqM*~_K9%>rZ!!llQ@-|=+Q2Z^K~HT=~1hJrJ@aiz&xh`$3=@~vOYgQ zzl@;osO(rEjB4RZjY>oTpJ?Fh1<&>|KVrvQmdTC?857cuiQh*|9yj(75)*!i zmBlInw(+W3jJ3p2CS@eE58p&#~hs zo!NKudM;`f%o60%Zj+4-3lgDZ$y6|T!F+sr^6`0kc@3=kq(FbsUbjGg;vErZ<#P`~ zJbsOqh`>uUfyiRv(~QUu!zmOAc|-03?kK$jBC&IhvnWi8#!YTYzEIyE)%PJo5uCp` zTN53#AxVkrcD0AJ8==)-(=~3}pExv}yeRR-m|HHq)EG~Ln%EL8d4UURQ_EHeg^=uoRcrlK`qYH9)yJs_Zq7W;Fnj|e>? zBI4~0N^C4Bxn9mI|2qopC0Ei%sDd2ku^j|9Ss@!JlwlWVA@d(!2Ejkzp@aW~U?V(e zrApwcs3V=`Hg?)m96v$JoE9lXY;fIez{mL67v|}Ib1To(vcQ)FkYBpzY!9Kc5q2mv%1Xn^Yg<))>$!6M@QzIoR15_90KU@k~-AVBg+(Pme$cd zyM??&Q}Dh;2|G_Z$i1U;VP^EA-Hf9ey~e{(?b3;}VRUsu-aoRM_9OFKoC@^!hIi7w zcaV@@vDuT5PZ;G|z6TvI?~Laoq08`^m8-AJMvhr(aH(jAp|l@@drSfX0;Hv_eSCbh zJyCMToco0lT}TO_0+hYiNG}~CHtJ^(Va9LN$Xi9OeC_H!CWM5H+bb-UXN#FC(09iL zx`4}yN2ViEK_c1hVyp|$DLhhWL|4B3O^AEDE*n^`Vdy#^cxZ;@Ve`&p*B0s^-77;l z>v;M`KOr!~mn2shDL2q*;kYqt#x=rbvv@(}?Vlu+OBlR^9Z@IKCT*cJmsH0g{Y+ez;71g~8v zdMV04gk*Qw2-k52$q*t85I3()W+ZJM5terp<8YhSJ|FK3-RT}nLP-6ej?d83zoPkIe&`3CV;W*pH(&NumF;(8$*}< zM5Yb=1QHB{q5=2SFV2Zy6)-BX+T-_r`DVFJQwr2;8WH!-eMHPViW=8B^`zI++lmv`@p zW;2rmO2W{Ts`F_!#IwIDbi`mqt&mzLRPm)H4Hcc1z97!=tl;sjp!df@vsIw>{!0El zpLle!lY#j`cMcO87-j3`^S-twRb)+_wk!?b06D6~)>OqtVX<^dNhLx4MGxK+K4gvE z>87{K%>&@CsnEE*zZMKfMqkxON5hY1_X4i^6E>59ik8;m6y@FH;_1I;i}Y{ysyKLQ$=#RCCf{%3-&<-&pBk)Z%wO^Itwm|5xY|f~?>TAeQhH;0j zpYW(dFJlKZ=@Gu|e`W;SI)~lWh-!zc3T>9UkuL9ieJRk=C=IF{8QDs%pY!)-8M^#e z!$pOZYwipbLfw(u$Hcr>Cc>JNeqDtYs7 zp0=W!_X$zkjO|bKku%$$T{i!+Wv1%^_QbpUrLx@MJaS~2?b^ka!FD8s&Fpg~e-l|( z?T-#)T;w_n96+FKqo#!9!Jli4X=!Ph7#V+7(V~2=JuGT(_chX#oUdKutlE6UgJm;C z4MJ6&$282TWlC2x+$^1N(yVK%1e!QvRA_R|uYp25a&plz@bK{O;}F?>cH$u@W6v$?_ zM8hyNd9n95mS&Tux&~;Kv3&!k$T7z%=C*_RrLRhT8&C|ckl^J6F{r;Kax^X)cMLNP%}Qi z{Ii~56|p$YbGMsW>iQKAr+XlThArOOGBXXl>viA<9QY$~(vI?SmN-7CcVC30iivP_ z?UmEysS`&@Wn+T}2r)SvwHGPkZxTyJPD-8>AvpjbXJnn7lepQtmQwMxWhdfqYYe+M`X7nK`3`so7^I${+z%)QS~U$=O&v zK)c7WfD@->PKfjl4-vnvs6^66^#=QP*O$TpGs~({C@{H0jIV^leV>>_H=ks#nOMkj zyQ9r&<65-XJm&{YQz^(SJFgKWn4co4cb`|L+J6AE8j1W^T3${=%^W~d2wlQZ4RjKM z$GDQ=kBtwn_OP(N4sLBo2eX-F4+Ed^i7V;9BA|aOhg>Hk^r)J-qV+90S`x2iq;WNW ze|_N|G2F4ZD5Eel_bD4581VLiLpLi+%U_nx9Ko_kAYMy1#d%HherQLT=#I5_q%WW+t|5 zt{4HfD5}W3o1zuF%H`IuUtV@=ucBem2>J)R_b7tYEGu2YfY)Oof#>mW|Am<{5Zojf zh9$Ro_Ao@1po+i2DMqREh(hhlGGGejPdD#9Zxs_n0LV$UFIEZ>=Fdv*iGac<66%O? zt5K)6lx!T?jZDCMCF+8{DoEXvw~p?D7;Nf9PTwuO<8Dje{51u2tj3EKGSt(BFPUa1?TrG#AfwZ?XN z)d6+>nB;r>MVD)KGC+~ytU<8|ovbg#ry*B^FhVuS&`@&L6a!`bIcP2ZrV4SBZNg2} zCj^eES!0XB=^pkW-Ll&XK+bHWp)viNc!DpFrS9&LFa?BEu2 z2R;C-fUF0VL^M_hj^alhHOLaQAzBhybSw#7PCONyc#*^u(fKr*GI|XsCyiRW!HD9c z2)$r;LQ=pa)!~LBO%xJni~CGVI1E==MhjFaZq1z5#B2XSaz9G!II=` zYyv{Yt?{>@_r<0LN0YSrqsM@ez>1~a*Akq4X;kPD+?R;>T)n*X^m{KqO}?QN-f39*|Xf9+LWgPw1+f~`GdcA zpuGzT@drVODih9hhf%_Oj34;`4!{ghR-QCZ5PSvNp4qqLQNOlC$dW(|GdLs+ug6_P zk5?IvUat@Pn|Pyq2#Ekhvkc;vvNaKb5RJz-oKGoHbZIuc(11Nl#&~&cum5@XOHpvY zAl>!mLGnFCMR!$Y%Hml$`)dT_fR5i4flT=M=Ffb*aBi*p@f^@Y-Q{0@P;zx`u*~M9 zi7u|F>}L0ie)pYT7HJ4loH?s0SraexL9$6`X=!QyKcV7et>Z~r_;LF2=ACPBJ*%#~ z=CvI+7qu9K$R?)l6-@^rsss}I8EPDda@DA?mV`8z{&LU4hDWOTr>3Rwek|;~ ze_?e3zo&YfiWY=B(gd-*jx8xP=bROvX+IR-rC2)`UA zT!`e1Tj^TENU4eU*nom_VI`2=slt&jinT`!B%tPHEjUc{RnqGUXYB!8E*F?Blx!gz z=SF-Ar;r|74sa0mvcJ*O)35tKooXBDdd_wNHU-cyp3dK16}eYa=eCWMvLytHzR9*p zz>zL+z7r&@AQ=a2f`?(bM>&c|aX-8Al4Y+#EIe-m;>HT(z zM!6yi;y-5!eTfPuBV*lFv90~it*5yaJ`Ti%)b3*`FG^YOVd*|Ik7}-I)3zIF~FucB;hr&#p^x>^+Yb9*}_|;jgVV+UHnG z3Ly?fI`NPJ-T@~DU<+kEh!_&fAHZet5hBaVo&VXO(w4HYvhu%-nXl1pu(~^2Wp2L+ zXs}?az@SW$3GFqFvSx$$urHRVECKg(ILK-(iMm;i$Av8@R7Rn~7UdRk5CE}GmQEH& zMOBWW)z=2y1enp%%JuKkd`|0KKP$^3#a<0Ewm%{*5mj63m#zkC4KR1kF z!9h0vGXfeSO41Vd+6h2zyQsaCSc2J86gjJhBDl`J2F|~B1J}>je|)@lo{-}7fejan z;)#*ExcFEIxLk5l4egZSq->qR9KBvgW}bP~=Hw=CWj%4Q!?Bvs=N;9HL*NEM3Zd=Dl;hn|ha(Sd60I4MSuvIt=gepx@5r*|PnTC; zFfquV|3pmWfTH_c;uyN;R{FA{-aR`UdD&AicNtMpQPFbNdJI=o3mCuf&8)gfs9>t% z_R>$3OzjDlt;_qN$O3f?B5JJCvl)>@%y1P&MGC1;|J)j!#i%Cth7>1mhvUD?D?NrS9A555ds&zmMF7BLPEZ7ZUTjkO%se{k|DcL z6`M(#&1#*=J)1%OPi{l$uG!!Ix-6(q^Qz)Oczsl#l+W?0<|*44(F`jmO*{;y24x*|shN2{ zwSsW&)^*`riaE zFZaFxWLTZWOrH@4&sGC=Qo3+9Gd^4}G**Gs(;_2kk5~~aB#Eh6FSC0QGm|E!2nolp zf{tMuW8@flzj%`Ki*yX7S&}rq$*s6v&G;)yQhZm{U?M$E9^dP>0l7pYBBA{1eLX>3 z3xAKjmgf!=0K8QqTA8u6vI^2VrEWm-`~xlK*W)9M zmtgXCQFA6VTMB7#i=1_FKv_Csr_tdvO9YiEzSSN zOw)Q>YzCl$8H8iAiX&OcK48g}ZXO=DcQ=@pmsw1?UFbmgX*8kaL}XCsW6xs))ZcNv zv!k?hfG^(?5ebR9IH;GQ$C7-Z3q4D>wo^#1nVq#(I_eg_n#^Yne%eru$FIIk%|G>~ z?a_E?R$nvO`A?`q?Kl}hebLQkfShX*I zh|L_fSwtD6KNkz;m=hlVypLo&SI}O>YCQQww@}6w<4p0M-&aosv)u*%MoGt%O8iJs z;lhVy&lMF|DicsT6LPxN;WHRd*!A{u4ip!ioxY{JdziSz9?*^yLoKkrN8~xM5z%z_ zJXjKPD=Bi9C2V*{TU(!vAeemr$B#4_sj1J$U9ZP^o@>19WCDYI;Yj%TzDI|a4==`g zjEj^CpT1xQ{1IY7X2gHS;UD$Kv%KB>SUa!VPc&lg<4Q$YGUj0=U_9^UQP%=aLaNzl zoe+*4ZOV;229xcx9W_>9?y1=D z(zK>fa)tHg;Bad^mJUuoA9#*cYv)tT(e2dDUo@Pe*5uYS`<3dtU|EdtecboxK?4XW zGS&fqi}vw=c-{e2w(op9e*=i&uPH{${2d+h31;=%)wuEN?+=W&eC+mYTMzpMFu1I1 zti`RZkFQVXU4W+^>%*ONoqV|rc)Q4%EckBd9A2ofz&6B=-lwgbnLm1=Pc`O)izBpf zF*vtIL&K0*UBPEpH3n}o%{eo~5T3$+MQR@AZ2hK+C@dE*qrkF1VzjK2MR4e#NUjr$ z(9NxnO(PzJ`#q*dzX9S2YQT~8?MI#PlmM%Lx+&(sdJxLuIP(pfvHh{FkOS|P&)cT@ z3F!K+^(I|!%jzT#m%CU0Q>TxFHin)H=51&O?70bZV8@>Ue4$&^?T0}l(&u3*2dG=S z5NS9MG9Fk*>h^J#dN)K;^Emk9P4k+IX4U`K-(of}@Lfl`j&ZT-Ws{L8|Uu z9Q!)7d2R|b%? z!VGVFZpjV_nBb@T1WrGcYS{Dw}WKZO=yfbBawXkB9Wt zwMt*uXUNHkymyjdh`dYyn(*%KE`S$%fp$Ra=bIzyd@nNqL9RdVaRYqPx5fQy-HZu| zwa>OM?2`fw0^e>CtVeHS4ajf^hZ0Kkayf)fDB=aoUdCk^uX8YO2FF1f zL}8A4ctvUFStfp9itqSpcelBIKOZr433(G<8oIPQjeQ?Wu`bY~X}6$!#z@#!Gp0P# z-JG|e_zM(4Fr6C7B+UucFKwW`HBg9xO5mg|liGwat!QsFG8>M8+=HB;jd`=Vk00Icj-4mL2cRjloXwe`NBtZ37@*Vqy}3DEZem7-Wiaj}m=#x2Le{DL z_U#-X%_b+KqhbIIT`vKmrt18tzbJ@OQcu^0%q{RKbifh!ssS2izR{oxkjUD{x_A{3|Wp_H!Y!nksfK4b7^I3@dM{nk{>EYL82Q zUn`R^dzJXLe*h&GVg`yqta}I6c8n00-6TTFD-a4L)&%TW+FD?W4s5Clb7iXDq6c!@ zjQzwew8XTAYB68(`*=iVkZpsB&>tO|K=%@J_yJhb*a++@r(QHD@*gJ8StoT;Dy9rS zOnxX1=1+FtW1U<;&P0q3?TD9GQvsVvIjdwZ#Oey}IBLPY@CA%mxQ!e!4Uw30G@*7` zC+cvxFdH%G_Rnr)^?+{b=yQB+O#*@u;0OM$Pu@8!Yr^(rGG zJbdGX8OWWm=(PeZ0ao%{pA{+~=hu=h|KHyTIv>!b^E0&FD{W;Jqilu~^AV3#OoD=F zMxlIR+2_ID;-YWFeeW@T2&uR_8rh}lQrbduRY6>@Nab$Bw$bY9nDn`vZfrlWa`v4- zm*%`p(FYluKBuENlwCrwsgty)6DUIC%`Vg)Frjs5hBkeTb>s?mLQL$c%#D2htE?#O zQ*<1T5Zd*`G457*QX0men^C^Ad#XE|F8LL))NEX0nL!1|{j>;RFz7UWXBHm4ZJO8e z-@Q_ch-;dNySzXccN))N%5w!AuM4|yW*IKg)5zS~O&jzPzgX0lJ=d6hhT--VqEzp(1@SbVK{< zHeYQB;1A*D?n5_#^zCV4VzS!mK5gT6x%JE2+k1}O8lK5VUj>+7LtFFH-bRzB<}w?K|MsV|s5D#UI8mu)4P_NGLoA@D^3^ z4fLcYv!n@%9fn{_GvOS|g8OicKbecN$%9Y&{#jna@Vd{i>A}gJTIk_PNenIuHC@@4YN~t*Surg2{}$JVIE|5IL$$^hh z>8X2Ea=Wa$OdVfoCq+i|2G{?EhF^}P?vx65rq-hg`#HGD@=^`@cy|JN>v~QP+KwHa zfY@%&@!16Oj>IaJJ!z9}C+~u;L&Hgp4iC?)s`qF9{t!%W(PAZj8+4W_s!?15g*3A5 zCEBn)sTEUTx*r|q)?k;ALPpbHS0us8c}7OP=4P+yvJ=UD`9=ASbSi=xsi)+=h^-EN zb3^1m>?1m7z4CL|jt-wfpNnQbF(@(@@1o-%{tq>8ix10M0M5T@sQ=xmQY-)4h@T^9;4ZN3WuK196bPn5Mc#8cRRr2 z=h?3^Jw!|wm6^uxi(H%U@^rfI#NS)@x1=qH zH*$$N;|0L7^yMc2HCJCLw~a7)rW=?|^2dxfew-wo9WcXjkwJFvhq;yD=ayJ9PWaIQ zAHYd4Qlz996_S_@&R5bt1qa`~kKII!w`k;Q0KaiOul4#My}#=2{%Z?9p>Lqiyr!f1 zeqdDYy1|Y_`e<2v&VA^z=)kVXsi&LmE3f)v+CqoVUA~}?h)5Mc(KU$7Vk0v#(F+6) zh@An4HeQF7{n@Iyte{EAKDYA8yM`K|^!(~U17&^IVjR`|$xRpmh)@}FP}rY%_Vr&%s>32@_BXqlO7Dl4;DKaYQDXrMnhrys{yxh3Z# zCj;Ua7Q!f7HBVDv`&7$K_r>GtOI`nPY&~uqP0x_AJEU|xf}%P8qWq=g*&|HQn4_X%-li?k*#+E*h|! zDMeoE6a5=c!QU2CUFtHyjh8hryHcGzqCV#aPckl104rIW_x$U(S-iz;V5by)bBUuX zz!j@o6b$()<+GMG!JE-KBD7t3pWARU)0n#}Q9If*r*k(T^JJUU=$>@TZPu~85SbQg zY#k+RUZ}2j!z0whcf3NW8&unFx$dNRU2ZApuo1+M95>q-kv@5y&*ey^jKy<_iX9z@ z!~q(KOaXeO&)K%s58p_cq!mAn$z<#6@$oN>UWY*tn_lz1%L(RJOZ;RN0|>2l`(h}E zA4UXQhgv8~M{IQ-^}c83XIDT8qy)arPtDQ#@2*3arc&fA6|6~_0M%ADE=yY9cG)CA z`y)OB zK4jf~OHc!>z5A_lc;ouP1m!&`)}Opz`0Q+7(yzj_Dd2Vj*3T+mM{>fnJ6vvr9iA57xH_6E_Qwfd zzIP<$7cFqV`K${+yS-i5h+!%jg5f3yTMC{4`T-Pq8t%ok4|l7hC;8-=BgDyCcAc!N ztmVI)a&mQ+*qWO)OGVu@+*mH`&<9_BR!1n%e_lE2MM&R2u_f?x*FSegekHITBz=2H zAoRZ-pV&^YAOTx}X&s<~D@`@wFe9U7Ibg3XdDCOdsRi_)FAdv+6grylra_7;K zSzJ;6TN{%=F|_0HP3x}Rm(uPjpkeRBx{?1x@>t{AL4c6q(|Ujn!C&gCUd6xm|Ob3)&% zw8s1*bEfS(K=k>(EsV6bQXH1O)8nX6MZqSM4VH{QKYVZekWX(l0Tkt;ZYiN}2U@uY zpFD?)xEjT1IV9BWmf#}dx;|-cW@CAiz^<+FPyNQIQ}ShK$!eT5)_I;<&%1qyiFSgn zObK+an{`7)%bd-W0eX@1$Am;g`4y|=$-@?o=Ye^k{hbTi4=WO=80I!oRRJ03M~N=! zOV<;H!84h`47-UE@Za|fUg|y?Z&Py!5cwA!Y6m!AQ@z*@))QUudkvF&(-T7NH}Cn5 zXuj%N1I5T(%g~IS>2$9~u>5ug?zt>8E+CA?GK! zwN-;XD`fND^7WfR_I^o?o#jCB9NdGr5^sfxgse7ZH`GjuJXR^4U0rJS&mT@M&T+=n z=myr3AQBmP=gX{?4+Tm1u%m@zN}svtc6bW2vt=G_TU5SFV5EMRW*3)%!!^B)%j{t* z1~SZwx{nS)k%Z)l8es>Y)Zjb;w3^5&?X**BMF0`VmD@d&UnDcXK@GEMDVZ>!shjns zePGa}R6s*avPacqRChv+=)pQB-z8qfs{jMi$4pRvE5s+w21Vbu0B7`6Nm_Yq%V3a_ z{t7$Q%1)34F~{rntRZ(`e&I)leOYMvA!Xn#@! z7^8a->KQ!U-A@-AthWc^&fBjYY}LujD8ADRVdtYSl-{7QsS()`t}D>Gc9u9%;_s@y z;_m0le;EsFtsaO#k>E2*_|a*`xQTW)H~WQ@p%ggWc{JmqRgg{yJ4#IGQFnYX^v^zp zd`(`e{Tt}N^1AnT3F|%$BIP-GJ^G#>UOPiqCPZkPlSgfef3lOgN~H!)a8>GWY<5cF zvKHa6n-N>eo#2W9M-~0VT{Vkz(nC_T$zYRRVo_dy#3zU(mkU$8oyAS)zxv&MY^owI z;M)rGY}-8f`2p)~oYOVNm2mIZ&@_qM4{Bbu5_+^@ZsRLW=TOEo0ds)9QE`4WuUGXK}#xGKxHH-GIH+r6J|2~ST?FLiQl zH2w^aq}|3a)y^m%9lbsv#8kI6hpHu;m6VLRyK#;zOK8`T-zk*H?`cY9jLpFArjSPz z6FN%h8OOV|W1TP4M(}ZPI!9l^p@NcS?8zKc;?+*IwLjPB8R{4vgf=W1<&2tIo+*F3 zdbwEpw7?`xEi620g;#XZa*YrGfT6eTGfIR}r=V(c@B+-BNhV$w90y@q+qz6uWX~U! zANi!c{P!q07c|(lob`Z{rlU(gZ8bGJfWytqtp{YI*{>30Nzz1qCmo(f?c3_ru6r{( z3Zn}oACb{gWl)A-x!PyAiQAX{ma-R`5!NKZ=Cnl3^SG1zUSFKUC5#S=-ftbCX6|ohexc|E2swm?-T;8@*RNI-rf)x z?cjk0o1`%!NJ<>+7hEr}R18{q3ar8LwcrX`_LA{)i1GNf@6ddco?`_NB@{j> zFaf;C8>Dfp2VY&La5A8mZv`%)lF|df021qLe-&8U{DV4TFfvT@3-3gT>YGmqMk|l+J}@jZ)A|1ICBeJg3$HH_%u1eRcV?FX6>Bw)53~7d=XNMy%u(Bm8h zOsS|nJs5eME<$y`p!ZL?l#+)I%7sp}PgC!UTleP4;KsMdtIErrS`28_MioJrYg8Aq zpL`{v+`dhd8k(kfp${`Q!$Vn!CW|g0gaj6VbV3C{HDxRlsud3(|M)nE?&_m1ljcA_%{$qw z0nBvlTU}3oH_;R-$>GTZJt7jg{UFLQZ=PcKI3~;lJ}YkKD!J8f2t%Z}I6}hjt_c0U z#MLE1Uoa)KxAlG~Yp1j~n9zx%F$4f^jLg%`!*0Fv<)!2N=>@#ef^AY;cQtgLOWHb+M5gS$%@9)1sd z!W2R5v^+tOktoK!hjj>v$Z4UVxKnT{RZ~hDS1iq>hB0km6=$Gf zVD37*<}(G3P6?MifBgJ8EUWv4Y!|LT_7p*Ke=+%5V7N{JlkHG;woZlh8{P6f1D%Cx zaf$@l^tv!Ad|146{1^N}YK!|4Z~fBLp8zN>`u5BYARgZ6iG9Krxn}yghGCuF?LR>8 z%c9UoF}8ke!i{;8b(`cOzn(y1K3l z$84;|wrw^x8{2Bqps^aev2EK%W81cEe7n#4{Z4Y_oQ<{CoZ}v2hG558%g|%TWMuFg zV;%vK3Z>Q-45PcF|2E8_FC?fcddn;Dxaf4V<>37wRm0PJ_Hv#ERfVEr`U&)xUp6xD zh3!U+yG5a>LQ-;xedl6PT3T9I&04O2lhQ_IV;C6mpg%SOS;5rYQ#D2O%>)~!NJSWRpbwyS4V|3%7$7Z;*o%EM;b)$D1Q>E{>S#PKW(eDNK8(C-kYpC^7tcEN8 zXu+n;0AA^7kc4{dcNs(fNjJ=yrFiYyDK~(OfEmezWDY`&6`73fMH&SP?{!$$f4Re`hUftP z!D`wq3L?$8gbGuc1o?*%H0BXq6)3Jnl8N#K;n%MSQ4{^`12qP_VhH@(4W<(==oJnL zy4$7ABT5c2M=52r)BRhW7KbmAtF3@)dHs>$P%RfndUpPq--(`w@(gTql`jv8fI&%7 zE#q)_uc|xKs{8fZ+>?Qk0VD3dsF?PHvi5{!`yRL7G_yS|Dk}lAALqMMtcd)CPPU8^ z`c=<07w+Hq&bh@!LY_6CZ9x*f;{@P8V@x`~HujU{a$rPy4$H1{p0-};!ij?+CUvwo z;Cggzps>cu1hCf?NmwPnft1XDhr$LO^KBQGu}<@;t}9g>a{!n;Dg5HZFP1gJG_8;x z42Fj1upl@ue3Pf?0(^Wrj>Tq|nf&+8&ft0eURsme{eA-`75cb-(s4C6OYucf(Ou;!w>Zoz9l_H+YxiZ2Srd2E%xmNY+rAPQ9c^uivQ|}i4x;G7Y zY|6YKm4zDO^X*9Vq5{`P0k^gC^}=J*)naqw#TO+k`|XRC&dDy(*kxJGHgIL1x(Vn7 z=$hed-OQy@ZmAi)j1)qmjn+bWv^9(i|Io}Tq_jWngd_1?2?0SSzy?}YRz`2#I=#I7 zd{mWnX1V0LS`hWuu{Z)yI?+Koj~$BDV4XuV9hmdxYBPzpBB%?7O&sj)tE;LQ(c%0T zLE#-|vPr){_nRvdClys5|5^)Bc}qq89$p)M@Fd-HI-dWqxo1$mpHt>HJ-yiUi?62g z(O%+r(b_S_UZc!87Qnv=h+TvwL<*c^*oE_45!1UndG)nO{QI zK3Pv;G>N~7ZDD#DhA~X*w&f`oXw&R?tFw_q5Ux%XlCf51zyaRt_07$!g>_OZ>r<=K zlS9mFQ@3UoE`Ym0Zj(G`ZS)}rt)|+YzwHi8+pTM?KNTssbl$ae zz1^KKdS0lswT5***l$*9eInU4zMo_K_Kyy)8R)+PC0{7AW|>73Wh-owZWExA<+oRz zW79-z`1{&4_`0DYavmV9{Jo*WqJh3`MWe(73?g87$#*ivQKB%hjPvTVTwLISY-5X#!fB-K!A4&k4!ciBeG)QN4@TO2!ALccm@Sz)yYW(QPJ*^Z9e!*hW-z zgQ{pz!rWe2rW=K}I>hB-V=;`C75eXzIsC28rS=mQlFr?%#>0^+TdmY`nDgTTskGX@ zRoR@DoxVe&q61-o)E?*?Lgp&ffsxu>{~zJb!yYyw29pMnYPK>ZiB1HZ(F%t3g{%GYz7 z64A2(jv1NEEQR0=DBs_i*)1$Bmm91B?qs3mFcaQmG?fBR!1HN-aq(~kno*Oc5Uz_A!&=yCfq^>p_34ilF_(}5zcL~7G7ks=xuI1GIo_(o`;rqI1VpX zR@BSfb@=yXyw?CIqYQjUJ3m_LWv)4cb=zuP$(BI}beu3fN3pnjf?^x0jan|hmV>JL zu01O%4T{B%f4%_;##`&XHU;R@-uAO_KaAqST=KuebH=bx$5~Y{R^eZXEwCOnBD0C4 zTFkmdMzgOoZm1ZP3N4u^KYYrRzqjm-vC5mj%gkiOk8Y-|lg_YJO)o9YZO(FZNe*4x zbDaYC1S>|g_EmE?|EbLmgs$POvZAp4o>WRWo)~RLK@xWuW4uEm9Cm@IljU#-s*M67 ze#E0q_^)>Cb65V2x==X?>|%8iej2JTuBbGqR>nW!X|%XeSbYs`ZJ16ZIBw(J3Q)`p z(jdg;~5Q0|;qWc$BNb581cb{bC{%p zi&fb6KP4}uGKX zPi2?15>8k`o?BEkQls2IFF*NY8o*m%`}*aV(=S8>#L`kLhSdrcT`CF@PzAPyLQWhj z%g})`0dj4;TJE!`_IAE6l6Zm@{4xLRy_SxXx>;pU2T2ERx+Gr#yeOy8`3~sss!!gh zCgCHHel<9E)(x#e4s01Vl#9ao;o;e0gU?`Wt$f8ns?$S)d62oRIrW=A`X_X+8DCCi z^j7Ll--zbh30?prsCK(Oknnz=TZ@>`W~gz) z<8mX9g;TUR8UAoD=3LJAFbdMN6LFTMCJYT|^Jo>W9feIfhRTEHwvHA~_(3VcfN?_= z69LIMgVQ^_Ub>d|d-S(fTW&5`e7`JCgP>b`X9p7cHztxzm)+ltdRj)B2-wprxS-fd zN_(}kgMla_AhL!zkZCmjtBD zNwzU(DbhAHxQI%4l)<@0gLgtC;sfx=0de|Rt4?_n#cDlS(eT(I{Ewa(Mt2(9Wtnrx zL#{AJr$oI2y3cw5+Zjv`KOZ0|cmOs#x9W=O{S3=d-u1+`wL}k`)x!+KQNc7_#rhQ` zPrr^m)WP)8bW?TU&l~&hHN(XeS_~$Qalo9w-^6Lnnb+0oS_+}8yC&1~#Ycu=0J7lr zdFF>-CBO}>tUzV)>uC<%nw2367ZU2qKx8)zuCj(|X4TR}K!{6hZa#hhnpj&~E4vz+ zs9#`sBv0a_@~X(RcPdrlRr%}Qm#_6-K1ResG8)u!q(enXzJ_rT01`f6e5yEw(QPTc zx^cXvF9V&7Ta(oWSl1{8f@b2uhCrJkcojqYcEl%w^>rkdK?t8;T) zT^e-51F+RGbH0k~0_EcFt`dlIT><3uF#E;j!?4<_b)$+0)RS!`stjBc=oyF76Ln;( zo_>!)#=~FFI9R8+h~wb6UQ$xXKmvPN9 zxluY`@BVyoR$~}6se(2Piy-B^4;io45b0T)0Y^UMBQ7m0VKp_&QH@7|gzD?-J0>AT z4HdQ4Zo|Vbr`ucSnm_}5fC$B5U8tBt*Q8gX=pi-+DKqKlk>V!i=0!?uxfK=X_O{=0 z6jHRi^8$nlu^cmvea(5lk@TuHQ$Op#uc>(5^=Q3A>`-;iuy)KO zU&aa(X`F`k#(Akwz`&v0yYj@Gv?Pm>e0Y3}hLTv$itvOGnR>+H-a%X9XwiND;p2eUEJ0x6PoE48w+19H1w zAI`me^bMM|^M{k^oW3A7Kx*~6Cp)MTfw9-(mJ7%X_g|9gJVU}@AqJDiz>I|C z-CS(=C2>49pS=OJa7G8$I0c9-xDy9>Lbu~^e!46Ly>Y6)7pXi(acruV7Pnh-t*^O^ zyO!C%oWW;gz~Ip*Zlc*^(N6}3lbfAQgbb4(7*T9zQCv|`HI%pSHicOq0mEXN948@` z8&gpm8`VLOA>EscG6lFFc1>p)FjX94vtrsQ{nT1oSps zHoaVcE~Cfe+4=dgnn~cHE6sGd4*zOV0Kc+POkayCGRyJVus$BXF&!;#mEo7^qsvR6 zQUZB4P5<`w)aCwjJo@3s2It+@V&ccEt_+0{ALY&B5rCHOaR)+@0-h0ydqg?H+qQtr$&@Wn42GNuLSYA)YgI& zb%_JbG68HWaZ-&%7@(0xVHqKqN( z(Up1=Er0nRM^OJgF_L1FQ!|q$;S)0rSpNZy4a!da4`avZIxj74tgjDz<4*|uy%>mQ zKw1Pbi_k7ajQ{}#jYP0k|8o|IX6yj04iAZiojq4o`qBFDSs$jHgry&Mon@VCuPKaQ zbnV?f|EfQHz6(a<@x<2?qWA@^PNk@>g_?+>=EX`nk6GYB=EfVIf~5%?nVK9N+i=lElSitdir=XcJ?f&djo#HV zTp?>AWa1ohghfCE@c%#&fZ{A8_0)5~s3tLyBlc@09r_t6S~AQ{XmTIJSZ#}0Q>C@H zSAOARcV!3fs`iRnDbI*)CF@dh_*lY>fZXTCXVB(S8WW*|>Iv@trNEZY%QBN=WPl_2 zUb!S6os@Sl{u-$nTNE7Vj#KkQm-*}~E~jmIMOpaZZk<)wBp|1G32t`XT)61`GMrSg zX3AhrsE)y*!^xp(R(vus7AI9^E%|vgmDAc9^h|D~$smvQFT50w(O8!b;|!Pi*f(fs ze4Ks2Dqn{!w=<`vtgfL{a_rGa9QtXl@U)e;hoT;KRWxDeEMZXm zus9CpneWo9Ls2{^7;xUR+cvVna9rZPtSD^gcUf<3Uh3R*>&o1){6wrQ5i`FP?@rSB zZW50Y7nQOo+2Grs^DX!U7Y8eT30UF(rMCuvY7mu`R8B zS0ghs-2z@PC8B^UJ|ql?p-q2iq>GJ?wvGUOT5C@A zuyb(1fB#YT9aFERRB`KCKE-M){0AEBB=xncP6kQ`9pIrbs&8!M;An{7cW}I|QHQtz zErf=Pf;v4tZThkPGQoS<-3k1B3kf+=j{a|(TZycFCh;;Y88UVj*8~%_<6(KV{wufo zj|oaosj8M4=lcYC#rlVQqqu}(G73>+W}7|ZDQ+WDPmY4@ZW#RQ*H@?)bMcH1W&<8l z@+o0)K%DR2xz?aF!=6o1O+o?U9RP{Hgw?sf$DiHV*%@9se+Dnz8SdW$!tC@11*}F2 z{hyF7H5ehDFRu)aLwk;&Vda!v`p0GEg9avYOb>>*#{ik^p!5B8Y{K2F-A}Gz%u$4( zfgaU19D=I)B5n}BUz+S5UVXW$wfDK_OqtMdTJUbj)nu<%xuV9)2@J!hwA*HGX%M$gB%~L~D7SRCC0h%6gBtb*862(M zFE;CW34A_p?rl6GOgy1Zl8tiNYXGXg-C(D z1n&k&iVkg;r2W3Tc?Bl|&?Uu>F0fhb5^&EdF~7QSGC!$EYQPl);6gm`PWa^|mc>U4>F27>@7i@axo?1mXBNwzypH4-vh)ZMM2VVv3~0c1c#MOE6Em)C;4R*j1nqgaIu zhMGPqR@L77 z+|f1qw0%C)^%?oTz{q=uep@>h=`w|)CO5~Hq6|sN%I)nG#lv;N1~#6KXp2$2V6OMy z^@UusCL+Znk)i;Q0PnPv*nJW zrlO{j0!!<`1O8BadWUb4gr+HoQHSTML-})N#lfK$TzQr{bd|yWT2#eBzunnJA|*Dr z)nQXF{-`C)B$H`;-+Lm;W!5A0N6v`&5`E|7LK!Ea4?{24<0L+kQ>RI1iyE_U0+tGM ztbj8Vg07ie2At!H%1rfQ{+#w4|5Ka(#Q7b2XD*550xnz}PblCJeH@R1kB>iIagO1( zw&od@6M~I&N;!PnV{p{n;}5WJHnz5bcDx!(HcB|SXg#Y`liwE&Q^FO}L5+H+xTsae zv|^4^E=dRxc@*W)RMiao*p~WLzSaqVIz_F({zUE}kDp|$O4cS0%XOxCXP(98MT*w> zDGyr6sti3HA`W~ClCe&dSq4&|F^@PmH$jU^t0X>V;r{xv0c6-UaoQ|3|J?Nhe|;w< z72PeKPzeolbRERb1(XE0N)vq&xRkhBt3bT(xgDVa`U~-S0qrmfuDm&@*pr)mVnjB0 zVMgk6#bjgYg{vSOmg=mq!wckr|~xu*eC$caHZof*gY$-JQS7w z`a^aA_(sI9tfJYYg=a!%j@vHTs%^vj1-%csKo&Tub?8diz=(o3Dpuo5ImaT88t`W? zo3B;yt7T;A&-=UzBlaBfAXDzUocq9%fzZ-Ql*H+3*`d&H+&HsFO7vFvMcm*Y{jC)p zyw(y7f}EctYLLkjlGIzP)>yF9dm3~C;E9QH{_cZc%a}9b6!CeSnsagt^5OGhK48tG7g+^{Tsc<|Q zSqZpHhYV4)@ktK^H~`QWd%$i7?0X0nsa2_*l1V1T7k$5rojn5_`Di3-a3y{bDR=l< zTj=1+_v;PdobUPh@E6J3R#PdekH;?`Y6`A8w4dSx@Jt8^ksx%^|BsHEW!C_IlhgJv zPvqy}%rZjwcTv+xT5E=iba%`LPISITK0yH2)CzG?4Si|^OedT+(yx)CfGtH9=!~2J zZS2pFcm8#Leo}tt=@tJ_uM7ukWd#@;F3!m|>PzB{D27eMg?(a;@0=rHfEGYe~5nSL}d6j7y!p&TKn0MhhsRMel~J+lE%EcS(QgQ|FY4lxWidIp#!&YgIobb{U9 z;9X~JT$hU#!>F5vAE9@kv)GoPo{r>x8tc)gL z24#-eDiUO7{hmvfTlkQ|R8&+~&z^ol24Pr7JYVJ()G=@N-9)8&kU1S}w!T|hSS$gJ zMgT#eLN}u|Qp^Kt%gC z1=h&G1!oV}Su3F<#Lj`%D9)7kbL8l3z@X0P*5*B4k_@a#(S4lQ?>K@@1bwL%Cz~X9 zx}Fd(o*>eOwTk&Kywh;)+QLSTICLo-WKkp@b1$NlZuZ7u=+x$-zKY81>T20YsSw15 z_+PLogxp&^SPqE>W_OkJ_`i%%&~nrM2r)u(k~bkOSSA?d!xLRpZCA4`nzZfhaf{Ij ze0e(MoXpk3NYVIR19*iwS8SnuZ1UJ5+{9@&0&otjIH5odERh@IG;9rQ2g0?L(u!rM5P8_Fi;ng_u{l_C64iGA5VWFti;dB6uABF&_X`En)?wz zSoofopN^^&pA8V9?vOnb+Kf{Bt}$?k1RqShPZre%@Zn9#hS11OsM(xe&0yS+ z!14*>jQSJ-LyqEKA0iHX?DIbm6Q-2IqF*kUN8=mwgCm$Q7pM%v0~O{SwtEb!3mVpi zCCcDjLkA7|*}&CWh+t9+@9!VGfT#8VNW8aQF}dLEXtP}Pt7v;$ee8ERi|SI3TU#V` zAwP#*1?zE3G|6JD{>ym8w#T^T0vGR}Hpt*0AL_Wu9UXVe!;L#hEBDnZ9nj$L}taYQ|c z73m+8bX0_3040M}+2jOjoSXxDT}wpHCXf}6L=@nhB`lAxd#J-fqRfpGUScUguH-%h z?h)$SGoa7%2Hh=qSGK5ET`qV8 z)w_x;s>-W5$<2lq`Ws+nw3A9WVJ;bUgl=beljj~}W+gPygx>_fs19u<{F!-o_`It0 zZJSAOY>eh{b5l(uwPGnBF%*-sxCtr$LJ?>qMN@mrXWkU2Lr6bDA*Pwn6gT?VD}LjZ z-Y1U!G>=ncfmiRyl>RH%qL#s>>?FJJXY1r)Suxe*(2!(Lsl(y+zsB*>Cf7>^<3!u- z3EUZKjQCajDc($$7U3`z_vePk1sxEcBcD%f8K(eLL$cEbk$nvf!AnjkB4PwRu+>1x z{Reh%qE&WUk_{CukWR%tmSZ{u7%ot*+r|+ix#sivZoN=mQy%A=OV#zhe))ORTep}Y z!Klr!Rjx7%Mofl>*i>Kt1qtc4U1+=|!AV}7+h{jHM{lTLj(HxRQnN}bQ%(@t!$-sJ zWIpZXZh)YpM1t_jS~_+XJ<_6eeB6BOXS4L#1K)6rd0k(ko#UQVdzy1ZJ}N#xUgfi) z@nh=;_ab_FiPTh<&FHU;*U1PWO!@g$B;oe$*4$OHFKh+%< z9PBQhm+igsc?pigDSwwjsn=w~kYBBc#%4*;h7YZIDuZeh4ByriB84jyi+h5lE`7~< za@{&VQHj$ntvu$NR996+$HFSo0`nkCe#;W%5NN18UkMMpY%}~w_bhS-lY-7>f&F`T z$nkg8H~|Roi*lUgALNM%%8!gFE-M4auJQTw{)6(**g=0v22y#N6wOC)=6P9`)ItLv z5-}Yj73B7Pk`OwSK}|PQ@wa2$3ca$_Wa_InbV!UyGsMIDy5`ifr z=As)KD)mD_8`Z=8#;)tVkv&PzDns(y3|$E`q_F@Jp}^YA8dsMn&4>{pE5O+R)*_~L{XOMwGc+gy}x;4I*C5o&e^F00h(K*!U&K#XV zONmi8YQpsO?C7jos|MPp_^JSiA4ANB^?k#~Xq!zi#N ziDeDDpf7Pr*_D9T{WbMK*;DgnQU~(Bk~$8D1l)ZH^bCz{HFz|FRI7;5^C3V>w|} zTzRZTELfyL#ho(gI@9emFa~1MU*-`n_+z)zsc&5Wc_cEC9YKl``}(R6N${#0T>oVz zNl0ODZ%<0vAJY&_&Xu6{VvCz#XX71P4a4g>R)k2|=qmLV);7sZ|m`Mmt8!|fvXT@{_9z3SueGFJcna<7RX zj?m-V`eNzdSf2XaGm`Lq*&T@l5@d#nzsBxtVj?I&2m-CPM-x6?C)nbIqz_xh_^-=f zQ}$FHgPw&d%Eo|K66k23U;bnDUaMM9XhwN{+AP=ZFGlmLU08J;8?`M;Rgb=ufP)!X zSQNLkkmE$c{O+#3xT@@hYVDDG))_I69oDX1Jv#-#pvSeHF0m_{f8ezK<~?pk+36s0 zv7EwvXlka)<<>SoO3cppmw6j_IHK3tkvI~(bL_7-3H6n~<$hb0Kzwf=*8M@o4i_b9 zg@-gCZGhgNDYW+o^+z})B2@501XLa#nMJ?vYF(>HX93u*pKY0fRK)WG*VH)T(YdASON2)dztykE^=J8QS@#KzA)A?YE zAn&KPT@Q0A8ygd+j_NDCe2*hipgr@(L+SFeNqY@PQ-ktVl);~>K3}Q;^X!%#uwnx3 z3G1d+`cu&>K%^CTo|`pCNANoK9A@ZQHCm2|?m4^rBTE6841u!T!O`I`ek`mC6K5W&@l-pqK2R__6fw1-JHbWIYyvK;Zb=@Z zblB!cap*j)3T(slgCGz;;aEwn^Y-W%Dk^wwXNVn%@0~bJ|{FO_!=?o(1y0;R`x z%&e#G8#6ttxb=B&E%gu(T%@>OfHe`nDxwdywdHnM^Iiq~L}n>7kxpUaAO~UF0~(Q` zc;%o`)hz|=1Se%Qs4RHJ!~)ogNJ3;dwl-F49Ud+~YnO>>j2Ts8v?; zBDx4Q=a>B>S_!f2{Z{SI)WS>Kg^x{{kwwCo&#q0%COp+Zqr;gt8THTHmoY+mnzqI% zC6ifn-N=%X8HpR!uhu?=Bb$cKGjl>j?pQ5l7j*oO=JSW|uG4E}x8S0#ANc!O1Pb1V z)Xzw1^8#HHJKs>@(F?HccX?ocR^xIJL`#swP%j|w3WtnN(m$;|ixm@_ef<@4%VkN1 zm!AIvJe|14Jde5M^)^dT3#!gcE-0PH-Btrf2Gee>q;i#xTa z@c4loQwUbFvk7z8t+P<=pmDDRM>bNjQ)r5J^gkJ&w3bKo8Tclqcd;r*VQ^yfoEDr|3E7pd;v*waAuAgceD0hP=K8t> zQaqj0P#q<2J9V004rQ|O`5tM>E4dMMGg?kSH|Eg1^c8l9i@=^%$UHt_6>2B0=sT+% z=JQ4;w0H&01FJgKKcC@4s{~0tCr71KswiO7N$G#15s{t+(1StSk!=f!1M1nIp@ZRJ zGlh&#AeONwOlYMdZfmRS7b+hgQW{ zPFE`>0F?`+>(gM|PuJsDLsL`TGNl{oMs|%Vq_c`;rhz_%q@!!GW5u8>L_CZ6Zak1; z`O)UmVE3lgd0DfUwJ8PR+{I!`)!u+BWlpL8G3HuvqtoPi>q`a23?_gz5Y zU-k|8+wZ0s5AV-qJ`Fa<{H8jI=aJ_(E(CFx9?IUPO_&NNKX}8L3fPFkbieC?U%c6q zNQok+HG+MBuO!0=?La=Yrk zy}wfKReh2?w=JT+6SEw~o+TjBYrXGT!hbaK8T;YtA*mqQu-l&23@Q0?nzwEcM$V$j zDlF9o)LO$&zW<#8ew(3%s?1CA^Dlg88)2f)n|VWvdJ`_Gbs>|wJ&6V0B~g3a`iA1M z1nG3iuyuP)2O+SX5IpILh#fl5Om`P!Z^}u`D2St@qXT_tAbL7dZrp4ATrJS3GT1jUyRz0VuQk^L%bf20$2_D0z5Yi99P!}8L)4yEH2J?<)g(@ecgh{}I|b2*6ym~h zW5hauG-fyv<$o!)KoAjg26NrC)57xTX<=TE(8~zS|F|?cF3+bcpc)1eNhbwfZHjJH zlNy0wAJ5(K`|X}q8HG9wvvDiz9zJwN#YT5b$BC_4SNV|BYlfD*;L|XP9i4#PIw}~L z64kAB#Z{jhy0Ag;xj~zyz>It8<<(rlkHVKBp8IwF8+*k`y*(}a*K~3pbtMPW%(^MW zF2sC)0a`&)l0OEv7WSh+Ia!Ofgz7)6q0hIF6>^WQZAY?z7JWZpNEj&MLbouED1j6l z>;ielt$Z;;H%%%VvcjvDEysA8?IENP@690iiI+v7#Dg@*aiOxoKPDEJPZw=`+hti& z5At;_@2b|Ahq7)fef`Ji&`@$a!9V0SMSWG@wdoZ=0-E$SGk5DWDFMdu8;M-UN{+nO zbuOf@sT}Q$%?8XClFw7$zrMkWWsx6l` z)2l`_JvHS&Ah{nrab;>oscW-)oJ7tCZZZX}!X7E@~zXnOZWs^>?SZ57udjrC#4!MV;+RI<9ihdSx8fOcCX#8v;0Z!I2~aVNB{d z*s9&gu;Z6Cw9Hrp&~M`mbBK-2-H{df=CWv4S*N5@f`=g-ssVAYYArJJY8f}^CZa!oUYm>&*K{#oO*tZ5;^Per z7n;FN#jj`;@jtvAVPv%(+jael{&%Al#DPJEzP=VeesumjA-5dhjJhiW28Z{Pn8D!H z#*J(0!#5H*xh&1!)I>(tu0Z^}oq_@#W}YHDj+CYDesLU{%(8nL+NrZpEYrQvk`-GT zlI11d)QSiD6MiNb^=JE7ufo3jLE9Fa3KAOc@{TNMJcJ!9Pq9W&wD}p0u`)D$NkMtg z6G(3&q5tBsAo7`OO_k521xe*3ZNXy2&SZ)LnV)ZRa-%Ep_FOiFOR-LbYh62#GN)JN zVzkfBgcAeAg$xXS%(w&LjF0O~gdX1~phPoymrD4b&0L3Ez{JS@&LiFC`R-_4IAsBems25m5COe8cn3 zrKQR09VRi8hjsG#NR}MR;K{|zS*e8$4bGxq9SM-X&40=IBEXdc{k+Lcet>TR);I`w z?e?^Wx~0hOL&aCrX+3%vHycBXTVhItV(7H)8Sj{Yj|tFok1q9#XSW+H#^H0)e3OF9 zvrF}i&wfjpPgA`EWh7TbaueC_kwhR*hd@22Dv{%Ly*bH$c_@Ram&W-u4~f6(?Y(M$ z@mHBt3IcM5`!Z5*>WWmlxc{({SlZJUs;G(N4Byk?YDYaRScn#dZTu0R+-c~;J#hmFC)}$^*sOGuBK@tRrCjL-1>_k zkwoC}Xo%Hh&3ISS&RQ0|uBWk~5SI5x?#=jMyr3Q6x%!oMt)k~=*@`)v3rlZ!_br7< zob(2WpxapH4T+N*=SYrVGS9}5TPz_3ULufzUL2bTm~NH~u3)4^4o(h0?+Z8Y;Zhh; zlBzXzWx+!<*3-vG{cdwtXzOQCh1pL+`eqLY|10gJhxlh$?xp1naIijE^d|otyxco? zPOV#Oc++bf>P`9F?9Cm$g-8PF6qecAg5PU4xQ!E6(=JqW9!$UWZp?p)+9{^uYn1;8 z9*mu|{r+x-Z+F~OfW-*G*RdC?}ON7}!KAAo$)c1X59bGZ@Q^&apxwtCV{r7i4a zMKK?A8D2iB#1C~dz>>j2n9us%h{yPQZe1uHJNMpW(LPVs@#0_9uh`hjEsjN-mx8Zn zb!DZcbf=;ATit$(n`?^c+gMiC0`AiQ_X(#%PrSx8{72Qf7$7_Ku ziQ^qPT>qbFbyIcxDWLU_mcPH4n*CTgFtJl%jYy3C`rtmXp?;B=Hd)-SlEJdfcHD zE-VmTy>mm`w@|kZFt;!=c3dN`hYJ_d6MRk+_QkjnPa#;Wvw?{RKZ94$9BD8!ehwU) zNj$NU(3^_>6Ka7f2ZqH6@QDJWZYwU^fLrEJyaN3;x1tSN3@oaHF6= zroTi59in)>+@2t)=ep4+bNDHjV(y1qs={vdrLFr4oTbFVCI%51Eih|@|5gHi^6f`K z*~t6Bk9+-0`HvTb0>NxviV|>&?KxjeYZ>w2-5y0IywLO!GS%b>A&_E@4*4DDm>3iv zp32*lN-xsdx;o)+Kr9vY2rT1@2Y_C!{6nuAZ}?)PjM+3~g^{Rc}Uz@edE zptBi_ON~6w$HDYy_DY;aPI?9oB2K=}_;g8iTuMFjcFBJjcJL+d$uN#`Uk1age>fcX zcF{konOC>6mu^?Xo0Lv-A@oC#yB(TmePqE;KK&?AJ#c^Kzt75y&2ra92yhPWCmBG4 zcUIaM|Lq%AD%!hk!s6z@!Vj1NH#fT6HmAhQ_W+K0Y9F~AZHNv$z@jjG&-KZ#C&$kZ zbTm~UzaRo6VwhCk;UOd_Xkg=Fp;Ux;FwQ&N!dC|d%HO%6q3ze@4=by%AX3E)%{hBB2H-dbrZ|By-7ev(URHti%bQoYgG|ND2o=4|xSG$tc$>HucM+QQ zs~Q4%A4Aqc@SOk)NS9PLRAki}NRr(M7fd=nJ`NByrMbyc2po!WyHB!K+GJd%0LNgS z$C;zdFT99&(qn3jPstm6x7nWOy{q)B-6j3;ac^RmjINvPj945zs8IGHul4{($k&Bq zu0jrc6=j%jvdGeK48z=~gW(FVW-Vu^KA++@os{udjh3||{r%Krj{?3G^A}{IzbTEq zVuhrNDfJTO>LWU9D_o|sx}BiFg#0;Z{co)7$q( zb=pqI(7rXiFY{SK^LQq^AD z3bvGZ-c0l0^^>hZcSRfDFFy+2?)53Myy%&cccd96crFLw8K2IN=Rf%-!}zPmAmyKZ z^O3}}V6E~T1@v7vCX*OGtcLB=-_D-ho%U z)3S)>FI;(-TMm@tokuOKiQX=H57>Ie81uzpHPB>{%>4md*^XVx?I-G^nCpsjr-uZd z9M9)P`}mQmWVI#g3Wy?_dj2?Wk)nJ*Mce=#fQS&%M6@v6#B{1B#}E+r1E@*m>+M7l zaPyV))yNVLr&UKSgzAD0pB1T`uC{uB`SMjQEt*Pm+f!GWIT^vR&|oJpR8X0_%SUp? zU@%}+pHCkUuGtm?1Z0(tiatB^_YYYkE}wkQgPf=zOzPfJ3#Fe;PqBg-Eob_Nru2{9 zj-@DyNK4kJDa1$iG7{{}{#h^Un_39-Ho589Jg{%gj4tqDH8 zGa`g27hcrh?jYJ9;K_DST}oEK8h*ISCI1E+vvA69T9WpB4BkMoIU*az|??{$DHSA8JQR` zjpw3Ra)%d4$;gcU3v-eM!kkEGPvaI3swyhH&c_j+A9`dGrAwGVIdEO&VM5Xt78U@f zAF!;-sYMRw9YI^$C0>aL#375zZa4c{lgHGB>L@QD)gO0l7JuxR-cM@JCo;%gg%n_! z(zmwRYOj& zLU=vKysVkee0sg$_L642i)b~|AGjs!7U>kH%8jb_O7askU);FdT=mb+!A}%JXvfJ@ zE_Tt-c(kA7qmQ-FE9bXgPk*)9a-=ywkct|OTy7qDew;2joRB6)3|sif=`_U{ukxbcu5a1pliV;NF@HW*^v?Btiq@_-LkZsmYTERi6PFa) z@?7s3OVtIuSK2*BSpn7SL{%iYMF=^F;Z#fKR?VF5^AXbA$0xIC1flkIHJUQZO&dXU zDHb4w4x;@-#2;ZYy%hR{_I7K_%y{yc2EG5bJOif-0k~7sV>6mxOzTkA`85#$2=nTB z_AU_R(hj7DS9Stj#qWD^x8*AR8tuG&hZ9$()hSm(R7ZIC$p0FoG?E1aM{=%#gAaGI z{9k2EuG=^Gb3ZpdP6P$UTV+4a0!?g#Gh4d71{P%|eVmqCx-@tm4^Y)hzR6fvY5X!IJO}0bcI@CHw zHHas1^W?cudEY<({m*BDvIiq1{-i@TIO-oJSw&qlt09j5^$uI3(0F!gX>N7)yCz!! zngN;!736#`(;PTFQ^1^}N^WJ$oH(BFhI}BOl|ISJKhIB07gwXNK?VT?hXVSL-+|tH z(`E7JRr5`xJ{h5QQGL{(H;hh<%@U3GrCJOmdg^zP9DW65W1Py^K%%UOiGjf0Nuc|X zdB3$Y+xeZQEx$-lz4JEyZG}MXdrC5wyOq+RD`&$bR=!*N9-7$4(eN3PxOsYt$9^do zUWOkYeDPi#%ae(diGiy@PPb_ii-6bV+jS9D)D;If+`Lrm85d)@6hbJSho>Z-vYZ|Jp79UwLZX37&aue zyP<6J)+1LY^_4y^l=eIIDL=0oXR@|rfDP}^BcY5?xA9F76J0Np@&)1#A`#J@Wn?pv zmZROq=3zn36S!x9wml_CwPwkdUN=(f3dRWe;p*xjWYO>orwX-Q6 z!t1c0uK%j>St13N4?cNYOZWKr$jQO({L3k*&ro-FhmFSoaJGC4t5lr&8c-2vDF10c zrwE!XMrsS{tnK5w`n^c7P07p5|78WSph3S#Q+XJ2`PPm;(`7XsXocxI;$3;RqNMSk z)Dgotw0FBmPP_4rYhBQ5B+yIcw{bM?dleMM(Pyfrk4y3WUvXa<6h{ z1VRWTxVsZ1xJ!_M;O_3hfuK9Jlx~9AD z?N9FaopWx>LOP#Ii_}L-oM4dPPMD{-r^}$$b^o%B9xb-Sg*$u9MW-aK?O<=1WG6<_ zHO{k0+7mEqx9pf?=*Y#v*#PjF4NwYHEP81wVPKGH_JEPjWj9x6H8dE4s8uoeNiHoP zJsmE}@yqQOH#a938@peYbJpNt*FuVy=;X8GR?oPB}J8ZtPucr{L^u0CDv$v z>m|Dxy@%pH5{9Go9yIau9Mtr*YjN=+btAE2-iQG99cW7O$5v6l{D;Wh$&F;*58FLF z^x2qIawhk@ujh=RcPbXhneZi4%~ng^TwPslYkQoS@GrD9mkOGeAe9D!cU7P(NdbdH zStu~A9&`zc3ci?U@qq*xzzT7qEWVXDo#&U+AGJ8K`Am~s36S9xCkH2k_s~$%Xu>;? z!*U8``s7=ebP*CWDXc5PZd~o<86(^AYCMB=#ofu*_+vs;wl??F(7|&$R#;(i^Ux@O zU_}5bN;Qhq{U1SY*}Hdk%L)g3gYDau3$x`-Q+#pr`EDFEq|rxqft0UM-{Ogx|U*AH&TrR_`EmCGf+z&qYC6*sx%Aq`_`Zu=RzoJ~hfEMN1Q zyF!b75HFO0iaBxgvsK%nxHAp&&CJz_HJ$Z2kvWjd#ITtzR<-NK;0*`AzPKj{}=y#mhNxsIhCOw^Z5-?%CF3T%{ZVb zL8w0*V7Aqop&jS2Ip3-XyJ~Il#A`1$&1EO$n_XC1n42gmVcN_w6ASOf&z%zQQ88e8 z=}xte>R`HI6e5kFe0YaBqa{|xbBKvX(KdG(w@49PAE{wiuBy>|ucXHN-A=KBF0BB`~zt?qfSq4LpV2x5sL z{s}5HM^$iJ#x{0m02Fzc`OiBg&1MOBw|R0XOv*>1YtT_-U;m9#|8|siY;YH=zKyUq zh7S(g95WdDF%V+-E)uyInyf@qJOl*lYOTG6MU zQ(T(%8E<4Z5jQ&ua#|4C*dWVrzzw+_e_clW_TCgq{moHB0`#t>U>RS%nBL!BPOS~Z@}BuJA;C@2C09UUO= zjO^E?TN+JH?4B?6eO=B#iwYrS+WXDXx3{FUpT2AG-IX`| zRsQzV{80F;p&x~5@a#S+iNjITwvI*+pj%@obmpG#c2AMzsJ?->+1TD*o=#V=YTsB^ zW@T@$9B0Orsk;70%z)AOCr9)*ixy;)ARqe7k}xfms$=s>W6iu7&g=n)=xt}a654BP z!y^xEc!;e9Y=@~V-rkeZ^bJU8;bhZ9C_Sm73U$G+*qWS7IGPpwt~!itwi@R#oj;FO zOa*EYEplxn*xmTB-cs{G=b#KGX|Fc9$k>}9t z&(RW8ROI3skWYGg(A0MU7J(Lk8GETDROe{BBEKzfJyW7|C!Qm;?m<~v0CXCU#>5zX zz~}`_*_D#J;FTn9w^}P&RX-1P25tV`M_!9_Fk>hYM5UvVxt!iJal^k{3?`iO^(6N9J;dBDyUUs| zy79Dj(gK<6ML$Ew*^1A+>V6)t6Kl)$5x=~gichgUFyWPzEZ_0SxNT8L9AFCE+8QyD zJztcBE{7NF1fG(x^05fdsf6`Wrc$Y?S6%~qJgu#*r|ucssN>*+jJMQuG#fRStP<#W zQ8ho}f(;gcuC7_P87sjc(g_aPe7K_*oVTszyjB2fN$rc1fYFL^y~(0PA4&$tqIn@} z*i-Tt*OAP6xx)ya*~>g@9*;chOj0Pww@Xteh4+2#ThSit@ppI%MWhf|XD8Wv$1=03 z8v>74i_lS;E0YS3nM8E$7avJ4r1lL})%7P`O1s|+ic>rcbOa`nli`|E`eFk-mrhR< zSYukL1Q7~z@j^1q$m(JoIl>RFE$?-1e?yOXwlkc{UzW%L@4=o2n{91EnhKTV^w7?4 zq1I6k&{1He^2oqy@#`zfpx36FZO8u_VD#bd^wJ>}NkHvf&SY`KoVHMqoa9upIBLLd zMCEHA&7k@`(XzwwywCb;E}F@ytsJ!1EyLyPEr6?^>bDMMJUIQ%66Imo8)wE7D1P&# zDFjDoX%GCWqtZYkej4w?JSbA96o!BfZF}tDNSt#FLwVzgvs1-i8f^%BAvPDMGXmD3 zAxSw&V9XBXXGV!(*`ig|k=o1U;HPhMINnUTjPus@QBhF<=SSAqHhK4|eH77wE7S-? zBp;6w)^USs+pw^I35W(#S}p2}i$9wZ2Dr8}T)eTj5|a(K-V{ApdD^ZI#K*OlBpT1i_xzhFQx0_Z?B(-(Z`eq0H}U)UZ? z(0HG(NESzcYs-jo%ZNN?!_d2IhD-$Jj}Gf` zs$0g!4mFT6mnw)o{$H=UGAa%>wpO1sh;$8zub&Pe!V41y7f!VCIJdxjCCba!WR+imQ8CmndDEHGIqE&uufH2<0 z#mdTx@l_z{`&Y7hEyJ#35N~Z;!IGU}KfL%)Z*q|6BJk;7dCPu^#I<^cWGfR%KW)JB zW5d(k)95?@cp<0D*UoH~Zy7KK_p%IL$X#u+m)@o#6CRAI-^F*$dAHL zNW*@*t}{Ql&v*}zddFxp1CpXfk5&S3Vr}6(p>^o|R&D7)n%d{_g5j3s#c#-(Jh*Cc ze;kw(QCihH#gESMnzb}gSi#7AF1pN(mQSw7!y%cOJ%^lWg4&qv>j}8tq$~4%NMM^A z2ecb=$G5`{aA+v2<1=JHq5x3_GSmOX4h3!(arh&)rRxfIH@y6YYIT)tl5QzKJ7W%T15j~2kLrQZ?jOo{_%{>#_(Qj zQ&X6K){+Rh^M!YSmzP&g=1*O1QN6wD8M2w6iToLEF`%>aUiUJT(&lef0E3IWyIlya zSJQ06aKh)^SAu~bN4s{IJ@$@gQtj$92YF2SyB+G{PhlHDai{C3t}~2L!iyGz-IPMI zPFvRXB{RJ`ht_sCULDqJWMK0nV4v<)jj^p06dC$up&6?V_#DHH?@m7Rz*$Wm3ex5BrZEA|Mw>FuF}5QUSvPiDaI_OYnM9GlA*8~i`?`a9xhNQ9!X?O&*vXx4u!th?i#h0VQuND@)C!N2Yh@5CF4*`> zfQmc5#d5cJwh?k{NL^u+KUVqjH|jp5MHhhK!uv7gX`$H$LPuK0RPS?#?QlsWG!&hN z8~ncVbX0URj(&Asg{LxgHRbq|^}VhXUUt!TiMu_DOJg4tT`VU2!HGy%iK6_&oA?lxzO86$gb_ zAzZB$FXR}KL31n04-Xvf4-S1`At7O5DpC(+uJqmNu%S;xLXRSqA_E$*3m3&IX_WSH6%3RBg zf47XL)YO^%cyXttT>3b_zt?>{J8KT&{QaYFl+{76T7t(8$uNGT?euvX>;vCN7@mhM z%=oftWRPA{&uyWCTl^>Bcs>HthS>IdWa!6G7fi!@TJi5xdS;$LakY+Wzwo9I7bJqx zA-%(fHicxqD8$cCMv3cMS7VEO%wTlq<&Fl!2%E73^qF~WvmLE$ZGAVBTmBC zberkwG5u_p;PIjyIma))H8r8fH8!17etGf(+e!E7b?I%b&6ZTnF?R8 z+5;Ry-2fT*%;`rSpqSBq)598=$R32Vrge;@j6XvFVBOzhtLd4UnE^n)rmelP(JW0~ z0sOx%#gOj%I2`n*Eu_&m-vwAxR*i0fUI9i1bL^7=T(qWciqrVXrs-*U750#ya5m&b zB#ZE9GH#u|zLj?XJP8oJ4fer!fg)05vJk9P zl&^mnl$G<}@-blQ?fcJj(x|Cx08l>ND>a%!GYMnkRlwzXd3utPk}|{ayn)2}?h!!P z+OLZ369a%Eb0me5%^@Y|6_()*f-|e^hb|$;&GoFSjR3KSM@oG`%(--UpX^!7pSLx7 z{DlIOxUwsE2t9pBZj1L(u4Kv1&?Gc+lV`y63{cp6S_S)Qsj5B;3;xbN%CqjZd=G~R z-)kR$0M_Di8e(i<(yymA4VP-1V*NNixxXEvegBSVG_5a7TlQOR_B=!F;MPL#XUYjj0vy-h6dGF0bk6LI^!+b_xko;r1K@b2K+{((MCAa0J=EK(dtIFW=mxDwQd59V& zWF&8B&?1>k50pMBH(~#!>{UpS-gWik)E(mh-?`QGVv|uP^1j5NKifZ1#4UCKffm1~ zM__;T0DkUkw`?S~Y90TfK}1hyR5N8#lAePh$iENyRgx?wwpu<$@CaAolcklT8|3P+ zVac_JAVrr!1ugME^tvPAa5$jDWDBp|G#WAXqkg4SDzJH8_XoA7YmN7nnxrMJ!+dJ# zc$5e#*+oFimmk#R3=xZW4}(w3@Fk7`hjeuEtTdnH)p%$=;}1ehrifCN(!mtv(WZ?b zYL4=fw;H@#Yue}!2+i&mN?-wpFu1Ue@mMEa|;-MjV*|%*ER||G+x0kS@c8|wC zs#t)2$6&-xiCfsO`f)p}LRRCnXY5VZBBhN@6!+xvwA;_e8}Ui3O!A57KH13+X;Cx1 z1J?sQX?sH#4IEEf*L8l64GCjUYphSZR8Om`-C>rOIn>c05FJoU%mO-mE_Pvdz7JVr znGa)1RbZvjQR(%8$BO8&qYA<1hARf}8$*E%foATuI{tb1C;Z4c0U!O>+LCv@fqk+C z8`nfj`B?FcUUcO?4uwK7u>?68HhCNDn>5v-DapL%LUuouZqBL zl#XJLmr0Zw=xT^_9wnlN^x;9H-C5E@ykm~d8QqKj4kshckw>gf{aZJ6Okyd@bJML(w& z(WQ`Vf39MD@#yI5n}$HEPB`C~?oyII-`HQ$!w<=W-A>%!PV8PTB<#bkXU}gh@91QS zuC5Bb8VawEC z4^KW%XPadWVaK@O*qB%))+$KC@87#u^N(t5QNI^pr;pB#c6N?#cHY-BJ4enf4eana za#_zDxUqG`zJT~PAva0rxJR!-y)mUW_mkCaW52f?)g9ln@$y4c+J|hp_zmh2?2Wwn z?-d)zjC4#pz4NSt90aJe@0 zLS+XmG}|U|2DrFprOB)Y414~{aK-zH>ONjnQJxQo8*ZZPu0Iu?bW7(v>g-%v3&F@j z44rOS20C|dcXq6u5x&08Tz+m`N^q)-5v4K6z_Na0h9R9D>4sIZwc$uX&#eX5k1;N; znd?F*Fhvdcu!jf!EO`6VZqZp%qt|t1B0#orbZ~%u_yn0C|2IjJXAEb+JYAOn#EzOJ zDXfN%H)lzv#PO~&p|76=g_1ee4-ji>I+@#iSmWBAck^14F?0!9DTlK0Qgr;6S#X!; zY`MuSw)_IwoYL>+VA*79uusy*R2=n8?{-B@Sl_DNWZ;CiP-av;7k9k$)75Atg8Me! zZUG8gTJZ96`?UaYQ(hl014jz8F_4^@n3zoay0HDbHKjA+X5eUSY;0*s1YVh9JU3C% znV>9-ZGL(Y1Og!<+Sb%O+nJrDBKK~Idz7ZMt$kb4bBE*6%dk8<%gxQrrK+n_`uRs75+ZnO5u>9k{{*h;e+^h4P{0kO3l+8^eXJ=b5yL0Cw3I=ZaKBjp0 z0tPdI_SfmJWo_4Dgq|~ZwyAY3m@h|NLX2smJI<z z-(Cg(uTNHKK>UL~`)VTSG%;2pf`3@Y;f_k(itCJaWNJ*azYhGi%OXVqt~k>DjsDeu(Poit5U{(1@8+pJUcQv7;Sl@v5j{n;qEcyA5%`L3cWeh zn#Qy2b|$HRzge`tDAO1wL4whTp^%4|Ns`s{M>d7pyYd3R;kUVcaJ=eU0Ic#?mTG-*J=m*g7)!yV0k*NBq_u$aPe zem#^LrBUXZGe_R|_B^$KA*sJsDEAQaWrMr?Kv_#J;rT;=j z3;kV41D-`nIa^vts0)LLFKP5Ak2W1oi&>}4<0*zv#OKhlRlMnM`Q?trIje9o>gX=+ zdLswjZu}J+z<8kDhoC6E0M_1re$qE<>L_eCIcT74Qoknr5O*>pP_ZaJh9d@X%YS_E z{{}$FaZ(_VzX;%TLDVk*69mGL0HTBcIV_@@W;g^ZpoF5aZG7Db)DuO(F__b9L&^)} zmz-xGDyB?k<+IoKO?T(c2goa5O@{YuHM%T~rCuF*xV2MMhnZW^X0FJ(lBY&2Q`GbO z2kdj-3=5Eb4t#61XaOG@S8NsBkZd8vi=z5kPTsU|NG8Mr-MsR2NT44s1j@K*#APWP ze>UD!RF8kq=iiffRYL?Vu?-xPsfqzRzZFa4HD%MpvHWvZtQT1jSOVLtXj9n_-!}3Y zjhX+BhNHe_UaIaoA>p{2f7o}};}nI(An5gjrPR-yXcQlegPV_6)@AU}G@TxK&q1)4 zZ>ku5OWX?8X>7Y3egeV&U%=A0QiE%~YG*ZIL1$KbeCs!)|V$HKt8hv7=G7WcR^mIyf{A`Cs{<$q?1 zoP6`3R4hDQ2pPJadzYc~mYF#=xB9fJ%P8bKJsgf1@2bU*{nTQ7=X3eHnQnJWhpP%&#p+{=IRWCK@fkLf-sKLW{VI0sjJU9u6qWlUL0~ zcH6hJ*z0p`B$i|!QP?{<40R8Y>Ob~YV;ssb<&~;8RZd&B6c{1@sBj4{S()P@rHR&} z+{?6ld}WzCv&7=rK1RVC@HT?2p!9dM0&ka9tl&vA(tVw@8gDa8m|?#I&B3k;S?4^l zx&4MikR@9HQe6LQBY%b~;4^6^+xcDK))X`c@ zK1-TQ<&Unc6JCjE=ND}-_U1D<9N|#46E@4Obsb;iI`6X z?rooG;;&v?i3%SvznCe>l!KKaY>59P^f~p<8=e#mU*+3)kSi^dPLA-kU_wVNO|*!r zd4WcmYv^177jh!SJEf3tFxs>ZiGIn;D|h~*<|qoOMAf%s9_A_Y7|O2Jp1AA7`Cm(; zDmi5M{@^#`D^pqiskJnblp(qeegp_a;Uvw@IclLcN@v-W7)Y(dAXdqW*LIN_~6YDweL{dvL|El+Fa9KHIn1~u!V4V%tU zn%G9Kd9pB9I8Oms4}YGdY<%S#S{Yx}FK^13-jSX?<4k?}#FcffF{Wd@UU9WEWB&yj zyLeO+4PUUOB0;2+Mvg4frJY+W3&aScZ){eD4SzPH;AP48rs(?|0%iO7m;8NViB~w} zyNB8I!O?K#V0B0y|JZkLj;Q=7rQkHa81X?@-oWds5+1(yrn6Pk?sHnfCMk>uJ?(|7 zB%d;&+HsbDJ_|4FSIAhW8SGKUG`o`pU|uO`xr#U2O@%hpc$LHhTrEO$UA5F$Lkh;{ zm3beG6QjTIEaGuRE&K4rV-?KZ#-9w*SQC2?KPkdG?qgg2`O!CP^`UYt(H+@oF6}2` zF2^?NvHII3Mj8kM%7cQyqcqrio^_jb8;P-pBuo z5mpFso|{sW)qBs$|0y%*(p#l)d*hk@p1`7-)ul0WblKJV)t6X@w0wvXOp-oi$TT7h z4Sh14Aou8G*vD3=*GGW4m8RN;>iye5A9bO>=*oq}`_(r1q=^*N*WS1)Mlt)=(F1?q-yrFhl`rhX++ zY+}%M3u715Zhk_QzE9H+AwRv5IHHPTjO@b;I(aTW^^Hzk-E~%!xg}Z)Kg3OkRgLbE z+y1|rVUp3gk{%T1)B7xCzfy&<BqX#T)!P2Nwfv;}g(kKW=bI$bnX*it(_+|HH})gOYD z=yvcdQPwcp3JzU5;iKnOB)xS$?2}wys%51gebO+uz8kp~B|V^FM2^Sgvz6*3?d$yP z)x~_1J*N|vikTUm_j)pXGv_F++3MF*&|uh7xKdE-@^;K>dVF=CLFm^CAiXdu#^)WE zn8bnoq>ysH%4S0Udy2g=S0rvjeC1pcZDfPZ&U4n-$&uFKFSGI8Kkr2-$Cm=$qr>n) z4fLDubNjx?hw6<(a46MVL`j+0&e+3*!*@pPXO@3dN?Z&j^=hHo4~GW1*Niw@yFPI@ z89$wE5F#nAoZTdE{KM-eMnnz_)~-@NNyNapt@&nvpitylKAwC(#HD)wZ*19{vqK3> z-g6H1i*5H#w_e<~_^46r>Y0EVQ{-@hAWK+(3Q9HE=LyUQUKJt`n+&bS=f&UCzmi$z zwg0;%E|;J@?abDBm-nuM$qOwvLvF609XciDUu!~}DKV`^qHp=#Ih@{^K3ixq+)TBJ z=C6Fk_E}u{>Dz}UhF!<&02X~lEYkW9PHiv5l_yA>Ux{GJ&?YC0(JniA{7!e|D4W?A zYwo2^J3%Dm`-`&$f}KCu)bp)=CQXqV+#&5Y`C_%c`1>n$9DkR^`eYIp!2^j6;2Pg= zwS9BxyIU?EvD>XD3hBC9IGR%M4a<<~BS(3KB{wsBC z(-4dOs1V&_ZW}-B@ym{~ZfHAZ&=8!KH^}FxCv(delZWYM_NAIvhf($V#TfPZVCmda zn!bxk{|WX$7(YIJHc=J^y9;?(;-MqTv7xGivrd1dVcBVI4Mrc!=f9DD3f=6f0&aCQ zu<$(JHmFYAU$)jML2{Qyz7p53*EdU=1p{(JcW2caUmz(xcrf|BLqX@SgQ!vgeL z@eK^)F8=dm+3?)9vs(lwkQ<|{9si#r>DI2 MsVGq?W)%3}06@0SbpQYW literal 44819 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

u%ZQ1DqfFh@F->}bUdkq`;E_S44I#kG-36_ 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≀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 a*=(4r)lDMdTK7NTr6{W=^Fzu!^#1_9*$6@a diff --git a/dox/user_guides/modeling_algos/modeling_algos.md b/dox/user_guides/modeling_algos/modeling_algos.md index 30d5b4eeb6..d01a6ca487 100644 --- a/dox/user_guides/modeling_algos/modeling_algos.md +++ b/dox/user_guides/modeling_algos/modeling_algos.md @@ -3151,9 +3151,9 @@ At the second step, the faces are tessellated. Linear deflection limits the dist @figure{/user_guides/modeling_algos/images/modeling_algos_image056.png,"Deflection parameters of BRepMesh_IncrementalMesh algorithm",420} -Linear deflection limits the distance between triangles and the face interior. +There are additional options to control behavior of the meshing of face interior: *DeflectionInterior* and *AngleInterior*. *DeflectionInterior* limits the distance between triangles and the face interior. *AngleInterior* (used for tessellation of B-spline faces only) limits the angle between normals (N1, N2 and N3 in the picture) in the nodes of every link of the triangle. There is an exception for the links along the face boundary edges, "Angular Deflection" is used for them during edges discretization. -@figure{/user_guides/modeling_algos/images/modeling_algos_image057.png,"Linear deflection",420} +@figure{/user_guides/modeling_algos/images/modeling_algos_image057.png,"Linear and angular interior deflections",420} Note that if a given value of linear deflection is less than shape tolerance then the algorithm will skip this value and will take into account the shape tolerance. @@ -3171,24 +3171,24 @@ You can obtain information on the shape by first exploring it. To access triangu @subsubsection occt_modalg_11_3_1 Goals The main goals of the chosen architecture are: - * Remove tight connections between data structures, auxiliary tools and algorithms in order to create an extensible solution, easy for maintenance and improvements; + * Remove tight connections between data structures, auxiliary tools and algorithms to create an extensible solution, easy for maintenance and improvements; * Separate the code among several functional units responsible for specific operation for the sake of simplification of debugging and readability; - * Introduce new data structures enabling the possibility to manipulate a discrete model of a particular entity (edge, wire, face) in order to perform computations locally instead of processing an entire model; - * Implement a new triangulation algorithm replacing existing functionality that contains too complicated solutions that need to be moved to the upper level. In addition, provide the possibility to change algorithm depending on surface type (initially to speed up meshing of planes). + * Introduce new data structures enabling the possibility to manipulate a discrete model of a particular entity (edge, wire, face) in order to perform computations locally instead of processing the entire model; + * Implement a new triangulation algorithm replacing the existing functionality that contains overcomplicated solutions that need to be moved to the upper level. In addition, provide the possibility to change the algorithm depending on surface type (initially to speed up meshing of planes). @subsubsection occt_modalg_11_3_2 General workflow @figure{/user_guides/modeling_algos/images/modeling_algos_mesh_001.svg,"General workflow of BRepMesh component",500} -Generally, the workflow of the component can be divided on six parts: - * **Creation of model data structure**: source *TopoDS_Shape* passed to algorithm is analyzed and exploded on faces and edges. The reflection corresponding to each topological entity is created in the data model. Note that underlying algorithms use the data model as input and access it via a common interface which allows creating a custom data model with necessary dependencies between particular entities (see the paragraph "Data model interface"); - * **Discretize edges 3D & 2D curves**: 3D curve as well as an associated set of 2D curves of each model edge is discretized in order to create a coherent skeleton used as a base in face meshing process. If an edge of the source shape already contains polygonal data which suits the specified parameters, it is extracted from the shape and stored in the model as is. Each edge is processed separately, adjacency is not taken into account; +Generally, the workflow of the component can be divided into six parts: + * **Creation of model data structure**: source *TopoDS_Shape* passed to algorithm is analyzed and exploded into faces and edges. The reflection corresponding to each topological entity is created in the data model. Note that underlying algorithms use the data model as input and access it via a common interface which allows creating a custom data model with necessary dependencies between particular entities (see the paragraph "Data model interface"); + * **Discretize edges 3D & 2D curves**: 3D curve as well as an associated set of 2D curves of each model edge is discretized in order to create a coherent skeleton used as a base in face meshing process. If an edge of the source shape already contains polygonal data which suits the specified parameters, it is extracted from the shape and stored in the model as is. Each edge is processed separately, the adjacency is not taken into account; * **Heal discrete model**: the source *TopoDS_Shape* can contain problems, such as open wires or self-intersections, introduced during design, exchange or modification of model. In addition, some problems like self-intersections can be introduced by roughly discretized edges. This stage is responsible for analysis of a discrete model in order to detect and repair problems or to refuse further processing of a model part in case if a problem cannot be solved; * **Preprocess discrete model**: defines actions specific to the implemented approach to be performed before meshing of faces. By default, this operation iterates over model faces, checks the consistency of existing triangulations and cleans topological faces and adjacent edges from polygonal data in case of inconsistency or marks a face of the discrete model as not required for the computation; * **Discretize faces**: represents the core part performing mesh generation for a particular face based on 2D discrete data. This operation caches polygonal data associated with face edges in the data model for further processing and stores the generated mesh to *TopoDS_Face*; * **Postprocess discrete model**: defines actions specific for the implemented approach to be performed after meshing of faces. By default, this operation stores polygonal data obtained at the previous stage to *TopoDS_Edge* objects of the source model. @subsubsection occt_modalg_11_3_3 Common interfaces -The component structure contains two units: IMeshData (see Data model interface) and IMeshTools, defining common interfaces for the data model and algorithmic tools correspondingly. Class *IMeshTools_Context* represents a connector between these units. The context class caches the data model as well as the tools corresponding to each of six stages of the workflow mentioned above and provides methods to call the corresponding tool safely (designed similarly to *IntTools_Context* in order to keep consistency with OCCT core tools). All stages, except for the first one use data model as input and perform a specific action on the entire structure. Thus, API class *IMeshTools_ModelAlgo* is defined in order to unify the interface of tools manipulating the data model. Each tool supposed to process the data model should inherit this interface enabling the possibility to cache it in context. In contrast to others, the model builder interface is defined by another class *IMeshTools_ModelBuilder* due to a different meaning of the stage. The entry point starting the entire workflow is represented by *IMeshTools_MeshBuilder*. +The component structure contains two units: IMeshData (see Data model interface) and IMeshTools, defining common interfaces for the data model and algorithmic tools correspondingly. Class *IMeshTools_Context* represents a connector between these units. The context class caches the data model as well as the tools corresponding to each of six stages of the workflow mentioned above and provides methods to call the corresponding tool safely (designed similarly to *IntTools_Context* in order to keep consistency with OCCT core tools). All stages, except for the first one, use the data model as input and perform a specific action on the entire structure. Thus, API class *IMeshTools_ModelAlgo* is defined in order to unify the interface of tools manipulating the data model. Each tool supposed to process the data model should inherit this interface enabling the possibility to cache it in context. In contrast to others, the model builder interface is defined by another class *IMeshTools_ModelBuilder* due to a different meaning of the stage. The entry point starting the entire workflow is represented by *IMeshTools_MeshBuilder*. The default implementation of *IMeshTools_Context* is given in *BRepMesh_Context* class initializing the context by instances of default algorithmic tools. diff --git a/src/BRepMesh/BRepMesh_BoundaryParamsRangeSplitter.hxx b/src/BRepMesh/BRepMesh_BoundaryParamsRangeSplitter.hxx index ad0f2599fc..5006e1b65a 100644 --- a/src/BRepMesh/BRepMesh_BoundaryParamsRangeSplitter.hxx +++ b/src/BRepMesh/BRepMesh_BoundaryParamsRangeSplitter.hxx @@ -44,6 +44,11 @@ public: protected: + //! Initializes U and V parameters lists using CN continuity intervals. + virtual Standard_Boolean initParameters() const Standard_OVERRIDE + { + return Standard_True; + } }; #endif diff --git a/src/BRepMesh/BRepMesh_Deflection.cxx b/src/BRepMesh/BRepMesh_Deflection.cxx index d3e9757de4..bde26b833f 100644 --- a/src/BRepMesh/BRepMesh_Deflection.cxx +++ b/src/BRepMesh/BRepMesh_Deflection.cxx @@ -14,41 +14,46 @@ // commercial license or contractual agreement. #include -#include -#include -#include -#include -#include -#include + #include #include -#include -#include +#include +#include +#include +#include #include +#include //======================================================================= //function : RelativeEdgeDeflection //purpose : //======================================================================= -Standard_Real BRepMesh_Deflection::RelativeEdgeDeflection( - const TopoDS_Edge& theEdge, - const Standard_Real theDeflection, +Standard_Real BRepMesh_Deflection::ComputeAbsoluteDeflection( + const TopoDS_Shape& theShape, + const Standard_Real theRelativeDeflection, const Standard_Real theMaxShapeSize, Standard_Real& theAdjustmentCoefficient) { theAdjustmentCoefficient = 1.; - Standard_Real aEdgeDeflection = theDeflection; - if (theEdge.IsNull()) + if (theShape.IsNull()) { - return aEdgeDeflection; + return theRelativeDeflection; } Bnd_Box aBox; - BRepBndLib::Add (theEdge, aBox, Standard_False); - BRepMesh_ShapeTool::BoxMaxDimension (aBox, aEdgeDeflection); + BRepBndLib::Add (theShape, aBox, Standard_False); + + Standard_Real aShapeSize = theRelativeDeflection; + BRepMesh_ShapeTool::BoxMaxDimension (aBox, aShapeSize); // Adjust resulting value in relation to the total size - theAdjustmentCoefficient = theMaxShapeSize / (2 * aEdgeDeflection); + + Standard_Real aX1, aY1, aZ1, aX2, aY2, aZ2; + aBox.Get(aX1, aY1, aZ1, aX2, aY2, aZ2); + const Standard_Real aMaxShapeSize = (theMaxShapeSize > 0.0) ? theMaxShapeSize : + Max(aX2 - aX1, Max(aY2 - aY1, aZ2 - aZ1)); + + theAdjustmentCoefficient = aMaxShapeSize / (2 * aShapeSize); if (theAdjustmentCoefficient < 0.5) { theAdjustmentCoefficient = 0.5; @@ -58,7 +63,7 @@ Standard_Real BRepMesh_Deflection::RelativeEdgeDeflection( theAdjustmentCoefficient = 2.; } - return (theAdjustmentCoefficient * aEdgeDeflection * theDeflection); + return (theAdjustmentCoefficient * aShapeSize * theRelativeDeflection); } //======================================================================= @@ -75,8 +80,9 @@ void BRepMesh_Deflection::ComputeDeflection ( if (theParameters.Relative) { Standard_Real aScale; - aLinDeflection = RelativeEdgeDeflection (theDEdge->GetEdge (), - theParameters.Deflection, theMaxShapeSize, aScale); + aLinDeflection = ComputeAbsoluteDeflection(theDEdge->GetEdge(), + theParameters.Deflection, + theMaxShapeSize, aScale); // Is it OK? aAngDeflection = theParameters.Angle * aScale; @@ -144,7 +150,15 @@ void BRepMesh_Deflection::ComputeDeflection ( const IMeshData::IFaceHandle& theDFace, const IMeshTools_Parameters& theParameters) { - Standard_Real aFaceDeflection = 0.; + Standard_Real aDeflection = theParameters.DeflectionInterior; + if (theParameters.Relative) + { + Standard_Real aScale; + aDeflection = ComputeAbsoluteDeflection(theDFace->GetFace(), + aDeflection, -1.0, aScale); + } + + Standard_Real aFaceDeflection = 0.0; if (theDFace->WiresNb () > 0) { for (Standard_Integer aWireIt = 0; aWireIt < theDFace->WiresNb(); ++aWireIt) @@ -154,10 +168,8 @@ void BRepMesh_Deflection::ComputeDeflection ( aFaceDeflection /= theDFace->WiresNb (); } - else - { - aFaceDeflection = theParameters.Deflection; - } + + aFaceDeflection = Max(aDeflection, aFaceDeflection); theDFace->SetDeflection (Max(2.* BRepMesh_ShapeTool::MaxFaceTolerance( theDFace->GetFace()), aFaceDeflection)); diff --git a/src/BRepMesh/BRepMesh_Deflection.hxx b/src/BRepMesh/BRepMesh_Deflection.hxx index 7c3b5aed77..8a7e05df9e 100644 --- a/src/BRepMesh/BRepMesh_Deflection.hxx +++ b/src/BRepMesh/BRepMesh_Deflection.hxx @@ -31,16 +31,17 @@ class BRepMesh_Deflection : public Standard_Transient { public: - //! Returns relative deflection for edge with respect to shape size. - //! @param theEdge edge for which relative deflection should be computed. - //! @param theDeflection absolute deflection. - //! @param theMaxShapeSize maximum size of a shape. + //! Returns absolute deflection for theShape with respect to the + //! relative deflection and theMaxShapeSize. + //! @param theShape shape for that the deflection should be computed. + //! @param theRelativeDeflection relative deflection. + //! @param theMaxShapeSize maximum size of the whole shape. //! @param theAdjustmentCoefficient coefficient of adjustment between maximum //! size of shape and calculated relative deflection. - //! @return relative deflection for the edge. - Standard_EXPORT static Standard_Real RelativeEdgeDeflection ( - const TopoDS_Edge& theEdge, - const Standard_Real theDeflection, + //! @return absolute deflection for the shape. + Standard_EXPORT static Standard_Real ComputeAbsoluteDeflection ( + const TopoDS_Shape& theShape, + const Standard_Real theRelativeDeflection, const Standard_Real theMaxShapeSize, Standard_Real& theAdjustmentCoefficient); diff --git a/src/BRepMesh/BRepMesh_DelaunayDeflectionControlMeshAlgo.hxx b/src/BRepMesh/BRepMesh_DelaunayDeflectionControlMeshAlgo.hxx index 922d530bd4..78689d114d 100644 --- a/src/BRepMesh/BRepMesh_DelaunayDeflectionControlMeshAlgo.hxx +++ b/src/BRepMesh/BRepMesh_DelaunayDeflectionControlMeshAlgo.hxx @@ -18,6 +18,7 @@ #include #include +#include //! Extends node insertion Delaunay meshing algo in order to control //! deflection of generated trianges. Splits triangles failing the check. @@ -314,16 +315,56 @@ private: const gp_XY aMidPnt2d = (theNodesInfo[i].Point2d + theNodesInfo[j].Point2d) / 2.; - usePoint(aMidPnt2d, LineDeviation(theNodesInfo[i].Point, theNodesInfo[j].Point)); + if (!usePoint (aMidPnt2d, LineDeviation (theNodesInfo[i].Point, + theNodesInfo[j].Point))) + { + if (!checkLinkEndsForAngularDeviation(theNodesInfo[i], + theNodesInfo[j], + aMidPnt2d)) + { + myControlNodes->Append(aMidPnt2d); + } + } } } } + //! Checks the given point (located between the given nodes) + //! for specified angular deviation. + Standard_Boolean checkLinkEndsForAngularDeviation(const TriangleNodeInfo& theNodeInfo1, + const TriangleNodeInfo& theNodeInfo2, + const gp_XY& /*theMidPoint*/) + { + gp_Dir aNorm1, aNorm2; + const Handle(Geom_Surface)& aSurf = + this->getDFace()->GetSurface()->ChangeSurface().Surface().Surface(); + + if ((GeomLib::NormEstim(aSurf, theNodeInfo1.Point2d, Precision::Confusion(), aNorm1) == 0) && + (GeomLib::NormEstim(aSurf, theNodeInfo2.Point2d, Precision::Confusion(), aNorm2) == 0)) + { + Standard_Real anAngle = aNorm1.Angle(aNorm2); + if (anAngle > this->getParameters().AngleInterior) + return Standard_False; + } +#if 0 + else if (GeomLib::NormEstim(aSurf, theMidPoint, Precision::Confusion(), aNorm1) != 0) + { + // It is better to consider the singular point as a node of triangulation. + // However, it leads to hangs up meshing some faces (including faces with + // degenerated edges). E.g. tests "mesh standard_incmesh Q6". + // So, this code fragment is better to implement in the future. + return Standard_False; + } +#endif + + return Standard_True; + } + //! Computes deflection of the given point and caches it for //! insertion in case if it overflows deflection. //! @return True if point has been cached for insertion. template - inline void usePoint( + inline Standard_Boolean usePoint( const gp_XY& thePnt2d, const DeflectionFunctor& theDeflectionFunctor) { @@ -332,7 +373,10 @@ private: if (!checkDeflectionOfPointAndUpdateCache(thePnt2d, aPnt, theDeflectionFunctor.SquareDeviation(aPnt))) { myControlNodes->Append(thePnt2d); + return Standard_True; } + + return Standard_False; } //! Checks the given point for specified linear deflection. diff --git a/src/BRepMesh/BRepMesh_DelaunayNodeInsertionMeshAlgo.hxx b/src/BRepMesh/BRepMesh_DelaunayNodeInsertionMeshAlgo.hxx index 11091236c2..23863b74bd 100644 --- a/src/BRepMesh/BRepMesh_DelaunayNodeInsertionMeshAlgo.hxx +++ b/src/BRepMesh/BRepMesh_DelaunayNodeInsertionMeshAlgo.hxx @@ -46,7 +46,8 @@ protected: virtual std::pair getCellsCount (const Standard_Integer theVerticesNb) Standard_OVERRIDE { return BRepMesh_GeomTool::CellsCount (this->getDFace()->GetSurface(), theVerticesNb, - this->getParameters().Deflection, &this->getRangeSplitter()); + this->getDFace()->GetDeflection(), + &this->getRangeSplitter()); } //! Perfroms processing of generated mesh. Generates surface nodes and inserts them into structure. diff --git a/src/BRepMesh/BRepMesh_IncrementalMesh.hxx b/src/BRepMesh/BRepMesh_IncrementalMesh.hxx index b24e1aa5bd..3940eab4d0 100644 --- a/src/BRepMesh/BRepMesh_IncrementalMesh.hxx +++ b/src/BRepMesh/BRepMesh_IncrementalMesh.hxx @@ -51,7 +51,7 @@ public: //! @name mesher API Standard_EXPORT BRepMesh_IncrementalMesh(const TopoDS_Shape& theShape, const IMeshTools_Parameters& theParameters); - //! Performs meshing ot the shape. +//! Performs meshing ot the shape. Standard_EXPORT virtual void Perform() Standard_OVERRIDE; public: //! @name accessing to parameters. @@ -85,12 +85,23 @@ private: //! Initializes specific parameters inline void initParameters() { + if (myParameters.DeflectionInterior < Precision::Confusion()) + { + myParameters.DeflectionInterior = myParameters.Deflection; + } + if (myParameters.MinSize < Precision::Confusion()) { myParameters.MinSize = - Max(IMeshTools_Parameters::RelMinSize() * myParameters.Deflection, + Max(IMeshTools_Parameters::RelMinSize() * Min(myParameters.Deflection, + myParameters.DeflectionInterior), Precision::Confusion()); } + + if (myParameters.AngleInterior < Precision::Angular()) + { + myParameters.AngleInterior = 2.0 * myParameters.Angle; + } } public: //! @name plugin API diff --git a/src/BRepMesh/BRepMesh_ModelBuilder.cxx b/src/BRepMesh/BRepMesh_ModelBuilder.cxx index 63949d9d3f..dd9c3be4fa 100644 --- a/src/BRepMesh/BRepMesh_ModelBuilder.cxx +++ b/src/BRepMesh/BRepMesh_ModelBuilder.cxx @@ -70,7 +70,8 @@ Handle (IMeshData_Model) BRepMesh_ModelBuilder::Perform ( } else { - aModel->SetMaxSize(theParameters.Deflection); + aModel->SetMaxSize(Max(theParameters.Deflection, + theParameters.DeflectionInterior)); } Handle (IMeshTools_ShapeVisitor) aVisitor = diff --git a/src/BRepMesh/BRepMesh_NURBSRangeSplitter.cxx b/src/BRepMesh/BRepMesh_NURBSRangeSplitter.cxx index 6b09a39104..332be97de3 100644 --- a/src/BRepMesh/BRepMesh_NURBSRangeSplitter.cxx +++ b/src/BRepMesh/BRepMesh_NURBSRangeSplitter.cxx @@ -14,15 +14,14 @@ // commercial license or contractual agreement. #include -#include -#include -#include -#include -#include -#include -#include -#include + #include +#include +#include +#include +#include +#include +#include namespace { @@ -55,13 +54,6 @@ namespace { myParameters = theParameters; - if (myParameters.MinSize <= Precision::Confusion()) - { - myParameters.MinSize = - Max(IMeshTools_Parameters::RelMinSize() * myParameters.Deflection, - Precision::Confusion()); - } - Standard_Integer aStartIndex, aEndIndex; if (myIsoU) { @@ -106,8 +98,18 @@ namespace const Standard_Real aSqDist = BRepMesh_GeomTool::SquareDeflectionOfSegment( myPrevControlPnt, myCurrControlPnt, aMidPnt); - const Standard_Real aSqMaxDeflection = myDFace->GetDeflection() * myDFace->GetDeflection(); - if ((aSqDist > aSqMaxDeflection) && + Standard_Real anAngle = 0.0; + + if ((myPrevControlVec.SquareMagnitude() > Precision::SquareConfusion()) && + (myCurrControlVec.SquareMagnitude() > Precision::SquareConfusion())) + { + anAngle = myPrevControlVec.Angle(myCurrControlVec); + } + + const Standard_Real aSqMaxDeflection = myDFace->GetDeflection() * + myDFace->GetDeflection(); + + if (((aSqDist > aSqMaxDeflection) || (anAngle > myParameters.AngleInterior)) && aSqDist > myParameters.MinSize * myParameters.MinSize) { // insertion @@ -120,9 +122,8 @@ namespace // internals in order to prevent movement of triangle body // outside the surface in case of highly curved ones, e.g. // BSpline springs. - if (aSqDist < aSqMaxDeflection && - myControlParams->Length() > 3 && - theIndex < myControlParams->Length()) + if (((aSqDist < aSqMaxDeflection) || (anAngle < myParameters.AngleInterior)) && + myControlParams->Length() > 3 && theIndex < myControlParams->Length()) { // Remove too dense points const Standard_Real aTmpParam = myControlParams->Value(theIndex + 1); @@ -162,7 +163,7 @@ namespace // Lets check parameters for angular deflection. if (myPrevControlVec.SquareMagnitude() < gp::Resolution() || aTmpVec.SquareMagnitude() < gp::Resolution() || - myPrevControlVec.Angle(aTmpVec) < myParameters.Angle) + myPrevControlVec.Angle(aTmpVec) < myParameters.AngleInterior) { // For current Iso line we can remove this parameter. myControlParamsToRemove->Add(myCurrControlParam); @@ -257,6 +258,32 @@ namespace return isAdded; } + + //! Checks whether intervals should be split. + //! Returns true in case if it is impossible to compute normal + //! directly on intervals, false is returned elsewhere. + Standard_Boolean toSplitIntervals (const Handle (Geom_Surface)& theSurf, + const TColStd_Array1OfReal (&theIntervals)[2]) + { + Standard_Integer aIntervalU = theIntervals[0].Lower (); + for (; aIntervalU <= theIntervals[0].Upper (); ++aIntervalU) + { + const Standard_Real aParamU = theIntervals[0].Value(aIntervalU); + Standard_Integer aIntervalV = theIntervals[1].Lower (); + for (; aIntervalV <= theIntervals[1].Upper (); ++aIntervalV) + { + gp_Dir aNorm; + const Standard_Real aParamV = theIntervals[1].Value(aIntervalV); + if (GeomLib::NormEstim (theSurf, gp_Pnt2d (aParamU, aParamV), Precision::Confusion (), aNorm) != 0) + { + return Standard_True; + } + // TODO: do not split intervals if there is no normal in the middle of interval. + } + } + + return Standard_False; + } } //======================================================================= @@ -287,7 +314,10 @@ void BRepMesh_NURBSRangeSplitter::AdjustRange() Handle(IMeshData::ListOfPnt2d) BRepMesh_NURBSRangeSplitter::GenerateSurfaceNodes( const IMeshTools_Parameters& theParameters) const { - initParameters(); + if (!initParameters()) + { + return Handle(IMeshData::ListOfPnt2d)(); + } const std::pair& aRangeU = GetRangeU(); const std::pair& aRangeV = GetRangeV(); @@ -357,7 +387,7 @@ Handle(IMeshData::ListOfPnt2d) BRepMesh_NURBSRangeSplitter::GenerateSurfaceNodes // Function: initParameters // Purpose : //======================================================================= -void BRepMesh_NURBSRangeSplitter::initParameters() const +Standard_Boolean BRepMesh_NURBSRangeSplitter::initParameters() const { const Handle(BRepAdaptor_HSurface)& aSurface = GetSurface(); @@ -375,21 +405,79 @@ void BRepMesh_NURBSRangeSplitter::initParameters() const aSurface->UIntervals(aIntervals[0], aContinuity); aSurface->VIntervals(aIntervals[1], aContinuity); - Standard_Boolean isSplitIntervals = - (aIntervalsNb.first > 1 || aIntervalsNb.second > 1); + const Standard_Boolean isSplitIntervals = toSplitIntervals ( + aSurface->ChangeSurface().Surface().Surface(), aIntervals); - if (!isSplitIntervals && - (aSurface->GetType() == GeomAbs_BezierSurface || - aSurface->GetType() == GeomAbs_BSplineSurface)) + if (!initParamsFromIntervals(aIntervals[0], GetRangeU(), isSplitIntervals, + const_cast(GetParametersU()))) { - isSplitIntervals = (aSurface->NbUPoles() > 2 && aSurface->NbVPoles() > 2); + //if (!grabParamsOfEdges (Edge_Frontier, Param_U)) + { + return Standard_False; + } } - initParamsFromIntervals(aIntervals[0], GetRangeU(), isSplitIntervals, - const_cast(GetParametersU())); + if (!initParamsFromIntervals(aIntervals[1], GetRangeV(), isSplitIntervals, + const_cast(GetParametersV()))) + { + //if (!grabParamsOfEdges (Edge_Frontier, Param_V)) + { + return Standard_False; + } + } - initParamsFromIntervals(aIntervals[1], GetRangeV(), isSplitIntervals, - const_cast(GetParametersV())); + return grabParamsOfEdges(Edge_Internal, Param_U | Param_V); +} + +//======================================================================= +//function : grabParamsOfInternalEdges +//purpose : +//======================================================================= +Standard_Boolean BRepMesh_NURBSRangeSplitter::grabParamsOfEdges ( + const EdgeType theEdgeType, + const Standard_Integer theParamDimensionFlag) const +{ + if ((theParamDimensionFlag & (Param_U | Param_V)) == 0) + { + return Standard_False; + } + + const IMeshData::IFaceHandle& aDFace = GetDFace (); + for (Standard_Integer aWireIt = 0; aWireIt < aDFace->WiresNb (); ++aWireIt) + { + const IMeshData::IWireHandle& aDWire = aDFace->GetWire (aWireIt); + for (Standard_Integer aEdgeIt = 0; aEdgeIt < aDWire->EdgesNb (); ++aEdgeIt) + { + const IMeshData::IEdgePtr& aDEdge = aDWire->GetEdge (aEdgeIt); + for (Standard_Integer aPCurveIt = 0; aPCurveIt < aDEdge->PCurvesNb (); ++aPCurveIt) + { + const IMeshData::IPCurveHandle& aDPCurve = aDEdge->GetPCurve (aPCurveIt); + if (aDPCurve->GetFace () == aDFace) + { + if (theEdgeType == Edge_Internal && !aDPCurve->IsInternal ()) + { + continue; + } + + for (Standard_Integer aPointIt = 0; aPointIt < aDPCurve->ParametersNb (); ++aPointIt) + { + const gp_Pnt2d& aPnt2d = aDPCurve->GetPoint (aPointIt); + if (theParamDimensionFlag & Param_U) + { + const_cast(GetParametersU ()).Add (aPnt2d.X ()); + } + + if (theParamDimensionFlag & Param_V) + { + const_cast(GetParametersV ()).Add (aPnt2d.Y ()); + } + } + } + } + } + } + + return Standard_True; } //======================================================================= @@ -411,16 +499,13 @@ Handle(IMeshData::SequenceOfReal) BRepMesh_NURBSRangeSplitter::computeGrainAndFi aMinDiff /= theDelta; } - const Standard_Real aMinSize = - theParameters.MinSize > Precision::Confusion() ? theParameters.MinSize : - Max(IMeshTools_Parameters::RelMinSize() * theParameters.Deflection, - Precision::Confusion()); - - aMinDiff = Max(aMinSize, aMinDiff); + aMinDiff = Max(theParameters.MinSize, aMinDiff); const Standard_Real aDiffMaxLim = 0.1 * theRangeDiff; - const Standard_Real aDiffMinLim = Max(0.005 * theRangeDiff, 2. * theTol2d); - const Standard_Real aDiff = Max(aMinSize, Min(aDiffMaxLim, aDiffMinLim)); + const Standard_Real aDiffMinLim = Max(0.005 * theRangeDiff, + 2. * theTol2d); + const Standard_Real aDiff = Max(theParameters.MinSize, + Min(aDiffMaxLim, aDiffMinLim)); return filterParameters(theSourceParams, aMinDiff, aDiff, theAllocator); } diff --git a/src/BRepMesh/BRepMesh_NURBSRangeSplitter.hxx b/src/BRepMesh/BRepMesh_NURBSRangeSplitter.hxx index df0685d098..a74f2d23a2 100644 --- a/src/BRepMesh/BRepMesh_NURBSRangeSplitter.hxx +++ b/src/BRepMesh/BRepMesh_NURBSRangeSplitter.hxx @@ -46,7 +46,7 @@ public: protected: //! Initializes U and V parameters lists using CN continuity intervals. - Standard_EXPORT virtual void initParameters() const; + Standard_EXPORT virtual Standard_Boolean initParameters() const; private: @@ -66,6 +66,23 @@ private: const Standard_Real theFilterDist, const Handle(NCollection_IncAllocator)& theAllocator) const; + enum EdgeType + { + Edge_Internal, + Edge_Frontier + }; + + enum ParamDimension + { + Param_U = 0x1, + Param_V = 0x2 + }; + + //! Finds edges of discrete face and uses its points + //! as auxiliary control parameters for generation of nodes. + Standard_Boolean grabParamsOfEdges (const EdgeType theEdgeType, + const Standard_Integer theParamDimensionFlag) const; + private: GeomAbs_SurfaceType mySurfaceType; diff --git a/src/IMeshTools/IMeshTools_Parameters.hxx b/src/IMeshTools/IMeshTools_Parameters.hxx index 8598e03f99..fedfff395d 100644 --- a/src/IMeshTools/IMeshTools_Parameters.hxx +++ b/src/IMeshTools/IMeshTools_Parameters.hxx @@ -26,6 +26,8 @@ struct IMeshTools_Parameters { : Angle(0.5), Deflection(0.001), + AngleInterior(-1.0), + DeflectionInterior(-1.0), MinSize (-1.0), InParallel (Standard_False), Relative (Standard_False), @@ -42,12 +44,18 @@ struct IMeshTools_Parameters { return 0.1; } - //! Angular deflection + //! Angular deflection used to tessellate the boundary edges Standard_Real Angle; - //! Deflection + //!Linear deflection used to tessellate the boundary edges Standard_Real Deflection; + + //! Angular deflection used to tessellate the face interior + Standard_Real AngleInterior; + //! Linear deflection used to tessellate the face interior + Standard_Real DeflectionInterior; + //! Minimal allowed size of mesh element Standard_Real MinSize; diff --git a/src/MeshTest/MeshTest.cxx b/src/MeshTest/MeshTest.cxx index 02501b9783..fd6e23c518 100644 --- a/src/MeshTest/MeshTest.cxx +++ b/src/MeshTest/MeshTest.cxx @@ -118,8 +118,11 @@ static Standard_Integer incrementalmesh(Draw_Interpretor& di, Standard_Integer n Builds triangular mesh for the shape\n\ usage: incmesh Shape LinearDeflection [options]\n\ options:\n\ - -a val angular deflection in deg\n\ + -a val angular deflection for edges in deg\n\ (default ~28.64 deg = 0.5 rad)\n\n\ + -ai val angular deflection inside of faces in deg\n\ + (default ~57.29 deg = 1 rad)\n\n\ + -di val Linear deflection used to tessellate the face interior.\n\ -min minimum size parameter limiting size of triangle's\n\ edges to prevent sinking into amplification in case\n\ of distorted curves and surfaces\n\n\ @@ -142,6 +145,8 @@ options:\n\ } IMeshTools_Parameters aMeshParams; + aMeshParams.Deflection = aMeshParams.DeflectionInterior = + Max(Draw::Atof(argv[2]), Precision::Confusion()); if (nbarg > 3) { @@ -168,8 +173,16 @@ options:\n\ { aMeshParams.Angle = aVal * M_PI / 180.; } + else if (aOpt == "-ai") + { + aMeshParams.AngleInterior = aVal * M_PI / 180.; + } else if (aOpt == "-min") aMeshParams.MinSize = aVal; + else if (aOpt == "-di") + { + aMeshParams.DeflectionInterior = aVal; + } else --i; } diff --git a/tests/bugs/iges/buc60820_1 b/tests/bugs/iges/buc60820_1 index 04237f0ac7..ff82704d2c 100755 --- a/tests/bugs/iges/buc60820_1 +++ b/tests/bugs/iges/buc60820_1 @@ -12,5 +12,5 @@ tclean result incmesh result 0.1 triangles result -checktrinfo result -tri 646 -nod 568 +checktrinfo result -tri 638 -nod 564 checkview -display result -2d -path ${imagedir}/${test_image}.png diff --git a/tests/bugs/iges/buc60823 b/tests/bugs/iges/buc60823 index b1b0244ca5..4724b1cbc3 100755 --- a/tests/bugs/iges/buc60823 +++ b/tests/bugs/iges/buc60823 @@ -14,6 +14,6 @@ vdisplay result vsetdispmode result 1 vfit -checktrinfo result -tri 2788 -nod 2648 +checktrinfo result -tri 2708 -nod 2608 checkview -display result -2d -path ${imagedir}/${test_image}.png diff --git a/tests/bugs/iges/bug306 b/tests/bugs/iges/bug306 index dba9f81f4a..8b543c2862 100755 --- a/tests/bugs/iges/bug306 +++ b/tests/bugs/iges/bug306 @@ -20,7 +20,7 @@ vsetdispmode result 1 vdisplay result vfit -checktrinfo result -tri 6046 -nod 5924 +checktrinfo result -tri 5810 -nod 5806 checkmaxtol result -ref 0.92213088179312575 checknbshapes result -shell 1 diff --git a/tests/bugs/mesh/bug25519 b/tests/bugs/mesh/bug25519 index 7b8fd5e7e8..f0cbe48aaa 100755 --- a/tests/bugs/mesh/bug25519 +++ b/tests/bugs/mesh/bug25519 @@ -15,5 +15,5 @@ fit isos a 0 triangles a -checktrinfo a -tri 2971 -nod 1592 -defl 0.083467373173701759 -tol_rel_defl 0.05 -tol_rel_tri 0.05 -tol_rel_nod 0.05 +checktrinfo a -tri 2971 -nod 1592 -defl 0.091190343620839553 -tol_rel_defl 0.05 -tol_rel_tri 0.05 -tol_rel_nod 0.05 checkview -screenshot -2d -path ${imagedir}/${test_image}.png diff --git a/tests/bugs/mesh/bug30008_1 b/tests/bugs/mesh/bug30008_1 new file mode 100644 index 0000000000..1beebc5f40 --- /dev/null +++ b/tests/bugs/mesh/bug30008_1 @@ -0,0 +1,17 @@ +puts "=======" +puts "0030008: BRepMesh does not respect angular deflection in internal area of bspline surface" +puts "=======" +puts "" + +restore [locate_data_file bug30008_badshape.brep] result + +vinit +vsetdispmode 1 + +vdisplay result +vviewparams -scale 8.46292 -proj 0.653203 -0.644806 0.396926 -up -0.0109833 0.51609 0.856464 -at 347.559 1026.89 219.262 -eye 2080.75 -684.022 1272.45 + +tricheck result +checktrinfo result -tri 11826 -nod 7310 -defl 7.6167024939147652 + +checkview -screenshot -3d -path ${imagedir}/${test_image}.png diff --git a/tests/bugs/mesh/bug30008_2 b/tests/bugs/mesh/bug30008_2 new file mode 100644 index 0000000000..7daf3f0f66 --- /dev/null +++ b/tests/bugs/mesh/bug30008_2 @@ -0,0 +1,32 @@ +puts "=======" +puts "0030008: BRepMesh does not respect angular deflection in internal area of bspline surface" +puts "=======" +puts "" + +pcylinder cy 100 500 +bsplinecurve cc 5 4 -494.543457494654 6 500 4 507.372773368102 4 1501.91623086297 6 -500 -798.578274581199 755.284518447357 1 -500 -646.205376770376 627.428476092882 1 -500 -493.832478959552 499.572433738407 1 -500 -341.459581148729 371.716391383932 1 -500 -189.086683337906 243.860349029457 1 -500 -35.5842111132817 115.056481200973 1 -500 -33.7993197286247 114.2995541724 0.957903314642061 -500 -31.778022626919 114.565662984205 0.95790331464206 -500 -30.2498570721059 115.75876223351 1 -500 84.6852511720001 279.903107977019 1 -500 198.774589601206 442.839569245217 1 -500 312.863928030413 605.776030513415 1 -500 426.953266459619 768.712491781612 1 -500 541.042604888826 931.64895304981 1 +extsurf ss cc 1 0 0 + +mkface ff ss -494.543457494654 1501.91623086297 0 1000 +halfspace hs ff 0 0 500 + +bcut rc cy hs +explode rc f +copy rc_1 result +tscale result 0 0 0 0.01 +nurbsconvert result result + +incmesh result 0.15 -a 20 + +tricheck result +checktrinfo result -tri 193 -nod 147 -defl 0.042090809832482222 -tol_abs_defl 1.0e-7 + +vinit + +vdefaults -autoTriang 0 +vdisplay result +vfit +vsetdispmode 1 +vviewparams -scale 335.304 -eye 1.95918 0.124681 5.05411 -at 0.0736354 0.0378839 1.46922 -up -0.748808 0.542534 0.380715 -proj 0.4654 0.0214236 0.884841 + +checkview -screenshot -3d -path ${imagedir}/${test_image}.png diff --git a/tests/bugs/mesh/bug30167 b/tests/bugs/mesh/bug30167 index 547cdcfc95..4fd42ad6e5 100644 --- a/tests/bugs/mesh/bug30167 +++ b/tests/bugs/mesh/bug30167 @@ -12,6 +12,6 @@ vdisplay result vfit tricheck result -checktrinfo result -tri 4006 -nod 2092 -max_defl 0.46 +checktrinfo result -tri 3424 -nod 1801 -max_defl 0.52 checkview -screenshot -3d -path ${imagedir}/${test_image}.png diff --git a/tests/bugs/modalg_2/bug358 b/tests/bugs/modalg_2/bug358 index 8fa4df7aa2..620f147091 100755 --- a/tests/bugs/modalg_2/bug358 +++ b/tests/bugs/modalg_2/bug358 @@ -19,7 +19,7 @@ vdisplay result vfit vsetdispmode result 1 -checktrinfo result -tri 21446 -nod 11157 +checktrinfo result -tri 21654 -nod 11261 checkprops result -s 24861.2 checkshape result checkview -display result -2d -path ${imagedir}/${test_image}.png diff --git a/tests/bugs/moddata_2/fra62476_2 b/tests/bugs/moddata_2/fra62476_2 index 30e911d8b5..feebf5b4a4 100755 --- a/tests/bugs/moddata_2/fra62476_2 +++ b/tests/bugs/moddata_2/fra62476_2 @@ -13,5 +13,5 @@ tclean result incmesh result .1 triangles result -checktrinfo result -tri 355 -nod 210 +checktrinfo result -tri 335 -nod 200 checkview -display result -3d -path ${imagedir}/${test_image}.png diff --git a/tests/mesh/data/advanced/B8 b/tests/mesh/data/advanced/B8 index 5ffd436404..62f5350c5d 100755 --- a/tests/mesh/data/advanced/B8 +++ b/tests/mesh/data/advanced/B8 @@ -2,5 +2,5 @@ set TheFileName OCC357.brep if { [string compare $command "shading"] == 0 } { #set bug_area "OCC22687" set max_rel_tol_diff 0.25 - set rel_tol 1.0015290236679502 + set rel_tol 1.7957583466671934 } diff --git a/tests/mesh/data/standard/Q3 b/tests/mesh/data/standard/Q3 index 10ab26554b..e8a44d2e65 100755 --- a/tests/mesh/data/standard/Q3 +++ b/tests/mesh/data/standard/Q3 @@ -1,5 +1,5 @@ set TheFileName shading_147.brep if { [string compare $command "shading"] == 0 } { - set rel_tol 0.8093314937741523 + set rel_tol 0.8791879462861206 set max_rel_tol_diff 0.001 } diff --git a/tests/mesh/data/standard/U2 b/tests/mesh/data/standard/U2 index 2193082554..f5c48950be 100755 --- a/tests/mesh/data/standard/U2 +++ b/tests/mesh/data/standard/U2 @@ -3,7 +3,7 @@ set TheFileName shading_wrongshape_004.brep if { [string compare $command "shading"] == 0 } { set rel_tol 0.06073194250400039 } else { - set rel_tol 0.0021948131898279323 + set rel_tol 0.003702162749171707 } set max_rel_tol_diff 0.001 ###set bug_withouttri "OCC22687"