update: start to bring up to 2026

This commit is contained in:
A.M. Rowsell 2026-07-18 03:19:13 -04:00
commit 2f1a83a1a8
Signed by: amr
GPG key ID: E0879EDBDB0CA7B1
3 changed files with 293 additions and 44 deletions

BIN
img/example_epi.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

View file

@ -1,7 +1,156 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.38.2 -->
<!-- Generated with glade 3.40.0 -->
<interface>
<requires lib="gtk+" version="3.24"/>
<object class="GtkTextBuffer" id="aboutBuffer">
<property name="text" translatable="yes">Spirographs is a Python 3 application made with
Glade &amp; GTK for Linux. It exists to help you play
around with hyportrochoids and epitrochoids.
These are the shapes that the classic Spirograph
toys make!</property>
</object>
<object class="GtkDialog" id="aboutDialog">
<property name="can-focus">False</property>
<property name="type-hint">dialog</property>
<child internal-child="vbox">
<object class="GtkBox" id="aboutTopBox">
<property name="can-focus">False</property>
<property name="orientation">vertical</property>
<property name="spacing">2</property>
<child internal-child="action_area">
<object class="GtkButtonBox" id="aboutButtonBox">
<property name="can-focus">False</property>
<property name="layout-style">end</property>
<child>
<object class="GtkButton" id="aboutDialogExitButton">
<property name="label" translatable="yes">Close</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
<signal name="clicked" handler="gtk_widget_hide" object="aboutDialog" swapped="no"/>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkBox" id="contentsParentBox">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkBox" id="topContentsBox">
<property name="visible">True</property>
<property name="can-focus">False</property>
<child>
<object class="GtkImage">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="pixbuf">img/example_epi.png</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkTextView" id="aboutTextField">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="valign">center</property>
<property name="pixels-below-lines">1</property>
<property name="editable">False</property>
<property name="left-margin">6</property>
<property name="right-margin">6</property>
<property name="cursor-visible">False</property>
<property name="buffer">aboutBuffer</property>
<property name="accepts-tab">False</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="aboutAuthorLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="margin-start">6</property>
<property name="margin-end">6</property>
<property name="label" translatable="yes">Created by A.M. Rowsell ©2026
License: Mozilla Public License v2</property>
<property name="justify">center</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkBox" id="bottomContentsBox">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="homogeneous">True</property>
<child>
<object class="GtkImage" id="epichondroidFormulaImage">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="pixbuf">img/small_epitrochoid.png</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkImage" id="hypotrochoidFormulaImage">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="pixbuf">img/small_hypotrochoid.png</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
</object>
<object class="GtkAdjustment" id="bigRadiusAdjustment">
<property name="lower">0.5</property>
<property name="upper">100</property>
@ -10,11 +159,27 @@
<property name="page-increment">5</property>
<signal name="value-changed" handler="bigRadiusAdjustment_value_changed_cb" swapped="no"/>
</object>
<object class="GtkAdjustment" id="distanceAdjustment">
<property name="lower">0.5</property>
<property name="upper">100</property>
<property name="value">0.5</property>
<property name="step-increment">0.5</property>
<property name="page-increment">5</property>
<signal name="value-changed" handler="distanceAdjustment_value_changed_cb" swapped="no"/>
</object>
<object class="GtkAdjustment" id="smallRadiusAdjustment">
<property name="lower">0.5</property>
<property name="upper">100</property>
<property name="value">0.5</property>
<property name="step-increment">0.5</property>
<property name="page-increment">5</property>
<signal name="value-changed" handler="smallRadiusAdjustment_value_changed_cb" swapped="no"/>
</object>
<object class="GtkWindow" id="spWindow">
<property name="can-focus">False</property>
<property name="title" translatable="yes">Spirographs</property>
<property name="window-position">center</property>
<property name="default-width">800</property>
<property name="default-width">1200</property>
<property name="default-height">800</property>
<signal name="destroy" handler="onDestroy" swapped="no"/>
<child>
@ -27,33 +192,13 @@
<property name="margin-top">5</property>
<property name="margin-bottom">5</property>
<property name="row-spacing">10</property>
<child>
<object class="GtkImage" id="epichondroidFormulaImage">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="pixbuf">img/small_epitrochoid.png</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">2</property>
</packing>
</child>
<child>
<object class="GtkImage" id="hypotrochoidFormulaImage">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="pixbuf">img/small_hypotrochoid.png</property>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">2</property>
</packing>
</child>
<child>
<object class="GtkViewport" id="plotViewport">
<property name="visible">True</property>
<property name="app-paintable">True</property>
<property name="can-focus">False</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<property name="hscroll-policy">natural</property>
<property name="vscroll-policy">natural</property>
<child>
@ -62,12 +207,12 @@
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">0</property>
<property name="top-attach">1</property>
<property name="width">2</property>
</packing>
</child>
<child>
<!-- n-columns=3 n-rows=3 -->
<!-- n-columns=3 n-rows=4 -->
<object class="GtkGrid" id="scaleGrid">
<property name="visible">True</property>
<property name="can-focus">False</property>
@ -219,30 +364,130 @@
<property name="top-attach">2</property>
</packing>
</child>
<child>
<object class="GtkComboBoxText" id="thetaMultiplier">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="margin-start">5</property>
<property name="margin-end">5</property>
<property name="margin-top">5</property>
<property name="margin-bottom">5</property>
<property name="active">4</property>
<property name="active-id">0</property>
<items>
<item id="0" translatable="yes">2π</item>
<item id="1" translatable="yes">4π</item>
<item id="2" translatable="yes">8π</item>
<item id="3" translatable="yes">16π</item>
<item id="4" translatable="yes">Automatic (beta)</item>
</items>
<signal name="changed" handler="thetaMultiplier_changed_cb" swapped="no"/>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">3</property>
<property name="width">2</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="thetaMultiplierLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">Theta (θ)</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">1</property>
<property name="top-attach">3</property>
</packing>
</child>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">2</property>
<property name="width">2</property>
</packing>
</child>
<child>
<object class="GtkMenuBar" id="spiroMenuBar">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="hexpand">True</property>
<child>
<object class="GtkMenuItem" id="fileMenu">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">_File</property>
<property name="use-underline">True</property>
<child type="submenu">
<object class="GtkMenu">
<property name="visible">True</property>
<property name="can-focus">False</property>
<child>
<object class="GtkMenuItem" id="quitMenuItem">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">Quit</property>
<property name="use-underline">True</property>
<signal name="activate-item" handler="gtk_main_quit" swapped="no"/>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkMenuItem" id="viewMenu">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">_View</property>
<property name="use-underline">True</property>
<child type="submenu">
<object class="GtkMenu">
<property name="visible">True</property>
<property name="can-focus">False</property>
<child>
<object class="GtkMenuItem" id="viewMenuSettingsItem">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">Settings</property>
<property name="use-underline">True</property>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkMenuItem" id="helpMenu">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">_Help</property>
<property name="use-underline">True</property>
<child type="submenu">
<object class="GtkMenu">
<property name="visible">True</property>
<property name="can-focus">False</property>
<child>
<object class="GtkMenuItem" id="aboutMenuItem">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">_About Spirograph...</property>
<property name="use-underline">True</property>
<signal name="activate" handler="gtk_widget_show" object="aboutDialog" swapped="no"/>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">0</property>
<property name="width">2</property>
</packing>
</child>
</object>
</child>
</object>
<object class="GtkAdjustment" id="distanceAdjustment">
<property name="lower">0.5</property>
<property name="upper">100</property>
<property name="value">0.5</property>
<property name="step-increment">0.5</property>
<property name="page-increment">5</property>
<signal name="value-changed" handler="distanceAdjustment_value_changed_cb" swapped="no"/>
</object>
<object class="GtkAdjustment" id="smallRadiusAdjustment">
<property name="lower">0.5</property>
<property name="upper">100</property>
<property name="value">0.5</property>
<property name="step-increment">0.5</property>
<property name="page-increment">5</property>
<signal name="value-changed" handler="smallRadiusAdjustment_value_changed_cb" swapped="no"/>
</object>
</interface>

View file

@ -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()