From 2f1a83a1a8b967c78ef941754c0b98cbfa6ee8b2 Mon Sep 17 00:00:00 2001 From: "A.M. Rowsell" Date: Sat, 18 Jul 2026 03:19:13 -0400 Subject: [PATCH] update: start to bring up to 2026 --- img/example_epi.png | Bin 0 -> 38746 bytes spirographs.glade | 331 ++++++++++++++++++++++++++++++++++++++------ spirographs.py | 6 +- 3 files changed, 293 insertions(+), 44 deletions(-) create mode 100644 img/example_epi.png diff --git a/img/example_epi.png b/img/example_epi.png new file mode 100644 index 0000000000000000000000000000000000000000..1ed6cda51d3a86a94514df55f55a6846b5baaa5c GIT binary patch literal 38746 zcmXt9b5vzr8=pMYWZSk~lUL8Pi*n?x!QDVaX}DG{W@BMNr3?XQjM zPIvYyD*`Hrzxw=sh6zo`k4SXWS2jo44;X&~ZSjS?T|xv(1X-vr)90QvrzublSlg<7 z>mm*GDQAW@F~xC=PxQZfZI}FgYfxfvfwz1!$ims2Z zM9o2q$ygx1AzQ|X+2+R5#dI@Wm?%6BD;O}W3rIpVrBETuCXFsjS9lRwGD^C`G^P9-^;k7}Au1fy&PQZ74a~O<@Ldi&+bYLQ!7n)JYNycL+>k@ziCvd> zm)TQoAD$%~Jwzgt4hiUTc#Ocbz}ib`Iez(qIPl*KEQt;g@5>kBFVbSds%~rNS*~75 zhnxSl&2kdh;@Rq-$Rh%4OY(OJOIsyFbQOu-?q@F_PimXaEOM6A`FxtHmdY`HqQKCG z*Oz=3fhHmGjA?Lq?7rG2`a_LOOajxyu$^+d2bD>8+%KjTq~TgD~R=)NkND2QXqR;KMH?z}rL!ar!I%cTE1&s8L~G^G7;(M8hDBm0?-S zAj`xY#>@=;rR2CD*p$m4gH*@JiT=CJ?JT-Jb+`~V34S!|DI)96_5MBd&8tYDKg#+Qj812#Z-T!B3bN^*Hd$Xw^*PhHk_h@uD_Df zz|r79Q$Pnm7wE~?>ji1mh)~Au+z0(_d0Ck~G3ZX@X@Wl1TdMGgJqe~I;;!Wuk5f;>bb+upxD=SPY|#wRJ) zM_JyoqLxj_kSf*uDbyfK(PQSr`hsePB3|1L@l8_z-@IjZgDaSgQrT2BE+tz^T7vXs z2y%fI3OC71#PR2*Fm#peBSC{h<8~169RuZr1k+r0wlH=haN43w$R_Zl_k|zK$kDq< z;$MSEoql#TBDMd;b(uecOUNQFAzdEuCxtIFC6I=d`2q~B-;cmw%pxt5vTwg5rVO|U zF2AnAveMqkP0%qXm@Xw0s_D740keFWi%ob3Y8?JEb!4!XDQrqb^&{IXpLSU;UN1_a z>bpz41fk2T#hGhul|`z$=kM?XNYmqtvN5)}Qk8;bYRV|CV%oUW-(1LlPH$DVEefjF zM}PATWXeI%(anvFOZAni$-ky4mBhT-@ip;OwSm3*D6CdBhOd-A%B|h7Jw4{z~gpz{UwS_5Yr4#lbJ4Qu9Dmd z7sFxo#nDP64%=2g6uA1^Pe}`chq}U<0g47TYAHn#o-h+QNhqCeVtE0?EenDoi zOfklau|n!`Hxie&FR?0B;yIK3k3(QvysR=7<Q=n5&F><}*}Z z9d`Ej#9!nx)Tm^bXgAPg3od-mZ+T#m%B{`@m>l9Xg=vkYNvz~j+@IU9OQpl724}lI z%`K~1y2*Ve99qT{XK_GP_h2z=zY*~Fltg^iA-6D2m>O8%@QGsB)wNGX?vEQ%2Qq^!dM$w|! zyhPbyE4uH@v^((PI4&W``QQ>o=vms)JW8U$O7a%r(d;VVVIBx+rVOyOJo#T;6l1fZ zAUc2W_1=oGEz?g>tmpr0sqA`R|00Gi-Y&Vp-_j7E;Q5;``GB>B8mEJ6V5c;rosbH_ zn~~q|t3@&7m`W4SN3Ms+txNHGkKk_GB5vCXc@rR$_MQ#mGE0{SU7I>Wh4A|?5q7U3 zL7w1|ydMil?k7zzN~7cxQwoN9dZ=0!VF%jxBPOWisIWj!3?KN5?=sJIZm6G<@JPZn zVvJs5Std7cz-lhVZq9t7n(ADBqqz^+oAunaC2)`T-HM2aQWMCLnV0%{oSxghHZ8efMdF!#<8w=8Fi z$CcvZD2BsU_@YK&uM#?qh>>+2{nE^+MkZlt;Ev!;-nNMM+|u%@4f!)-dLE?iWzcfG z7|LZ%oq7(@o+P29-s(uxm*yqgCjpBF8PEcSZY+7{ETF9Q} zPmiWW$-uhmc|q6*lD&KWStUh*D(GVY3uOUK4tit~1M#bKZ&>W#*bv6rqtO=8U*huNqM84#zZq^>r=Fg192Or;-8RF46edSS`-=~n-#Y%~ct@>n zmnv2j{{caWSz`I}j?qv$!r@B|8wUR+Ow`n}_ww*&l7WAbTP9s*=oXwzV{$Z?eK_*a z?VEi)WIxLm_d>tp)%{Ib1iYqF8jnS}Q!&d-?ELU$u`nm+w*)hVo$}LfV|Vm_Ip8X* zzaV54SXbha(}z};jT$Ri;7ao@Mp{xQgi#?I?0+)q+29}bFw&XofoL7loaV0hcdkK& z<72W-0r>dW$mrsi`pM&yewuo7`SuM8P&9MAsGh{N5x$ ztS*-`ahB&S8wzX%7l+h-%i@34X2VDe+i0o}9AHyjC1dfcHo#iPgK=;3!46O!!>UOY zmzSoMX*&o1E?B;YB+lbz9oS=QMMW9vbsJB5lw6pvLN`@Dd$uO|vRJHssgv1%+QtKF z!eueoF!407!(!+swAD(T+^dhIY4He+T-Iq`db+dhM@~s9vR{1HQI1F5OILG%>ErJy z$m;JhdVgxdKrf`qUTkV;3plquKaSyRPfI8}ZpH|j7~}ku1v|_kB>rO`*-ucw-&ByG z`(fMdrNqcZPuCY~{|JE{KHvtjqp~Bw*_B;RR!O%B&*)(SFHjJ|dvvL!76` z2U73NmIkIN!^+dW2^84m$fl{5;3#3^%lK={**JE%xzTa^)DSbNNReg;8}#bt#g63SiM)xZW-_yDSkjvG7R`a#b^#No&0(>L9lWP2_Bu z58*}L<}9oJ3Nt!fAquar>W=BTxY}1Lmc&t4Mh)5wRHi;0Q+ET_}wRuMMVpd`ol z+}cbwB%$s{V!Rl}c4t|5r)qzqpwKDY^;rrYwcM=Z`dEBx5xsb>_peByu0@%AiK)$$ z#Mp#NAtp~`G_mN%wU_yIn}byL4R2{!8fjS2&+Q|`>yaU{LR{4iPc58un)5j7zCX<< zKDBvav2rr;I%8|;PSx76Toe&LV8m>Rzzt3ngMGGlWMB+prb~8Wqbqm2$y1mHc*t1Y zuXes$i$c(iE4TVc3vaO7G2`!7wG(E0mgG$9DUamO-M5$Y^u%e9a%dRXA5`UV)C<3G;1L&*xo(<4UB!y5U7GXxGK#ktH4XN|&Zv{v3kGt`q#m>Re7%K#NNIWV! z`I%a2BAhBMk4F@0mV~flO+W}2r=znPt_H(|XuP#uXICzmQh6+1LvY+vX>8k5`!=y$ZN%HT|ws zOV+lv?couWmJSQk6$D819|hQ)*~9f&lq9t@UJE*FSzu0&eQG@W2hJaoa8l8!FI{9t z=RBqbMRt*!{eqXYEkBaYNT~+DH}ilcDf@{q68!TG2Za)c2Nr<){YX4^ZEAQ+jiRfV zzi|`A$G=5|m7pGHuQgPMYdhIDYC2Yt9)gVX$w+wwqw3I>uxNRaUaCkIV0~Z>qjNYlyZJ=(1yknR3G~zxA|#vL(Q;woL2wgB97|8PX(NyEa_tFm6K!pH|h+$ z;Mx#F9i3l={M#ZHrlgjOo{^N29{BH99O&c*?-f`%rRz2b%LO5EqGrz_p}rh~0W+!tqySF`vqZ-8Vk9hc_bpiCpJ zD8`slZ!3wXt`YlIT@@*7jT{EsSz8ehpo`eu){L8==e>4(4MoQO#JjS{FK3ezAuF4p z#X%LZf&RhM6fR~6UgfQz$G0G>+moTzKu^yoOD44VTY^I9BK<;?(WkXLTd{`T(A~uA zyP+%0^HjU`rB3>A{+yFn-dA7<&aH5Ef8<0!xdU6%SRwg(=&5(|)+OTgj-&GivrvSr zl|$$tWb?w)-NL19cT;iv9R9pybhEe zf=N0H6HIJ4HX>w+>-uFpT#KEKf$^%sab?i;pWgJ7ZFN33nZ=&gW;b$^O+lx&kQ6hz z(M6y2QA%-KYOa{WhV$nm@SMJCI2=Kvq4`oaAxZk39*Hp3nS-723$0uxQwv2eGZgqy zVZPoS;_qW1A2(wB2@O(dLuZ|A>nTJx|G|6PuHDM*-2mih6XSMe=Nc~L*{yz# z>k`HyoO-`4na@(!Jx}ZN64te+k-b7i$jwO)-9PK-6I{@Rcr&GMhlST+1M;-v!+jfk zBV1>Qb`L0d*QG{9i@9GJ4B^7Zyn0^b1btMy%w8gf`xA#hWU1d|OSVLG6&Pycvyv)6`45$?Nz@g!|pl zzt@p(&Ek|`-^%J(uF-cGGOp*!e1F$Q7aeB z`+Mq@kj8k@B2H!XD37mJhb`as_DmqPpLJJ!O=X(*R{DEBi{J1ze>ict*D1TUZ~NTF z*^XHa{w~%NJ-5|3P{B^$+T1*>@Z{BnY@)x!Y-&yJ&E1Fj&I4%X!r9r&$C)KUc3x<~ ze=kJ22t_Oon37wCkSwNcO%50S^2Ay-eqvb%r4lx zJ;BXEDWSU(;UEjW05zJs`KFgk7#6mU_d0+fUCj}lYyr(V^Lxpr)f4o2U{~Ro~U5B0Cm@&b)dVb)nGqOJy zg`X3$|J``cGti;nVID$7{rP(6QFonD6W-%pWUvO)e|j6y^3O73MPM&_di)W3aQfZ0 z#I3d8W9yLwJuKYU`>pi3H|HrFg7XS?wR*@l!)=;ueb5Hs!;szO^ZV^sH{#8(uMl}K z>5UR?NA$N){kQRM3$t~8zuM<*-wg(J-zVprAYGe$A@sDB2!bexJu{yk6@2FxA@tuP zgkINwV1%fxIQWl_^N#Uauj)~0Z|S9e8$lSo9|Ux%!QDzGG43(fKrnKN-F>jOq6m>%rf#F zu1YjoLakyF~KvlZu9RPsQYI@_A6Z^m-;Hs+NKYg z=nz7!O~D8-Z|)V=I-1{x?IWAbtyduwBl z6IIxa*2dqPHk_D=g|}(45zjZW^1wD6D#Cb(Rw28(X?px)eWZu*I{?wFZE<(E#%01_ zNqyZuzRG(u61E#LmPs%uUjE&=OcF0)Cs7zQS@&8PqgY%8)e&9<7&ZR%u1qEPSD8fJ zw;uAwy>O9<%Dn{<7X7ac#Ob>-C+rv_@Coysba$xe<$ZtWi-Mi~(Aj7q>JsCq+2)q5 zNZd-JpcRXGt0M@J>HNYF5Gb~L+R}S2&kq(qbjc~H+y14q`ZT;?2Ow_4K*!z@25@%@ z`_$*f{p;)uJQ#rV`EY=+EQ$o66S;JSp{J-2ph^An__V2q}BtL&7O38^)CS}*f zOq6OgRJfRC}^0bI=`Dp!W^bShqEPUsv7U6Wo2>e_#`Kr<%;c8y@Fv*%B208 z7RqtZgAY;?KA6sk&Q%|4wN(;C>RE8}LaoJ)QjTWA-i7zw8g8-86qvo{d?3{eeEV!o zA=*-6LqUeiA1S5lP38OkRGLx{U@Ji&c;3zIQ#f*<%HIZk) zgjHlgBQ+bJkZHK&GmIX%%>soWBUIF!v|nhmzlSRk6rHW~tsv zjX2v`<+wDdVCe`N7O(_84yBqkZ{ye&TZpwU=UL|`ORGHn^X4(IefCA?U8*Ij-hO`6K0{q#R07a+Knaj4yX@ zsWaOYNuT}2rkCkCf97tTpz*<=tqBpEw0PJTf{>$?wP?_du}d&=0Ej(p%{OFn zNTZ5HIX!~WZs=^9go_T+bC0lKky zDcObVl?(>eL)um?a#r=BceD;H;a`Kc)hv#2x7p2U&K&6sBIxh9Q@f19*o{lU}M#eo!CQjuz ztL)~W*AY!*MdAsr9KjI;c*hlIk5{0;L z3(!&hm0#a0qGgJTo3w{+c;5b~^x51Ik+aeDOF4Q=+K7%AKMVy<@}$|r;-aacWIk*X zqi~+!XdZs9%}8yvvDyXAPadY-g2?4A$jVHyb^1zy@<_Xp8iQ40_}y!_z5FiyRe%Xo z3=&vU{iSO4B_@e-D&Sl-+#tE;w)JQ|h7$Ae>LmNjKF6Q?#2L6D*w>Qo*K4dt7!(DH zKc>tR(%UO1#^w7Ql*6@X<6?8;6M!E}xt+aLEjMryMAwz)^-D&bj2O^aKK_6DoX4{+ zAcCwd{ejR(8H_R^pRe4nrr_c4C;*TU_c6LSG3%5?Q-Q&6geC}8Q|wj?5TgkXCF&Hj zCe)8)tD*L?Aiazfe;S8K=`Tr!@3+~sRpI6QY|BhxfB~@TXdHWGYiVTG5pZ^7THi{a z)kyQBSmyVj$q9d3N6611a5R<-65&yZ<>{m0X(CD{amo4E6tYd1qlsQtUuxmk+WBG8 z8g??NBIDB}fPBBeqIu_kjj^%a9pk|weqiSxhD`(9*Ph{%=2VBZ1Wd)yfza$JC^pcZRkZ~x`mdTYUDEcciW;*k~ z0vJiSBzCZCC)IZ8W{yw57?*>p73j06QEwg3hZPLQlw~jHCMG&8Tp8!a0)U)bxh+hY zgnAtV^S8nDdp~W8^sH4Px+(eWjKzNY%W7*EiBCgY6iEhNgs^uf-P^s8a8c~;6I5** zc%o^~u|a8)!x5&Yn~xorKd=I80wTudl`^SrLt1Na(ZuxD*2Oc}LZwL#*)$S!m?`0B z?4BGZP798{jl>KMZFF9XzirT4t4bFjY|dp zIBX^1U(>TBm%fHV>KecGy{rXuS}P;ZjW-i@i(IWx7K27RLB^0Ih)_I5Izt#HqhI5& zpDJk&pK|o%l*+TOYHE(L@J> kQCg&?ZR%EZ`5Fa{#2G3|0n$Ww%Ga^~M%5Qw!hz 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 RUCsai002ovPDHLkV1gZ6-0uJY literal 0 HcmV?d00001 diff --git a/spirographs.glade b/spirographs.glade index 08c4e53..56c8a57 100644 --- a/spirographs.glade +++ b/spirographs.glade @@ -1,7 +1,156 @@ - + + + Spirographs is a Python 3 application made with +Glade & GTK for Linux. It exists to help you play +around with hyportrochoids and epitrochoids. +These are the shapes that the classic Spirograph +toys make! + + + False + dialog + + + False + vertical + 2 + + + False + end + + + Close + True + True + True + + + + True + True + 1 + + + + + False + False + 0 + + + + + True + False + vertical + + + True + False + + + True + False + img/example_epi.png + + + False + True + 0 + + + + + True + True + center + 1 + False + 6 + 6 + False + aboutBuffer + False + + + True + True + 1 + + + + + True + False + 6 + 6 + Created by A.M. Rowsell ©2026 +License: Mozilla Public License v2 + center + + + False + True + 2 + + + + + True + True + 0 + + + + + True + False + True + + + True + False + img/small_epitrochoid.png + + + False + True + 0 + + + + + True + False + img/small_hypotrochoid.png + + + False + True + 1 + + + + + True + True + 1 + + + + + True + True + 1 + + + + + 0.5 100 @@ -10,11 +159,27 @@ 5 + + 0.5 + 100 + 0.5 + 0.5 + 5 + + + + 0.5 + 100 + 0.5 + 0.5 + 5 + + False Spirographs center - 800 + 1200 800 @@ -27,33 +192,13 @@ 5 5 10 - - - True - False - img/small_epitrochoid.png - - - 0 - 2 - - - - - True - False - img/small_hypotrochoid.png - - - 1 - 2 - - True True False + True + True natural natural @@ -62,12 +207,12 @@ 0 - 0 + 1 2 - + True False @@ -219,30 +364,130 @@ 2 + + + True + False + 5 + 5 + 5 + 5 + 4 + 0 + + + + + 16π + Automatic (beta) + + + + + 1 + 3 + 2 + + + + + True + False + Theta (θ) + + + 0 + 3 + + 0 - 1 + 2 + 2 + + + + + True + False + True + + + True + False + _File + True + + + True + False + + + True + False + Quit + True + + + + + + + + + + True + False + _View + True + + + True + False + + + True + False + Settings + True + + + + + + + + + True + False + _Help + True + + + True + False + + + True + False + _About Spirograph... + True + + + + + + + + + + 0 + 0 2 - - 0.5 - 100 - 0.5 - 0.5 - 5 - - - - 0.5 - 100 - 0.5 - 0.5 - 5 - - diff --git a/spirographs.py b/spirographs.py index cbe5d20..6bf629d 100644 --- a/spirographs.py +++ b/spirographs.py @@ -25,7 +25,7 @@ class spirographs: self.smallRadius = 5 self.distance = 4 self.rotations = 2 - self.highestTheta = (np.lcm(self.smallRadius, self.bigRadius)/self.bigRadius) * self.rotations * math.pi + self.highestTheta = (np.lcm(self.smallRadius, self.bigRadius)/self.bigRadius) * 2 * math.pi self.stepSize = self.highestTheta / 4096 # update initial slider positions self.bigRadiusAdjustment = builder.get_object('bigRadiusAdjustment') @@ -136,8 +136,10 @@ class spirographs: self.plotFigure = Figure(figsize=(5, 8), dpi=100) self.epiPlot, self.hypoPlot = self.plotFigure.subplots(1, 2) self.epiPlot.set_title(f"Epitrochoid of {self.bigRadius}, {self.smallRadius}, {self.distance}") + self.epiPlot.axis('equal') self.epiPlot.plot(self.epiX, self.epiY) self.hypoPlot.set_title(f"Hypotrochoid of {self.bigRadius}, {self.smallRadius}, {self.distance}") + self.hypoPlot.axis('equal') self.hypoPlot.plot(self.hypoX, self.hypoY) self.canvas = FigureCanvas(self.plotFigure) @@ -149,7 +151,9 @@ class spirographs: self.hypoPlot.clear() self.epiPlot.set_title(f"Epitrochoid of {self.bigRadius}, {self.smallRadius}, {self.distance}") self.hypoPlot.set_title(f"Hypotrochoid of {self.bigRadius}, {self.smallRadius}, {self.distance}") + self.epiPlot.axis('equal') self.epiPlot.plot(self.epiX, self.epiY) + self.hypoPlot.axis('equal') self.hypoPlot.plot(self.hypoX, self.hypoY) self.canvas.draw_idle()