From 47a7a8a831b56823a1b862255b4330ef0f22921c Mon Sep 17 00:00:00 2001 From: grimsace Date: Tue, 19 May 2026 11:09:20 -0500 Subject: [PATCH] made hexagons regular hexagons with specifiable side length --- .gitignore | 1 + grid_generator.zip | Bin 15171 -> 0 bytes .../__pycache__/grid_docker.cpython-313.pyc | Bin 12021 -> 12819 bytes pykrita/grid_generator/grid_docker.py | 122 +++++++++--------- 4 files changed, 63 insertions(+), 60 deletions(-) delete mode 100644 grid_generator.zip diff --git a/.gitignore b/.gitignore index 54f1d00..66d45c1 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ /releases +*.zip diff --git a/grid_generator.zip b/grid_generator.zip deleted file mode 100644 index 36d27df2736ce759856ee72569d92b108257609c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15171 zcmb8W19YX^wk;f1Y}>Yzie0g7+eyW?ZQHKcwpFp6RBZjJz2CcMpR@P9_x&qvtgLUP zrS~<*9CNj=jXt`p1TY9B!0(5Ua=qpsFaFOH8~`?eiM^Sjj){@Ak-eUyjXj-`A_M?% zbr7`q?{IQ~0ssU#0tNv1<4N|vfVe+_d`8AFus(r)2j<^_bac$D%^Y=fXl-5pz%2U2 z>;5~YvAvBIKJ6bL!qCRR!pI)q%*xir-VvV?@;4pwCpb6&tzx~V6k_o-I3NJP&(HV= zIw?JCCp}AAQ%5VyKj?=1pv{Lr<3E;QB-du$M-RPrgMzJrUlTL#mjrt}J8}#*%&G^W zL?W7Z`g|dw4*Q%Y6xP0rQ;O38<}eL=-VNspX-c~cXWJ99EI)dwzia8Q+~6{8Zu4ul z2J-e6tQ&^xJ$roN2}mJD6i=^0iCWgWegd2ocI$F3ied$Thza={0#8kHYEM;)ME(LX z(&RzIPlVLRaWll8o^%Ny@f=PEDGFrz>HB3F;u#x$sXn31nJ|8=I$qopgc0)zf+6S5t1-+BQ3bi zBm~+VEc9>5{nv)6eAb6|oE%Hl=k_gr2Gjox`d_tTVC(8=YGX~q#K81fHwJ&~}7mxYybdcY{jLn!1vbR3vo9{A@2=fXeo3LbWg+v^noNK^s!{xI30$sUs^;H zdc&&^v9p_;vABo0m;HD18S$Vge61#dTc&FVg}ZpFc=>Rj*_LNFqfp`JP*Bk4C*fna zWr|X_W#Lqk&}WKJKA>Lel7MO5xmkr9`EW#u>+sv%U8WmGiJjd$NJ<;KpL++z2?qr$ zD0ToefE;<~{g2(_!^1Ag{AD39!+-$)N=>p-y(Sy0wVLVYshR@?0O0taQ}ge~llGqy zWF7dAC(BA<%4SUn*~_51W1}*&<~TZl7zoV%%2%rpJ^&s$h7YAOL2z8#RBz9%xJqM4 zJIh3D4tNxz0SpAOtUuPm=9OYkmIN~q$#$6LM1F>dX?NX_O^>(>V=CR%rt`wn=Ezkl z#^9Xu;g=4`mP`uzqA9L+(g8yNeB7yRB>oivv%pQO-GtCwFsKV~?+RhSqEwx=vPw8DO+ov{KoKrwLB0FVjVc0mCH zgkN7(p(cd+BnpK&e-u;(vwqcjjL|hf@oT+Q3@WEKLB9fmv%;WbC1p&_w`r!FK)FV@ z#%}ARZ@o+e*(5nFSh*tbB{L+V4^V=Ah7J@oODoQp?M7~hGinN4kB-^bWG0WSFQKNO zQF7VbMA7;F3t6KA>0(VkMYnaq%o|IO?BszHl=R%4d$BW^BKm8`w>0zR%~E66cF}l- zFomx3ci2|O;AZB)25v76t>;md0@oI(DeMb5&ndOX{aJ+}JW5H1R9*jw<&tB0G9PhN z8N^b_e)#d;{PsBnj3j;2Ai=E+%-^mrTe$QW|F$iM_F zErU6Bck{WgZA*btFK53DVfLld8kFJI_BVAjUe5D#&Bj^qRzz8ujUO^W)wVr{HXUAd=+3Gu&MPap zooH2@QVdtnm$tdJg0Y4=?`ATP)Ua;6n*)$&8w7xWl?Va`e$}Upc0sxf2%4F8W75%5 z4V4!QIrJ{O2HHs*cr2F6a@8knNZ0PErPa6RD6&ClD<0hK7HcNJj1pxHGVj!7HGRn#$wJvE@ia&>s%wLo z?EUtRr^0?>kYAu&CQH{9jP|8gIcv55I%}2X^xRvkFO3(-tgNYg7t5D~dVRhm1m*At zG}UEVA7!1Nn$|3(9Zw0pc285z$*jG08c{s_H5m09jLo~jRNPZGk2j$GEZPU~zaMS2 zY%<^rcmM!2G5`S9|A(V(Xr^arWAgv!T%Uinvcwv3YJ0_w8>0)Y>!b;LF0cxXvwE_x z^GqTcI*hkmUJT>W@-RsvR6({fPtGc|lsF~{2BIk`^4-^rkGBVuBmxv50x!$q)oT8W80EvWucW=_^I-}RMALO!86E(7(b8gcq;GW}trJvx=`V&Wum!Mtdi z?vCcbxWYH@J&^L{7-~v|spN@gK%Sagg#UFuVkRH61Y<#<66>MCpjD20KHhmfMQEoOjSnAKU~Ukn6< z8nw8|#$|@sS#kHTeD+U3Z=2CI;SZ4NwoeAOn9&5gscv@8Ei0vb(2 zElOH^Ew2bb&64~ulY-P2cZ#FtDvEqtA*^R*hs?3aOH7GOroyp0v^FjsEa0pGqCtZTyd7L_!nM|`R+~Fb&-y8 zz^-Gem*$Uvo_TY(0U@A6kNW^YKkH64ez(y(){O?6C*m4OM=le93o8^BN3l*{t8L=} zsGJY6cR~|>kGfwe0Ibhu?)3rD09YX*0x@5SJq+ZGOV2S)?mKu_M5H$D-}+D~v3Rkf zqvsxQgoEY(NCbU+RJ~}%ru^FE( zjfz8Bl}fK7XaUwVOw&2HzI^(4bTOjr^`w2YM2j2Ab7wqi0zuXUa*`i@*O z@gxy@Rz-UcBAJqz^9u-;GPVaH1(F{TZDmgLhigknM(*cs5(uMd;j)H;qRY_MC@?FO zdKE^i?I*Kkmn#lRM{m!b%AommlwZGJ^J6L{i_NHw*!5~a7*tkFsG#!B8_69uRm0u7 zpIBXD-OsGP2e~aJjJTG><(F;1F1AS7D5=dqotHQ1$#g_6xr@syCRPs3M)B9*mzmBK z11W48i9W=&Sl*x1ElapV&)|LNOnB*6FTV|HomJ#rVab+$Ypr&U&_E|=a)_jBr4@0V zNH1b95fMa0Mgc)g0(5HX#IYK6;le=+-rz;g@fD$lva_1XROVrp71pRuX#u zd{-=n&UR+lQlLlMQ5#vHY0YGS9ZkHM%rCTrzU7;|^244$237*h*|}@N;m9D=T8FOC z7Fw#n%5V#)*JXoQM%$@K3kw)pCD9E$S%A387h$etdc-|J&GA)`D>(o=WrB3SZF*t~BWBhv0eyt8AMC>Qp7;I9y*D!)yEM7>F;q zt$!w#O zVZI<~=8$XbuUUjdXA~0NR@POg;E%{vMP`cOFEB;62th9l(eqi8BCbK}22NRoS5S1c zR4V|`Lw17Xw%~sjSP~GT(x*g3VMq*x)I!)|QF-ifI|IaSZY*3J2*A6bu0>*0^?-0{MWlp-jz&1_h za}SepHs<#RWrk`e5h>kmX+)A=4W)LWg0tk14Yq%}bF)Fk7N}or@O-w58v#~<#ZKt% z!CP0mcvUajKc_}tGd-GQ#uh($?~RK0c!}c%TSK%hE>no5K3az@AMvX~1d)gV7A3YN z=1x7uNOB9R*DYY~6W`fxQt8SB?Tn+Ql2V%v6)Ls)SWEkHz%K>+<6F)?S~gJxx_k2d!ry{T}~VHB7tud_E9XK%-4)lZnC?qF~90$ zQt@N^Upyo0qGzfJr5I)bhUS(!Hr`Zomkn0NvJv7%xlyI)7n|`qdlZ4mUg&pz5IBp6~caKHtx?G2VH8Q^i7EY&2B(=8&TR zlv&y@!|QcxhYD@U>|A`xI3aq~4`aCV1%jFU%c!p)B6|YQy9yazHt}d;#hbz^5!RJj z>RYt9wPhaT3on>fP3%f#=Lbxng}9@*A}-K;KqI0uS8f~B)D{Sbfg|NS<=uM}79b0y z0?Bw6Z{mt(+BFlk0QX{)OxD8*0ndt&f+F?cWMA`?^dtTDpbN!_RmE1@+Hfqk0$7n7vPJ?itgLT;1e1nNxJ!B~Sd;v$M67m~qr z>nX-gM%Cbc$AV^R2SYOLA%`NHxo->~7t&|a>;c+PzXD9`<^t38)^tC55aul%RuSfh zrB>G)-(ue2<27@?KdiouNhCW+HuXCeYpE4AftV$y+$ZpkVQ)k!++mf(gJnDP z8&J@+%rDP&tW^hQn@}+nEl8AIOJwKK^_g~pOJCkMyY!*qabA`}$cFOjE&B(<&d__~ zN8-->eCNXi&a+dDl2KIYZG?pAay#xogVCkf*aM^HW)J+{&*0%&kTjUAV@KdIA@uf( ziwu)$=#?~SrPZ?eRWwBK23J1ywP=>s6HY zCUKGzq2h}fbkK%0)k5dBr*x;*TS5gP&Ty`A5HRxwSLb3BRRBko1=r@jqaGNY1m*Y{?$pW4RJq$jT005JsW zU0VALp9QQz@AWTJ$#y?^AQ#{F$cBWIwMW=boB3ZgSHM6KEZZgzQ>KfHbykoard!JH z6j~B4Z5nn8u+sHI$Vd=^%bg={&D_=`nf5q11BdkpVH2+z@siN)K09jo=~M_8&G@*4 zlR|V>KJ$DWdJKN2FP&J;;7He~YhhxQk$%6f7+g+beqGV_*Q;vH zD3`Ez+SlZcD<|8%CXsRtK4p3VcAuOf;P}cIRaL-qQ6Wd}FiAVIoM`73AJks{t9}fQ z_E3{&WPhyr89~d+psG=#?0j?qH{Lwj$Q&$goK##6OU}={REr~(e@Ia9rf*|m55lsGmu>AfMEk*4qI z`ChX_rtHD!NIsRzT~ddDsR8pJqcG`x!FBx)1Hx1qmgT^a(ns2Z1l&>3`I8bI1O}2yBT4|z-y+; z=8v+XsFyq7=gPNTl?iUjtM)Xz5WyT3BF^Di6tPGh)gBPWa>W;rJr+tT6;b6?Fc+F_ z2jm?CY_9+;>N?Xkb*E9k8v{a>Wj`vbc#?={8#P;?EpEr%>$Aw6b-CI5L*=GY?l9XFurmWbV z4_ng2UsemA6|OzvT_NRjTgD;JY1u}CtR57Tu9n`4`#EEsrG?j+W>n991f#i3?xG^e zHVa}}vB(@kGCD$j!6l(7JUl zx~_FPqh@M^ctYZebca+=6nmJu;i2}Hud9dF0S8)rXGK5kzmZKbxDaY5t#cuG?=EZn zZbY*~F!x~S#@{b?8LO5NlV&X?q}Ufoa2V^ z$JsfUjkg=(fFd$oQdexAO26V1W+v*=*KEZPt-iUSE-N>EcU0|a-1wB*y>D5yw2`D! z)+ZEgg1H{noXuvm3|JoYkH@7Em7ok7)yIJtMwyy zCvu?}O3jfdEeNxRjY(2`sVRGS5;+LMu9~3nggm#{E|kvb(#RvQoYl)MeXnlHtNCOj z*->Cdn-ULeyj}*;MyJLJ3){VZY*zUjL|6B~DCRed+#OxF3uS4omrQYrYVb*b-fG0# z$lh{G1mHXNsm3r|3L+M?`N9NYP15_dUS2`t`svRkGmAWT7vCIubB845hFBDIP~E^S zPMj<3vJt`}EU$7J_0p*57ev6FvwfXw_!@2<6cv^-mdb=G;TDX)Vf|=2jQwyS)7f{9 zOOZFqk20(NY&zD4uP2o3m%Er8b2_s`fxnvvm~j*-5%v{ckf$VjRdFGFQ3%7J-0#0n zAutbf7?;&PWse|aZx`DZ4|#n*ABV!m($+;pB+=e-Qz}|#^aL63ZHCw28;a$O`j8Of zI`?g&*M?@%_OB48-^cE4Q(qLcH>zk0wcW-Ru{*~B!jB%2bOzGrLJzw}SZ3C6Tj1ZW zB0m)nkW4Tm2i7wd5pqR?L?ci`Y7KrzHGGb$2+d!5^s|%&LAImVQ+}f056u6rIE*6t zizt8ql9)tLW0ONN88nGb6NV}tjyBhDL@Aru)2v#Zr|9e~L8Xi*qZUtWGwIAzZ2b!c z0RpiSof6*YPq-!T+^F`_^9dOnKq>ImZcy7q5 z&M;>{FL<(6>X9r;W4FdAfr!1ce|jtR4XXpo~Q;O|+5ifGLl_zQu_xDP9rU6YqR9JKH;6TaOU@LAE@&ZO{s zCc+i;`fwn|d9spQ29an$fY%??dk2}C-($;>;)>(fLa}*9^-Cc@WS8SZf`EF2fJBN9 zkupLa)u2AykaqNI`MMAHkZ zZ{O%JGCMCw=5l#2?XmCZrs*((JI~ASl|5HU12OH%;c2ylE7GCzfP`h<)q)cYV=NU9 zMtc|f`7RdvLjX8JfSWDp{1Ps>2%mlk@Z|DkG{(yC>>0#dgMy>cjDitz%^8TNqF504 zD}-@x`g(`9s&XT^8!1T4-SWyMc^7_tPqp_hWSB{-CZBKbov=Bzwm53sU)hv<6iazy z`&WC#^RrWp$2BEP2Mz#miwgjN^Y`}3Uvz~3t2?}Z_Np5{<3EIe2{k#J-DU)@hiY9E zWHL7O0SL_7nxEJ;VyrC#R?hWew4UHV{z;}9XlnDZaRzL|-WSjmp#{XNBYAw~!9ti5 z9vM$T*s%MCu?})Epfm^mJ&Kp0uE=8iVtMZqVols#G+ZIIvTv7slsGT-ix-CmzEGT?1U<6O85 zFp!XUu!rE;kv4ScL*yw*S^}01#SgHggDy~v$BPWPr0WXMqdiAv%}9nMk~mVJ`wrfw z+kqxz8SzQOpXRLO3&tO8vF+8`ww)TrJTystW+T>y)rsg#<07*Yvf*`5npix_RC`o{ zh&CC^g1RlD*CykS7!2fD>++H!U}D4~S)?@>3hXpF@)ZuZhUSCXq`r+*h3oV8P2xLS3Zlzj3D&TN=Hx=j>wSyjNEA?@{47|^uJ$xQocN^p7T zM^oT^vHq$i-_!2X-LE-=G1VTdHTh$@F_FXI;vl9f6@SzIo1n1lm%%MFE$O4)R9xjlE>e!3m19L)to%&| z;iioR*W;lQW7NS8>}Kdl-`-TG?l?3W+T7C)>2nu2s3jTIrm6L%B|=OfrvW8%@!!DVEe3I&ytZ5!i z43G>1m5TTFH%+sLJbZXL_0jyY$Bd7MSFw%O0y6mn3x_?OwSaY`rnl0=R0U1!ps!XE za4i})Nbs7?-qFL7Fx_f~_iQHHa)!6=Hd4?{UAm*gZ$+613?(4aTm8gCj_HXM8!O!g;=4Ehtd{#*fX=|px4?gff00u+Zm!stqG9O4%J{zT$Uv#lKCkvI4 z3)(04!j6E?ty0_$gBSx*7{yIEDv=Cro9ayHi#vY3g@oxys{TF!1DXy=dZ^;}(KA12 z;mykOdTe|aylju9P|nr6Q#QGjK1;S>aXwH!$mVZ764sM_D)<%+v&CrC_WY&ySv5{# zZMK-#(Y{S9eQ66fO!qjCU;(q7tTERc;rGNO$y#@$l znCB?4LXuMy_|ia!BW`E0_A7`bwlxeJQFKMriAg&@GEM?7$g(d>9j@nx(9lN65;tt6 zMX-5ECT`>p-l@~%Q6j30l_sZXK?{(yCZ1R`my15YOD~_Z^!MCo)8bHU^m&41GSTnp`dEsofN!o{Jh)&W zxQGGI`r*3`q=4DdxsiCg9*cOzfM=#54FhO<)qCJjW81Qo?iOAPKVy4DmV(x4xCQpW z$r-56*!;gY*kM9VTkl+yQ1kD05)F(+D+3a?m*4orf}|_n_CiQ@?%d>|e_Ml(n}$1NCorA+&}@4i=6!wtuMC0-xgS@A!|~53PtE z$XU zLBIvTCnM_=n$#2(lyrd8uR)V?R-#tqoFkNUdy~x2*onq-+AN5SAVUsM%cGHNtzJI5 znBga|iw0jwSDob~0Y|VzKccvAOGZ;euZN7)qLJqXrlCHtedPce^7vu@r4IN+((o-wVhYi4{u6WOOE9mB&rD#>;7ItHCD2a_!(lKg%4M{zXCnc8L-wh7!SZn&O$q8k7Gq=GhC@*M7T}rc39rZbJF~xnj<}lge z@QcIbvDdl@;pq94+2Ono*6$Hbz(Gy?0qr9qO$H)rYnTb7-?SjZt%sDBAz;jFEmHijf zNF!3{@ZDJL5p;Iky2TV(U#ub!?Jx{Wj)7imaw!vi66DLbW&0}uLec{1XCKQB7muW9 zP2QyDKs+P|6{N=*yDK66ck_(HI0nFnBY>8m z8N>|6=ruvtanud{sbGYZJ5bpFL=0yH4>=H^N{JkYLzvx)jg%Lfj#R6dkqme;MJ9N| zkj>8;>fxc@7$gwuqKYg?fUp|>_O0_QTWb93eYjT%H%~a_25tjf(3?H=mTYT$>yDh) z1;^%#H**B$9YagbM){KDc^MR2il)yhymyP&M1;Q)1Ggz(e{~NY4`CL-i&Z#C+I3DL zcnXkdBHyX`Y84kc-#X|0>U}o54*cnaOyYzN$RkP?;ZnLJesP46YK^{W554e$E~dW- z_pXeZ1)8~4Ptnnxho8`zW@;=reFHY|q&m9ER)jl@Q59XT!|8M?bGoRCm!~!+rC^SB z@My_Q?V@r~jv11MoW_qtDWc-yr2MMN@r=SzWj9B+Mj$1+G~5MN990JzXt}0&0hTqV z%6#6#A}YNVTaps|h7obqre;Lg$PB9n?4}=xZjR~I0k{i`DtY;+W!qI2IBy(mS`gv} zJynbe^@+K|K`2@?(AqdKjZ3}kt>)UEW=<|v%~a$3H>7QTGs`HRr%(8il$@wyGdg1o zHT9^2%N)U*IWyuasGeTwRlcr*9W?x7q;8x|CC)}41RTx__VWv?11;sZi;2S7n?-IK ztn*kPJ)~|+R&p02ks1CC*iLs^Xf(NQikcHmi?$4*IO9Ewq<;!}nx1Pa-B>-|=*G zx>)mba9SJ;i-g<_V?|;e%^L%XfwB`XXS-;3J6sK8IVOgTjTI<&@?NOJCVuAY$3++X zz%m}Bw&-PKi zg-Dxxc5GoMO%0pjg~w#S8uv>xR+Cx1O-NUsak14wrG%#y0kk1pyjyIXhI}<2dbrqc z3k+1M4Ct*!{TIa%WdXPmk49{lH@MKNd=Gr9d&%pIr#oa$Hj=?!!n@@Fq{uT>t?u`G zV3{ox9y;J=B@tX8a|D5Kc)Ma#$DDqR_;<*tKReKH&KBWu+U0GxpHl-U16daFFvWxU zFVqBa9hLLd0D#s=0JYU21^ODycGq&TYp3dR+&#hl`oM>KMUhKdz0N@sn_au<&T2&C z7X)+^&$&rH7!T$^g?cMkNVZrHZLpEQ?H2-_Ch@J3bUrBREyHZ(hI?kIIY<1d4FHUY zJ}d&|Pgc-_oTF<}Xv&v%F)A0A&Fp7?<<&cq}h{4*OC&!#$SR|=~nL-jeHU3a_$80=C# zEpRQDv?$+uz{n9iW>;>ue5zbwE7(;!M6b6>244fEyXKFl{BzSlOZIuw73g(%dU_HY zl`giqT&yIJeppVmCtBbNDBJ2%v0HO0rU4x#^4XByCF6Pc-Y%CnSPZ?v8Xgy;&ry7+4ivyOLZ)9nrw3# zfaIpMprLN&NZio;a!$c6=wXJP&3>G}1@DVvB1!G8gRML~u5^~(@-qTHDjc5bp^)Dx zKEWQOL^vw$5VQMIIr3258#@5r&n2`Qx8fV;Mf>-c2B3AK8E(*4l|1+Gi1O|qVv-uZ zS7H%#tMMkUm_NUVE@y4uj91;ctl}{VPEmu*J$#IXzHgl#)&9u1B(}CyL(1xfS^SbE zBDGNWBuCVwM5l4bFkuh})jzg$KKZnI2qoFoe`~_+YFq}LYbcm1cNosFQp`3P%4huBd1WA zXyOpFLvDFwZ&u)ONDVx%ZjYbR)IZV=DxE}Q2c)qD!fr7=zMMh6t*Gv^il6|uoj-&| zvo1IaYRB<8G9rz`Nr~lG%{P9cF}}U}(GBx!)Ue4Cd&P6?(5D%b(mw^is8=8$In|aJ zrLCuYzzlhtvO|L5owT1+grF`>T=KF>zRsaFj*pxo@T^^Zgiss+J8-wyA(R}?n}~81 zVM~?T$xo)pSZ*mu|J+c34_bH`9Z9~%ozwks&%gKEyg)XCv zZ1m(PFG5;4x|`Je2NQ=#PYxCD??U!42k72u9@o4gE+&4<_u7&;0{x)5LjO|ctx-FT!G zo{4~*K7=u$@|K4W0r!?GhlygsiZ`UT>O>4^-d7-^Yhc`jlSY>&7FTL>5{VYWMh*o- z1Yf=|s(pTgjyqr~fPK}8n!pgXA#CS{)Lt690$D9eo8eE-x{cSdfZYC}+s51^F2G}GYLR(0NLODZ*6p4Po zK3TdpPk?n;JLE<$*2I-RBbci#CdH)hh=*=407Lmna^e>b_R2_5AUT#X9fd*6uh^0fDQcqBa#Uc{L<~#YIDzmV90vYSri{n#*We;qz*>6 z5Ftwxh-k4ovzrGiYBXiXY-tf!x^19vBT3(*q5^)>at*q4VUA^F@8v{{J{2Xz)$v}? zEA!sKG8DZX%mk7IIFATN(H1jm54x0)p+#XYk%IUvVfq5TY9r;QR^pR*VTKUmO-!YQ zC~~I!I8N_D(nOhJoz#|1(EI{oZL~g1GNxOXKt=gof`ww!jL)Oj`N)AS8g|8=t^=&i z%41}G)$lxpi9+_?F_p^~;wiq#T^WsV+9{LCwn;yWw!M`shr3*Z$@QG9P*CUWyLh8Wx{OEgSebozT)yL1 zfn`1oF4w(grR^Sm4OZEhbi$=#eLzloldtDp;%YafZLANxUzdORmFU@WKSQE1(@?o} zlBBtwTHAiATbu74`kq;D1ch{%I+Asr?yfa+_wL+$0}Zb%!o7^=FMW4AKe+y=#=(6hLoCZV^20|V>D(=-&i+rJdCOX?)0N`|1_z~!u`kvS*wzlh{0rb2w~y8_IAbudE2ox zAsPo~Sa=18vVNv5{{i*@J2Pb2T+rrVU6Q!XYT%J=vAUuwuO5$!>&f&{?jb*P;h7;6 zL!l*;!a?C19_LrPx}Jhf(PdCX#Dt7F`#pxs#ZH4}?3{Lk_%CnH(1qos87YwXA@_GH z7jCRx{(ibX+7iYbkV{V>8Yp*PO8KYD1f^t@_F$DeZQqULIpWUw;xdxUVClA;!7I$mpq3$I4g}ibje?U_i10@e>EyFha0j=5|A*PCNi*f!&x&w9eLqGlzEP984 zu08mQhd*+v;uT)bbNwouPC@nw)~q$iR*7z=29yqvci_h&76AiBRL-SROx8-fR1C?PNYFY)1Ym>!b!{^)hprn0n-b{7EaG2F! zotdc#m|v2hM{nY`%>;Mt*RLH9)?b!>Iaj%P3~7Qgi<9+<1rv)&=_!|M0Eq zi98HS>#lr)v+kwtjf%TG@`YsSJvx#uE!0ZuLj=L;eCn(A0qMtEVBistco=)*bHkED z-jc6A$yvsHhR}#mfal zyI}4yIcJAfJ4g9 zg(qY>!pZyDDKR1sE?mf`Zz10JWIJp(A*~-LqcF5xVZm}Y!MsFXHuRsuw-wp9vco4e z|4>Y?$&`}ZLuj$(?DTYs%^Oco;vX zu%%?S_1b&TGhV{Qe*y&@@($lK*gd>Bxzz8R%D?s1|3vu9LOOLG5+faXnwE-VbIFk{ z-zj4_T@6ytFv$1c9vna*T;TuC35WjK%l-X;2RP^d{rlgIH=n*I&_8`~|IxYpE9l={ zaesn-I@SORe8v6_`d_}M-yXS7{NEnAf5iXqY;b?YZ~i;}znS7b@qe4*{t^Grr2O3q z_Sd8!1N|*2Iy!$fhJ6zJLu>cX1pT>yzuUt8FTw8wnf=cM|COx2d7wUtf1AYqabe$P<+56kl_)6poobH<_v^c%)a2r+)vQX+>?&!j~F;pZ}-o`e*71nx^qZ zrdBn<;Fq;QEwAA;W7YT)a_E_e{MWC+DQz82F$P+T4{KUXMq-aV95v>~-C74esAFxq z2zK)5q5=HeZ z+F)?TS{_mpOl1TC_(9RD4e&@;N+N<-jQ)vihlsaK(Sb)KBA(Aw+kRL#54lm$4DQVesL7j03Ohw*`7Dl3VuL zTj9YD_sN?vK(sMmWd&ynXZz+c(nIq0Z0MaDS>ckl7yqs5=mSmHZ85!Li|LbwR(c1R z={2EE%uEd9j|@(ee~Zo|vd-=;&i8_rj2-$BGNSim+Tq1ljSPJNFy_EFj5`>CKoj3J zZudr#vAF+WoS)7l{H?PKp`mHT_<=`on<mPt%brT9!V$;SoB zo{nesz*n5lq(`H|bdpcwyQXb6Ya*VUPGmMEamefsNai$n+GI+4`8z$EAD>e>@jRPyy+q1?JVvDFnL@fon&|Qcw+g4F8wpq^)u|-c< z^n_PY=UpuoX#J_4sQcF3jrqOBra`f3aK$~8HIYbvea}{-gdVTOplBn0LxdQp7Vne^!(7)o^mNk@+qlkhc3g+hufx?kxdKLA^JfDbs zKR$W0dHYJ;;3^tg^R%pZLRro0<`ObqG+!_mQN4)j^XmK)t0;Uw5BxNj28dx|WGQx) zf0vhqK*=p4_Y#EGA$mF##UiQ^QB4u~MdV*a4Y=7hTWh>%xnL=xHW9TIQICjvmivmm z`^DbUq(Vf`M`svj5K{iJB zJPuN@J@Q5zfw9m|$QU6lghYU(iJQvuyYWZP06mZII6t7zUH^mYB^4dOL!KD@Fuv-! zsr??2H{yBkobwhkDSyPzzh8zM3MTi5D%+aY#@=P2MIe!|;p3qEYjuJ9J2!W)qfLr`si@HQK z9nE9}<)CGdSYtx;xiZ!#iD!ZIF3Bdd6Y+)UG*nJGB4$=d@)^k{#7{z6Bpw%1r{dr^ z#fPfo{1Ik}qB@qElJuEGa_U(=o=yt~2~$6nnn?+h&wxEBv{2^bnMpnsi%X2$4y5`CRZ#-yz-;u-%eu9u_gbe4lyF0w(94X&`QS^c_}s`eIL?V_u_@aT%Gmy}e)MdJnIYf$YPMbwyoY?)m}+in}| zxrcB1dy0l$(a>A6xR*v&EKMbM?N!UWmZCc>y2C5(t{hYH_==v8=m`})U81LJ@o2D-ei6?F z{qzm|X7C@bGLS)xq73kpGx9cMWb;7eUe;Cx4?vfGk`G& zJff2`8A5|>m#rM8BZxO{(XFbu2i-q|u4()evJ}oJ2V)-pV|XW7nWc;3t($6*tu9Z& zye(42*@$Aq5C%B%_K9+E6n;VD^hAtg37lQtCCB*f&Dngdv#EjN9F;JLgzTCfzk5%L z8nfbc7wdk2n3J|7LAhTbTpHYH0e1ZBb|RuanO#v7<{&Dy2w&W->h+ol5f4!rNp*V-!-)r6mni zu(U9bueQ~O>7=9wuQTzf3lnd-Gzo=xANBgbKSvOE{~!ZFA)^@6=>>l|pTWBfoGi2Y%&U(&Ym`GTaDc zN7kI)rM`D2a&*b*x-^mBE;`$DDl&d5r@F#`FSKtmq*?sE`c(lbm^3~^hs&N;cCP)84E4#1595M(G z!-sN7BRxvFpb%Kd*EP98DNRo9Z{&6-wBrvu_BD~~nb1i{Hz6d`gatxK-w<9TG~7sq9%5D$=ONhqN>lZR`)&xzBZy z4m74+>794)x##@Ox%ZxP?uF#1`;4C$jRp$a=Q;7ftxLv&R$y?X#qX06cljf2KMfy? zHmy$5!6kh?%|KosrVZfI*MX09ifmlpr6Kwh<%c@G3wCi%1J^~bU}<`5AW&;3Qt(M9XvJ<*5Iuj>OePYf7M6@7}5sNPjX8|qkxb)~W8ncbYj zylioaPgkwJ%67mzTrIr{E^$8iqgdl+mi(jo1650LLl+Hy*GK3^m}Km>JAJ3AeQje0vQ@_zW(U}xjTxGAQA0mCNvljxvXvKW{V)>g!fHB|$+looX< zs059o66Y709k>nZ7gSI2J5i^iN0j@qBo`R2JW{M<1H_d7d;)WtLN zT=beZba5S=w>$ZDv*x*m`{%ih@Iz-KB%FT+SM6eG4X(P(k7PCtrv?wEl1eKXi%%X( z4<3w<49ST@8KoJb?m9XOJKTPH;PR+DNw+_MQV~WW%E}f(Rui(7kY+-*A<2+f_WKnt zVZ=b|4bUlQ^!|=Mc=f)0<~v z^IZ1=OId3m=D#TLD5xgXPqlC*5`xeC--hjhRT%c;Iv43N44#Ndjg8%$9lq(~85TLV zJ2-meIN`m3$02iZO6DbfobK+Us6;zvi3ZLyPP3*O891xyb)&GC_L76P^Koh^O{rZ2 zIP0rG@e)rKPg(*uK;nDr$%Gi!b{|7lCt-m#=pasM4HY{Zm+c6Wp_lB{f3&_gm#s+x zdb4CCiE;dO-j3hlZGW%|F7a_)6?e&LC*o1Pja8ZDf8Y1|I{WrYT$jGW^HaNo{&00Z zzM=-;ZbYhl@`rsvdn?$E zU^2MZ=TFE13*`%bplZl?`JFl8q`yKb*)UvRS3fCzZr8I2-bB5*1PkloXP(HklqQ z^V#8%!Gm%tlPNRDMv~d#GCQ0a85+)(d9tDb6;!OGZ+a{{l9u60$o(K&F;h0ksbd3` zMQ20=^{;4^?6`-RvTsGK&6sy7rFAGJr<6oCbq*&or=hvAyV2tKzIoDIv^3@|jRi|M z$CRwjqBW4W28z~j-Wo1gBRLiljrMVux9AGzUE!juBk$@cxVmy;$x&N$H02#l1xIs^ z$8>Ueb3#dQO|2^kO(l=7=!xY$v01j@xjXkzNi?6|@%)Z+Jw-8`7sE5c?4GM)_jQl& zN39oH3!c@vhu$@NrcM>>WBK}6p}uW)U!ndRC3mRkj^*94!nnI_f-U*{MPGZ~*FL+p z;Om|+lq@wxOE7NgBtyKe21+GL9zKPvvSUSH#CghrJd=f6Ty=wI?j z!gmO9ilXe)wo8a2N+ROn!Nys&-lHFq4moIV7aiBj#ud843f=RlYwG)e_$?V#f6RSv zM;Sak*&>-G3oc3piQ@aOQ`2|r_6QBDbLxWr>l{jUYVJT%IZH^0y8@{?SHEO*#iZ&& zjFqi%9uf_Xami|@_S*K^Gujy5$+!_liaLUaBim%VWW!@INOlv|q1~<7X(s3Ar!rdE zF59ZhmmPRL3X%gQ#SU#0wPpRz$%^F8%auP$7%MXp-Ah7Xxxwc;7Osmz_YhjIV(+IS zrXB@%l~N`MK{(7Zwf*fryQSY=(&4k@nlUc2UM8~G9cKKCy|j*r(~F|O1pncwVS)=362(W*Y)B$C zW!-2ZI}9JLIZi(YgKdqT9x|s2kat^|TR)mk9yyfSpu7P;ZtF5_*V4fW&n=4l7aoWA H+gkq({j+TF diff --git a/pykrita/grid_generator/grid_docker.py b/pykrita/grid_generator/grid_docker.py index 53a2f66..8636d6f 100644 --- a/pykrita/grid_generator/grid_docker.py +++ b/pykrita/grid_generator/grid_docker.py @@ -36,24 +36,40 @@ class GridDocker(DockWidget): layout.addLayout(thickness_layout) # Width - width_layout = QHBoxLayout() + self.width_container = QWidget() + width_layout = QHBoxLayout(self.width_container) + width_layout.setContentsMargins(0, 0, 0, 0) width_layout.addWidget(QLabel("Width (px):")) self.width_spin = QDoubleSpinBox() self.width_spin.setRange(1.0, 10000.0) self.width_spin.setValue(100.0) self.width_spin.valueChanged.connect(self.on_width_changed) width_layout.addWidget(self.width_spin) - layout.addLayout(width_layout) + layout.addWidget(self.width_container) # Height - height_layout = QHBoxLayout() + self.height_container = QWidget() + height_layout = QHBoxLayout(self.height_container) + height_layout.setContentsMargins(0, 0, 0, 0) height_layout.addWidget(QLabel("Height (px):")) self.height_spin = QDoubleSpinBox() self.height_spin.setRange(1.0, 10000.0) self.height_spin.setValue(100.0) self.height_spin.valueChanged.connect(self.on_height_changed) height_layout.addWidget(self.height_spin) - layout.addLayout(height_layout) + layout.addWidget(self.height_container) + + # Side Length (Hexagon Only) + self.side_container = QWidget() + side_layout = QHBoxLayout(self.side_container) + side_layout.setContentsMargins(0, 0, 0, 0) + side_layout.addWidget(QLabel("Side Length (px):")) + self.side_spin = QDoubleSpinBox() + self.side_spin.setRange(1.0, 10000.0) + self.side_spin.setValue(50.0) + side_layout.addWidget(self.side_spin) + layout.addWidget(self.side_container) + self.side_container.hide() # Lock Width/Height self.lock_check = QCheckBox("Lock Aspect Ratio") @@ -65,17 +81,10 @@ class GridDocker(DockWidget): type_layout.addWidget(QLabel("Type:")) self.type_combo = QComboBox() self.type_combo.addItems(["Square", "Hexagon"]) + self.type_combo.currentTextChanged.connect(self.on_type_changed) type_layout.addWidget(self.type_combo) layout.addLayout(type_layout) - # Layer Option - layer_layout = QHBoxLayout() - layer_layout.addWidget(QLabel("On:")) - self.layer_combo = QComboBox() - self.layer_combo.addItems(["New Layer", "Current Layer"]) - layer_layout.addWidget(self.layer_combo) - layout.addLayout(layer_layout) - # Color Option color_layout = QHBoxLayout() color_layout.addWidget(QLabel("Color:")) @@ -92,6 +101,13 @@ class GridDocker(DockWidget): layout.addStretch() self.setWidget(main_widget) + def on_type_changed(self, grid_type): + is_square = grid_type == "Square" + self.width_container.setVisible(is_square) + self.height_container.setVisible(is_square) + self.lock_check.setVisible(is_square) + self.side_container.setVisible(not is_square) + def on_width_changed(self, value): if self.lock_check.isChecked(): self.height_spin.blockSignals(True) @@ -123,11 +139,7 @@ class GridDocker(DockWidget): else: color = view.backgroundColor() - # Ensure the color is in RGBA U8 sRGB for easy extraction - # setColorSpace signature: (colorModelId, bitDepthId, profileName) color.setColorSpace("RGBA", "U8", "sRGB built-in") - - # componentsOrdered returns normalized floats [R, G, B, A] comps = color.componentsOrdered() r = int(max(0, min(1, comps[0])) * 255) @@ -143,46 +155,32 @@ class GridDocker(DockWidget): return thickness = self.thickness_spin.value() - width = self.width_spin.value() - height = self.height_spin.value() grid_type = self.type_combo.currentText() - layer_option = self.layer_combo.currentText() color_hex = self.get_color_hex() - # Determine target layer - target_node = None - if layer_option == "New Layer": - target_node = doc.createVectorLayer("grid") - doc.rootNode().addChildNode(target_node, None) - else: - target_node = doc.activeNode() - if target_node and target_node.type() != "vectorlayer": - parent = target_node.parentNode() - new_vector = doc.createVectorLayer("grid") - parent.addChildNode(new_vector, target_node) - target_node = new_vector - - if not target_node: - target_node = doc.createVectorLayer("grid") - doc.rootNode().addChildNode(target_node, None) + # Always create a new vector layer for the grid + target_node = doc.createVectorLayer("grid") + doc.rootNode().addChildNode(target_node, None) if hasattr(target_node, "addShapesFromSvg"): - self.draw_grid( - target_node, doc, thickness, width, height, grid_type, color_hex - ) + if grid_type == "Square": + width = self.width_spin.value() + height = self.height_spin.value() + self.draw_square_grid( + target_node, doc, thickness, width, height, color_hex + ) + else: + side_length = self.side_spin.value() + self.draw_hexagon_grid( + target_node, doc, thickness, side_length, color_hex + ) else: print( - "Error: Target node does not support SVG shapes. Please ensure you are using Krita 5.0+ and a Vector Layer." + "Error: Target node does not support SVG shapes. Please ensure you are using Krita 5.0+." ) doc.refreshProjection() - def draw_grid(self, node, doc, thickness, width, height, grid_type, color_hex): - if grid_type == "Square": - self.draw_square_grid(node, doc, thickness, width, height, color_hex) - else: - self.draw_hexagon_grid(node, doc, thickness, width, height, color_hex) - def draw_square_grid(self, node, doc, thickness, width, height, color_hex): svg = f'' x = 0 @@ -196,32 +194,36 @@ class GridDocker(DockWidget): svg += "" node.addShapesFromSvg(svg) - def draw_hexagon_grid(self, node, doc, thickness, width, height, color_hex): + def draw_hexagon_grid(self, node, doc, thickness, side_length, color_hex): + h_width = math.sqrt(3) * side_length + v_spacing = 1.5 * side_length + svg = f'' - v_spacing = height * 0.75 - h_spacing = width + rows = int(doc.height() / v_spacing) + 2 - cols = int(doc.width() / h_spacing) + 2 + cols = int(doc.width() / h_width) + 2 + for r in range(rows): - offset_x = (width / 2) if (r % 2 == 1) else 0 + offset_x = (h_width / 2) if (r % 2 == 1) else 0 for c in range(cols): - cx = c * h_spacing + offset_x + cx = c * h_width + offset_x cy = r * v_spacing - v = [ - (cx, cy - height / 2), - (cx + width / 2, cy - height / 4), - (cx + width / 2, cy + height / 4), - (cx, cy + height / 2), - (cx - width / 2, cy + height / 4), - (cx - width / 2, cy - height / 4), - ] + + v = [] + for i in range(6): + angle_deg = 60 * i - 90 + angle_rad = math.pi / 180 * angle_deg + px = cx + side_length * math.cos(angle_rad) + py = cy + side_length * math.sin(angle_rad) + v.append((px, py)) + points = " ".join([f"{px},{py}" for px, py in v]) svg += f'' + svg += "" node.addShapesFromSvg(svg) -# Register the docker Krita.instance().addDockWidgetFactory( DockWidgetFactory(DOCKER_ID, DockWidgetFactoryBase.DockRight, GridDocker) )