spirographs/spirographs.py
A.M. Rowsell 3e96363771
Embedded the matplotlib in a GtkViewport.
Still trying to work out the kinks, as only one plot is showing,
and it's not updating with the sliders. I'll get there sooner
or later. Also updated the gitignore, and added images showing
the parametric equations used to calculate the graphs. Neat!
2021-06-27 15:40:30 -04:00

92 lines
3.6 KiB
Python

# -*- coding: utf-8 -*-
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
# gtk imports
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, Gdk, GObject, GLib
# math/plot imports
from matplotlib.backends.backend_gtk3agg import (
FigureCanvasGTK3Agg as FigureCanvas)
from matplotlib.figure import Figure
import numpy as np
import math
import sys
class spirographs:
def __init__(self):
self.bigRadius = 12
self.smallRadius = 5
self.distance = 4
self.highestTheta = (np.lcm(self.smallRadius, self.bigRadius)/self.bigRadius) * 2 * math.pi
self.stepSize = self.highestTheta / 4096
self.recalcPoints()
self.showPlot()
def calcEpiX(self, theta):
return ((self.bigRadius + self.smallRadius) * math.cos(theta)) - (self.distance * math.cos(((self.bigRadius + self.smallRadius)/(self.smallRadius))*theta))
def calcEpiY(self, theta):
return ((self.bigRadius + self.smallRadius) * math.sin(theta)) - (self.distance * math.sin(((self.bigRadius + self.smallRadius)/(self.smallRadius))*theta))
def calcHypoX(self, theta):
return ((self.bigRadius - self.smallRadius) * math.cos(theta)) + (self.distance * math.cos(((self.bigRadius - self.smallRadius)/(self.smallRadius))*theta))
def calcHypoY(self, theta):
return ((self.bigRadius - self.smallRadius) * math.sin(theta)) - (self.distance * math.sin(((self.bigRadius - self.smallRadius)/(self.smallRadius))*theta))
def onDestroy(self, widget):
Gtk.main_quit()
return
def bigRadiusAdjustment_value_changed_cb(self, widget):
self.bigRadius = widget.get_value()
self.recalcPoints()
self.updatePlot()
def smallRadiusAdjustment_value_changed_cb(self, widget):
self.smallRadius = widget.get_value()
self.recalcPoints()
self.updatePlot()
def distanceAdjustment_value_changed_cb(self, widget):
self.distance = widget.get_value()
self.recalcPoints()
self.updatePlot()
def recalcPoints(self):
self.epiX = np.array([self.calcEpiX(i) for i in np.arange(0, self.highestTheta, self.stepSize)])
self.epiY = np.array([self.calcEpiY(i) for i in np.arange(0, self.highestTheta, self.stepSize)])
self.hypoX = np.array([self.calcHypoX(i) for i in np.arange(0, self.highestTheta, self.stepSize)])
self.hypoY = np.array([self.calcHypoY(i) for i in np.arange(0, self.highestTheta, self.stepSize)])
def showPlot(self):
viewport = builder.get_object('plotViewport')
self.plotFigure = Figure(figsize=(5, 4), dpi=100)
self.subPlot1 = self.plotFigure.add_subplot()
#self.subPlot1.title = f"Epichondroid of {self.bigRadius}, {self.smallRadius}, {self.distance}"
self.subPlot1.plot(self.epiX, self.epiY)
self.subPlot2 = self.plotFigure.add_subplot()
#self.subPlot2.title = f"Hypochondroid of {self.bigRadius}, {self.smallRadius}, {self.distance}"
self.subPlot2.plot(self.hypoX, self.hypoY)
self.canvas = FigureCanvas(self.plotFigure)
self.canvas.set_size_request(800, 600)
viewport.add(self.canvas)
def updatePlot(self):
self.subPlot1.plot(self.epiX, self.epiY)
self.subPlot2.plot(self.hypoX, self.hypoY)
builder = Gtk.Builder()
builder.add_from_file("spirographs.glade")
sp = spirographs()
builder.connect_signals(sp)
window = builder.get_object("spWindow")
window.show_all()
Gtk.main()