harmonograph/harmonograph.py
2023-02-14 16:19:08 +01:00

116 lines
3.1 KiB
Python

"""
https://en.wikipedia.org/wiki/Ellipse#General_parametric_form
"""
import numpy as np
import matplotlib.pyplot as plt
class Pendel():
def __init__(self, a: float, b: float, omega: float, phi: float, delta: float, tau: float, sub: int = 0):
self.a = a
self.b = b
self.omega = omega
self.phi = phi
self.delta = delta
self.tau = tau
self._sub = sub
def point(self, t: float):
x = (self.a * np.cos(t*self.omega + self.delta)*np.cos(t*self.phi)
- self.b*np.sin(t*self.omega + self.delta)*np.sin(t*self.phi))
y = (self.a * np.cos(t*self.omega + self.delta)*np.sin(t*self.phi)
+ self.b*np.sin(t*self.omega + self.delta)*np.cos(t*self.phi))
return np.exp(-t*self.tau)*np.array([x, y])
def __repr__(self):
SUB = str.maketrans("0123456789", "₀₁₂₃₄₅₆₇₈₉")
sub = f"{self._sub}".translate(SUB)
return f"A{sub}={self.a}, B{sub}={self.b}, ω{sub}={self.omega}, Φ{sub}={self.phi}, δ{sub}={self.delta}, τ{sub}={self.tau}"
def update(self, **kwargs):
for key, val in kwargs.items():
if hasattr(self, key):
setattr(self, key, val)
else:
raise ValueError(f'{self.__name__} object has no attribute {key}')
class DoppelPendel():
def __init__(self, kwargs1, kwargs2):
self.stift = Pendel(**kwargs1, sub=1)
self.tisch = Pendel(**kwargs2, sub=2)
def point(self, t):
return self.stift.point(t)+self.tisch.point(t)
def update_stift(self, **kwargs):
self.stift.update(**kwargs)
def update_tisch(self, **kwargs):
self.tisch.update(**kwargs)
def __repr__(self):
return str(self.stift) + "\n" + str(self.tisch)
class Harmonograph(DoppelPendel):
def __init__(self, kwargs1, kwargs2, t_init, n=10000):
super().__init__(kwargs1, kwargs2)
self.n = n
self.t = t_init
self.fig, self.ax = plt.subplots()
self.ax.set_xlim(-2, 2)
self.ax.set_ylim(-2, 2)
self.ax.set_aspect('equal')
self.ax.axis('off')
self.init_harmonograph()
# self.label = self.ax.text(0, -2, str(self),
# horizontalalignment='center',
# verticalalignment='bottom',)
def init_harmonograph(self):
t = np.linspace(0, self.t, self.n)
self.ax.plot(*self.point(t), 'k', lw=0.5)
if __name__ == "__main__":
# kw1 = dict(
# a=1,
# b=1,
# omega=np.pi/60,
# phi=np.pi/180,
# delta=np.pi/2,
# tau=0
# )
# kw2 = dict(
# a=0.2,
# b=1,
# omega=0.1204277183860873,
# phi=np.pi/90,
# delta=0,
# tau=0
# )
kw1 = dict(
a=1,
b=0.3,
omega=0.05,
phi=2.5e-4,
delta=0,
tau=5e-7
)
kw2 = dict(
a=0.5,
b=0,
omega=1/10,
phi=5e-5,
delta=0,
tau=5e-5
)
p1 = Harmonograph(kw1, kw2, 7000)
plt.show()