From 285d769f5887c6bc96dff104fa9f8a48117b743a Mon Sep 17 00:00:00 2001 From: "Brian T. Rice" Date: Mon, 29 Apr 2024 19:43:54 -0700 Subject: [PATCH] Cleanup stickerprint algorithm a lot. No regressions. --- SlideRule.py | 117 +++++++++++------------- examples/Aristo868.StickerCut.png | Bin 529346 -> 529351 bytes examples/FaberCastell283.StickerCut.png | Bin 429166 -> 429179 bytes 3 files changed, 51 insertions(+), 66 deletions(-) diff --git a/SlideRule.py b/SlideRule.py index 43a12c5..e92b53a 100755 --- a/SlideRule.py +++ b/SlideRule.py @@ -1841,81 +1841,66 @@ def render_stickerprint_mode(m: Model, sliderule_img: Image.Image): geom_s.oX = 0 geom_s.oY = 0 style = m.style - # fsUM,MM,LM: - y = 0 - y += o_y2 + o_a - x_left = geom.oX + x_off slide_h = geom.slide_h stator_h = geom.stator_h total_w = scale_w + 2 * o_x2 - sticker_row_h = max(slide_h, stator_h) - total_h = (geom.side_h + 2 * o_a) * 2 + o_a * 5 + sticker_row_h * 2 + 145 - stickerprint_img = image_for_rendering(m, w=total_w, h=total_h) - r = Renderer.make(stickerprint_img, geom_s, style) - transcribe(sliderule_img, stickerprint_img, x_left, geom.oY, scale_w, stator_h, o_x2, y) - extend(stickerprint_img, scale_w, y + stator_h - 1, BleedDir.DOWN, ext) - r.draw_corners(o_x2, y - o_a, o_x2 + scale_w, y + stator_h) - y += stator_h + o_a - transcribe(sliderule_img, stickerprint_img, x_left, geom.oY + stator_h + 1, scale_w, slide_h, o_x2, y) - extend(stickerprint_img, scale_w, y + 1, BleedDir.UP, ext) - extend(stickerprint_img, scale_w, y + slide_h - 1, BleedDir.DOWN, ext) - r.draw_corners(o_x2, y, o_x2 + scale_w, y + slide_h) - y += slide_h + o_a - transcribe(sliderule_img, stickerprint_img, x_left, geom.oY + geom.side_h - stator_h, scale_w, stator_h, o_x2, y) - extend(stickerprint_img, scale_w, y + 1, BleedDir.UP, ext) - extend(stickerprint_img, scale_w, y + stator_h - 1, BleedDir.DOWN, ext) - r.draw_corners(o_x2, y, o_x2 + scale_w, y + stator_h + o_a) - # bsUM,MM,LM: - y += stator_h + o_a + o_a + o_a - y_start = geom.oY + geom.side_h + geom.oY - transcribe(sliderule_img, stickerprint_img, x_left, y_start, scale_w, stator_h, o_x2, y) - extend(stickerprint_img, scale_w, y + stator_h - 1, BleedDir.DOWN, ext) - r.draw_corners(o_x2, y - o_a, o_x2 + scale_w, y + stator_h) - y += stator_h + o_a - transcribe(sliderule_img, stickerprint_img, x_left, y_start + stator_h + 1 - 3, scale_w, slide_h, o_x2, y) - extend(stickerprint_img, scale_w, y + 1, BleedDir.UP, ext) - extend(stickerprint_img, scale_w, y + slide_h - 1, BleedDir.DOWN, ext) - r.draw_corners(o_x2, y, o_x2 + scale_w, y + slide_h) - y += slide_h + o_a - transcribe(sliderule_img, stickerprint_img, x_left, y_start + geom.side_h - stator_h, scale_w, stator_h, o_x2, y) - extend(stickerprint_img, scale_w, y + 1, BleedDir.UP, ext) - extend(stickerprint_img, scale_w, y + stator_h - 1, BleedDir.DOWN, ext) - y_bottom = y + stator_h + o_a - r.draw_corners(o_x2, y, o_x2 + scale_w, y_bottom) - y_b = y_bottom + 20 + sticker_row_h = max(slide_h, stator_h) + o_a + total_h = (geom.side_h + 2 * o_a) * 2 + o_a * 3 + sticker_row_h * 2 + 145 + dst_img = image_for_rendering(m, w=total_w, h=total_h) + r = Renderer.make(dst_img, geom_s, style) + + def copy_band(src_y: int, h: int, dst_y: int): + transcribe(sliderule_img, dst_img, geom.oX + x_off, src_y, scale_w, h, o_x2, dst_y) + + def extend_edges(dst_y, h: int, both: bool): + if both: + extend(dst_img, scale_w, dst_y + 1, BleedDir.UP, ext) + extend(dst_img, scale_w, dst_y + h - 1, BleedDir.DOWN, ext) + + def part_corners(dst_y, h): + r.draw_corners(o_x2, dst_y, o_x2 + scale_w, dst_y + h) + + y = o_y2 + # fsUM,MM,LM and bsUM,MM,LM: + for (front, y_side) in ((True, geom.oY), (False, geom.oY + geom.side_h + geom.oY)): + y += o_a + copy_band(y_side, stator_h, y) + extend_edges(y, stator_h, False) + part_corners(y - o_a, stator_h + o_a) + y += stator_h + o_a + copy_band(y_side + stator_h + 1 - (0 if front else 3), slide_h, y) + extend_edges(y, slide_h, True) + part_corners(y, slide_h) + y += slide_h + o_a + copy_band(y_side + geom.side_h - stator_h, stator_h, y) + extend_edges(y, stator_h, True) + part_corners(y, stator_h + o_a) + y += stator_h + (o_a + o_a if front else 0) + # Side stickers: + y_b = y + o_a + 20 box_w = 510 boxes = [ - [o_a, y_b, - box_w + o_a, stator_h + o_a], - [box_w + 3 * o_a, y_b, - x_off + o_a, slide_h], - [box_w + x_off + 5 * o_a, y_b, - x_off + o_a, stator_h + o_a] + (o_a, y_b, box_w + o_a, stator_h + o_a), + (box_w + 3 * o_a, y_b, x_off + o_a, slide_h), + (box_w + 5 * o_a + x_off, y_b, x_off + o_a, stator_h + o_a) ] - box_x_mirror = 6.5 * o_a + box_w + 2 * x_off + box_x_mirror = 13 * o_a // 2 + box_w + 2 * x_off for (x0, y0, dx, dy) in boxes: - r.draw_box(x0, y0, dx, dy, Color.CUT) - r.draw_box(x0, y0 + slide_h + o_a, dx, dy, Color.CUT) - - x0 = round(2 * box_x_mirror - x0 - dx) - - r.draw_box(x0, y0, dx, dy, Color.CUT) - r.draw_box(x0, y0 + sticker_row_h + o_a, dx, dy, Color.CUT) - points = [ - [2 * o_a + 120, y_b + o_a + scale_h], - [6 * o_a + box_w + x_off + 2 * scale_h, y_b + scale_h], - [6 * o_a + box_w + x_off + scale_h, y_b + 2 * scale_h], - - [2 * o_a + 120, y_b + slide_h + o_a + scale_h], - [6 * o_a + box_w + x_off + scale_h, y_b + slide_h + o_a + o_a + 2 * scale_h], - [6 * o_a + box_w + x_off + 2 * scale_h, y_b + slide_h + o_a + o_a + scale_h] + for x1 in (x0, 2 * box_x_mirror - x0 - dx): + for y1 in (y0, y0 + slide_h + o_a): + r.draw_box(x1, y1, dx, dy, Color.CUT) + p1 = [ + (2 * o_a + 120, y_b + o_a + scale_h), + (6 * o_a + box_w + x_off + scale_h, y_b + 2 * scale_h), + (6 * o_a + box_w + x_off + 2 * scale_h, y_b + scale_h), ] + points = p1 + [(cx, cy + sticker_row_h + (o_a if i > 0 else -o_a)) + for (i, (cx, cy)) in enumerate(p1)] hole_r = 34 # (2.5mm diameter screw holes) = math.ceil(0.25 * Geometry.PixelsPerCM / 2) - for (p_x, p_y) in points: - r.draw_circle(p_x, p_y, hole_r, Color.CUT) - p_x_mirror = round(2 * box_x_mirror - p_x) - r.draw_circle(p_x_mirror, p_y, hole_r, Color.CUT) - return stickerprint_img + for (cx, cy) in points: + for x in (cx, 2 * box_x_mirror - cx): + r.draw_circle(x, cy, hole_r, Color.CUT) + return dst_img def render_diagnostic_mode(model: Model, all_scales=False): diff --git a/examples/Aristo868.StickerCut.png b/examples/Aristo868.StickerCut.png index 0afe256254d89a09e3f1d6669a2974a0bfc9ad9d..9ebdb25f3f3de348de8dd10a249dc6457e146155 100644 GIT binary patch delta 4808 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 O-KE|uye=&k?EN1U&Wn@) delta 5417 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 IjeAr73yBdiY5)KL diff --git a/examples/FaberCastell283.StickerCut.png b/examples/FaberCastell283.StickerCut.png index c285823032ddf9b50353b4100692080377662a29..7485adf571b840dfbf2485b203b7381722425312 100644 GIT binary patch delta 4999 zcmZWteOyf08$VOI!+ObPmA4uyVo7XTrA87W)#&$8w%Ap>n<2%tw!)~nXtC=hYPqt6 z_0l%pM(Jg3>LOcKO=z2x)T~x7Of^X_t2DoJ?wz_bcg`Qvb?$SX=X<`-^L)>_T2D^s zJvjkS;3OC&7$=w{4EY(0;JnX@#HM>sc^FxH;NJA=SKX3V^2O;7ZU1ZeJ!v^-a#_%h zyJlkH(eggx<51%mH9077M$viqR?J_%ai(*HqzzO6Y4=Z@wQD6&H^0@;G%!)<; zrR|aNKyCM^-$4rpt|Q0QSE>k)J(z`2*W?_3U#y+l-DS?#$Lcb{DzjLd#jFu= zGUTVPzy6uXT#MOA{8l^t=^W>p*Xuc-@rzqLlMWeNfzLb^-7qWQ?DL_Lnx^DfrZn(` zYr%t7Aa`7l@W>jcKTpbr*YaBw%nP-9LfNVz{NBd$M$YdJWJ&(L#~1p^+slwHPContsrhh~Sv z*#6o@%D3O1aUu6SZ#0d0%s}cHr$-z&L!P&}s-=VL+B6so?85a(7)G3*g-!I{nm*x0 z=Kh`)Ebx_j;9ETvDV32oS>TiPxL-?n*g=0Cze=C*#Rr7nCrYb4ncyOOY8L~W*z)a} z9S>qyn{Ym=2asqNVe_V^qy-#qt@6y1idUCfG0DL{ROu#OoJ4qdV~%z^{3@DK`Gw-! zUKOe-O!Q|ddYLumOL*k}2_TJ9zJVNktXut(= z*J#GI>Y;97*Q5~Vy)d8g4K6P(gm;Z@qsV29LxjZH5G-hPmr%DfT2~O9)!1hez8GZx z%}1DAQg7A6HU^}>G(MLU!(!;ax5Erh^mysfxDV3!B*wK#?2CGJ(o6BqwxapQf-gq^ z($ZOg*czr+7xOdZa1N|1U9+k!z3fTB`o3xh07N6@$#B*dz0wYHeer^h+pYdtMLA7> zlpyuWt0!Y>D;XZgT|!~po~%cC!%FsUpRA)*pMf^diNZeKlO3sj2rZKIH%_u$W#Xlbv?;plaQpm9=+^gbovNjH|iy)jj}@Zc9a6$g}_6 ztFcBN28PlbHtSPs*QV?;SYOI}Cw8jW{~I-JrBwYr38dbr(C; zymkSS0kmLdrY@^%tlyM0!`74Z$NlUWkIu0#%FXM}y4UW$>TU94IJo+R}y+*t+3D_8Ej`&*uxyQ|Tiub+tx<4?h~+aG_r^CeGx_zo^^?$3ZUY7hx3)l$sa z)4T#jYR{u10jg$n{NdY*7eLJdvgEA zB?WS#0mxdrH>k8ozZ0LfZ&GtWM3I&`rUAAmUv)%be+jx+n06Od$_xV}mhfsxArtg| z+U`5-AKyGD0QQU6jC?hX4tBz7Y@Srms9q@Xf|8J968)5BdI>S1Wc9=_-H@;U|eK9O% zy-&F}?3;Kpn7NH0JLO;Bo4KqR>QoT9Jt0H*wxgZ6OLNsk81Ngm zD`o8?$vX<_q)V$5cchmS;gTbTEcAFRjeeiy#iW=E$D!N2n=DL98yfkF{nCpsHeP}* zAF-VX=x#ma5;C=A*-XgyY&kNS!)y%TWwcF+bHsp+fg16}oB&VZpR$`)f2MSjHY<$k+n>w~VwJLbG<|r;ewSA8;|d+Wzaee5fjMk6pxz&a*4Q*quF6(r-A+SUOf6z3 zz>B&E3v6&cvL)TWn^@l@!@u5dOKFtsN_p1P)lXqNSYKuJ<8msiOS-5UET(dcr0)whDfV=kand$kO25bf zyWzocEGPPAyOVb9MtaHj3~6Rnbf&bIy6TF`fnn#*QUrWK>6z}Z)-KM&3BY~#Z3 z6Du|WS}UnI;De?kGosxUiqT4T_2qs>Bdg!JIpstCmdlAy9o&v(N%UKd45KycG+Fd@ z^+!oU(>QpSQ*s%;C-$ zCf+s}nH$MHa-w{&Cq_ALQ&!;_m+^XUmC z*tJQ2BZs!9ETnIX%1Jr!B9k}-{U^*TBl|o*o;qFHjK1QOUmuDBAvXQ!`wz$;NT}-t z?GWG&t78Rqlm`=$kwZB#CDPb}m=K0d&LM5F5ghYAu3ODQ7w@xksPDWLOZ}EyUmUXM E|Ijsg+yDRo delta 6313 zcmeHLX;f3!7Cs4hsihiQstgv8NopM_B4fazNJRu&1w|-A6{!dqL_r%gv7qR}3YLb8 z8bE9`A>#et5|Gb_bA@|&U_VDe! zzq7+oie7h$9ygX2OOI8HRgazYGZsSY$`8dpbv3>cu7C9GtUsQPj<%jUG<(>g_iESN zqozwgk7zx#JnI{^&igdcv?Ev*T_iNd#59-mJPiQSysX%CfEIVsfQJ_GZR|s`_fidD zecqgBPVQ{vjxMH+y(IqrHju)^mub?qX|^JxFR&Bp-tYKK@n+9EX#ga@NdFQP9`0_` z8a|qYsT@NO;@bKW3_(en?;CPa* z7wY2Sz~B71E)W~=Er3MtYLJK2++9yeiuPZGeELEUZ@~aR z6@Cb{pxJ@bfulV2@pJyiWEN}`-V8NvM4~9%4O>s=zyQH9!Dh$1`zt;fmjsIvvNtK7 zY$kaJy&NdnJ<@UD-8w@>?A$z|r=~(I)1;$1qr|H+{gKJ&$kT@KQBG+5pZrE>MJak4waX_pYQb%SR z9TW2^?DBBI^Ci~}8Fp`uDl{dkxTy`@>=WG9(TXf9%490RI-(MEp{aM!5-+QW(IHv; z6-$mn8&?^cLP0{K8f#8`$bqN?LE{RA6l+64u)kNX7XLf=T0NxkV@Tyquo-m=eWdl_;iE;unoEOLK?p z;N7(b&pexd3GSOVt^)AWRnlONXUxMaKRwyD{>Sdd6~&qC^>+*umBFQS=mO+o}vhw;O`NO}Cei z5IxdQc%#tF+J^tQ74x1}Q>%h+5}x6LS#aLivVr>rHaZjG@amW)N}kV!!B({=GXapQ zwXK5Bk^~A!cD-jGbe&1xf!ftytK|W^v_yCB>l*+x9qcuQd#be`WzvDzNL&{^>22De z?O;Env~LOkzA;dCHhiI2QZ?@&zlTggjm+oIyz0sDMe&v!kxw34<5hu}0jKq2`}PhG zR5HaoGp#`jJNn5Ys3(Q6DV?nXpdqAPxcEMGI$Qc%(wz>(al|nI*pR~Lm3&EmM$Pp7 zW~XJF*YR3z!}!HKX7@lFWeh`{>rYOZR}>RAgjj4r zR&Y)8sBHGuJ2=ei3%)t5L@raM1nm>|Y@4asede(vyfwI*Y~SIa=6@I__;m$BGqwcQ z{!W^H!=cIqQ-HeoYy0*BPA$|Zxjy5{z{0nms{<~dh+8N+w_qf`_yhP(zPNKw?Af+D zzH`is&+BKU6;-f|chw|85wXRXhOq-+!HW8mKQbfl24!bB8H5ti>CFC=>*8B6DtP0M`4Y9hpkim{mfaET1}Pv7>a*GoP|^5BnhbF*@`QRAD(+h|f3u=Lg$*vO8s| zD8N(hGU%3l;@dWLP?)if|A5GaWU7ikRuy&;vAO!Pe$nl&RFw5*{`t^M;_yPl-kuUKx70vr9?JUdtnQwZAT1yY;K$$|GAnBTJyJJf=0NRmP z^G*_pYf4lm6B~Va-Q{gY{5pJZ6+6;38i074R~M@HeFV3Zu*G$jxoD+vnc;$4eiXIUCj{2rVh z$fiL`;xUPEW9{g?QK6nd`g%p96N~oBJEU(vv65IzHg*P+HVEY(P zP%W)b8@ z?2{jUvq`$1!~ATor%RjkIL8d3zMD9pm>$VJf&19cz{n2`UVN;}jktgwUy zesv`Wi?5X$0M zKoS%8pm|XeJktDp=CZXts8?A56YyY=s1|1RSY7MkUEAygZ>by9#1CkB2O(U-mIX2Z zH%hgFkQIhu9&Qw>rcJle5W$vsP3OpA7RL(?yj$9Dgt&2dp=dhNqF4*uhXIs@f(mRl&lUgqz$wp&L2YLxb2Y zm|DsHu(_&IO=J~|&k7>9pWMIjx9#U(Z7yW_DDDm~dcB0uA?(Nt`ag5vJxQ(b_@n?rF$)`tuGis0=DTnlbw$HCW^_}5Cd(q)kO`Ig6 zL{he2aD5cx1?TZaR752UNiDy53*}m@+X^W3!67G`Mdg=xmo>5>?@O^-}Rc& z)QY$fvZ+v?8phsa6vl|Du!x}D`C}97;|X~RB5n`E#S*8kri<>)t~x94>E0YFebZ$8 zp|%-)N$m5BvQ0eAs*y*fjRd=lR8NJe(V@&W2D>45zzsM!Jj=v?l*#tI0Ig8SuOYr~)Oov9=a+BLC_a&aPpLJfWPl@P1A{z6sp^R$3hvd+PmzT2_ z^H62mQe!A~CObP*tKk0n`w*O`RIjW_VEN}T@#pX(bf~^ zV&CZk)iESg-;KxuSYG-^V1(n6fWGz~$h%Gn_|osO865XuczCq7rS-!WXe5kc1c+0~ zbnqXpuIg;**f#hbG-17qQaUUjvIw-LQ5K=GFB&ubAX5#{sW8ibJ+aJk*+IGX-x-#C z0IY#@EfuCPa*B`$cHf1mh@cvi#xT1Kh=0S-SyL2sjt9&huU?wz-}{I${>Fi1v%ee% z%|wSD19(|K;umQrh41_L{idJb(Cu5jiF{OVs(a9#REEt^0}p2F;4X`~ql^0X{{I6;|5XlLD&d8)^HfAXx^WA2%WYKg zg-_xk_fvcPcKjQGxU@(H$)<%^(urOj{Gb`8i-sQ^+L!2;p$_e%|72VHr%^B(XKx*R S?{+=%W|g!17dgxQfA}W`3*wjn