import math
from math import pi
from math import cos
from math import sin
from math import sqrt as mS
import matplotlib
from matplotlib.animation import FuncAnimation as FA
from matplotlib.patches import Circle as mpC
from matplotlib.patches import Polygon as mpL
from matplotlib.patches import Rectangle as mpR
import matplotlib.pyplot as plt
import numpy as np
from random import choice as RC
blue = "#4286F5"
red = "#CD0100"
#Clear axes.
def clearAx(ax):
ax.spines["top"].set_visible(False)
ax.spines["right"].set_visible(False)
ax.spines["bottom"].set_visible(False)
ax.spines["left"].set_visible(False)
ax.set_xticks([])
ax.set_yticks([])
return(ax)
#Bottom and top horizontal strips of sheets.
def sheetHelper(xy, h, c) :
return(mpR(xy,
height = h,
width = 4,
edgecolor = c,
facecolor = c,
lw = 1,
zorder = 1))
#Ridges of sheets.
def ridgeHelper(xy, c, a) :
return(mpC(xy,
radius = 1,
edgecolor = c,
facecolor = c,
alpha = a,
lw = 1,
zorder = 1))
#Annotation Lines
def annoHelper(xy, lw) :
return(mpL(xy = xy,
ec = 'k',
fc = 'k',
fill = False,
ls = ':',
lw = lw,
zorder = 3))
#Output text.
def textHelper(ax, y, c) :
return(ax.text(3.7,
y,
'',
fontsize = 20,
c = c,
ha = 'right',
va = 'center'))
#Aligns text output.
def rHelper(t1, t2) :
return(t1 + str(round(t2, 8))[0:6])
#Math Proof
def plotHelper(b) :
#Setup.
fig = plt.figure(figsize = (9, 6))
ax = fig.add_subplot(xlim = (-cos(b)-0.96, -cos(b)+0.96),
ylim = (-0.64, 0.64))
#Title.
ax.set_title("Space Between Ridges", fontsize = 24)
#Remove axes and ticks.
ax = clearAx(ax)
#Empty Space.
ax.add_patch(mpR((-2*cos(b), -sin(b)),
height = 2*sin(b),
width = 2*cos(b),
edgecolor = 'grey',
facecolor = 'grey',
lw = 1,
zorder = 1))
#Bottom sheet.
bs = sheetHelper((-cos(b)-0.96, -0.64), 0.64-sin(b), blue)
ax.add_patch(bs)
#Top sheet.
ts = sheetHelper((-cos(b)-0.96, sin(b)), 0.64-sin(b), red)
ax.add_patch(ts)
#Left bottom ridge.
lbr = ridgeHelper((-2*cos(b), -sin(b)), blue, 1)
ax.add_patch(lbr)
#Center top ridge.
ctr = ridgeHelper((0, sin(b)), red, 1)
ax.add_patch(ctr)
#Angle
ax.plot([-2*cos(b), 0, 0, -2*cos(b), -2*cos(b), 0],
[-sin(b), -sin(b), sin(b), sin(b), -sin(b), sin(b)],
c = 'k',
ls = ':',
zorder = 3)
text = [("β", (-2*cos(b) + 0.1, -sin(b)), 'left', 'bottom', 0),
("1", (-3*cos(b)/2, -sin(b)/2), 'center', 'bottom', b*180/pi),
("1", (-cos(b)/2, sin(b)/2), 'center', 'bottom', b*180/pi),
("2cosβ", (-cos(b), -sin(b)), 'center', 'bottom', 0),
("2sinβ", (0, 0), 'left', 'center', 270)]
for t in text :
plt.annotate(text = t[0],
xy = t[1],
c = 'k',
size = 20,
ha = t[2],
va = t[3],
rotation= t[4],
zorder = 4)
fig.savefig("2025.01.03 Fiddler.png", bbox_inches = "tight")
#Visual!
def shapeSheets() :
fig = plt.figure(figsize = (12, 4.44))
ax = fig.add_subplot(xlim = (-2, 3.7),
ylim = (-0.95, 0.95))
fig.subplots_adjust(left = 0.02, bottom = 0.02, right = 0.98, top = 0.88)
#Title.
ax.set_title("Space Between Ridges", fontsize = 24)
#Remove axes and ticks.
ax = clearAx(ax)
#Eighteen artists:
#Empty space area, bottom sheet, top sheet,
#5 ridges, white out,
#2 beta annotations,
#3 L annotations,
#4 output texts.
tt = mS(3)/2
#Empty Space Area.
esa = mpR((-1, -mS(3)/2), height = mS(3), width = 1, ec = 'grey', fc = 'grey', zorder = 1)
#Bottom sheet.
bs = sheetHelper((-2, -0.95), 0.95-tt, blue)
#Top sheet.
ts = sheetHelper((-2, tt), 0.95-tt, red)
#Left top ridge.
ltr = ridgeHelper((-2, tt), red, 1)
#Left bottom ridge.
lbr = ridgeHelper((-1, -tt), blue, 1)
#Center top ridge.
ctr = ridgeHelper((0, tt), red, 1)
#Right bottom ridge.
rbr = ridgeHelper((1, -tt), blue, 1)
#Right top ridge.
rtr = ridgeHelper((2, tt), red, 1)
#Right white out.
wo = mpR((2, -0.95), height = 1.9, width = 1.7, ec = 'w', fc = 'w', lw = 1, zorder = 2)
#Beta Annotation.
b1 = ax.text(-0.8, -tt, 'β', fontsize = 16)
ba = annoHelper([(-1, -tt), (0, tt)], 1)
#L Annotation.
l1 = ax.text(0, -tt-0.12, 'L', fontsize = 16, ha = 'center')
ll = annoHelper([(-1, -tt-0.07), (-0.05, -tt-0.07)], 1)
lr = annoHelper([(0.05, -tt-0.07), (1, -tt-0.07)], 1)
#Output Text
beta_out = textHelper(ax, 0.525, 'k')
l_out = textHelper(ax, 0.175, 'k')
area_out = textHelper(ax, -0.175, 'grey')
ratio_out = textHelper(ax, -0.525, 'grey')
def init():
#Empty space area, bottom sheet, top sheet.
ax.add_patch(esa)
ax.add_patch(bs)
ax.add_patch(ts)
#5 ridges.
ax.add_patch(ltr)
ax.add_patch(lbr)
ax.add_patch(ctr)
ax.add_patch(rbr)
ax.add_patch(rtr)
#White out.
ax.add_patch(wo)
#Annotation.
ax.add_patch(ba)
ax.add_patch(ll)
ax.add_patch(lr)
return esa, bs, ts, ltr, lbr, ctr, rbr, rtr, wo, ba, ll, lr
def animate(i) :
#𝜋/3 to 𝜋/6 over 500 frames
b = pi/3 - i*pi/3000
#Empty space area, bottom sheet, top sheet.
esa.set_xy((-2*cos(b), -sin(b)))
esa.set_height(2*sin(b))
esa.set_width(2*cos(b))
bs.set_height(0.95-sin(b))
ts.set_y(sin(b))
ts.set_height(0.95-sin(b))
#5 ridges.
ltr.set_center((-4*cos(b), sin(b)))
lbr.set_center((-2*cos(b), -sin(b)))
ctr.set_center((0, sin(b)))
rbr.set_center((2*cos(b), -sin(b)))
rtr.set_center((4*cos(b), sin(b)))
#Beta Annotation.
b1.set_x(-2*cos(b) + 0.2)
b1.set_y(-sin(b))
ba.set_xy([(-2*cos(b), -sin(b)), (0, sin(b))])
#L1 Annotation.
l1.set_y(-sin(b)-0.12)
ll.set_xy([(-2*cos(b), -sin(b)-0.07), (-0.05, -sin(b)-0.07)])
lr.set_xy([(0.05, -sin(b)-0.07), (2*cos(b), -sin(b)-0.07)])
#Output Text.
beta_out.set_text(rHelper('β : ', b))
l_out.set_text(rHelper('L : ', 4*cos(b)))
area_out.set_text(rHelper('Empty Area : ', 2*sin(2*b) - pi/2))
ratio_out.set_text(rHelper('Empty Ratio : ', 1 - pi/(4*sin(2*b))))
return esa, bs, ts, ltr, lbr, ctr, rbr, rtr, wo, b1, ba, l1, ll, lr, beta_out, l_out, area_out, ratio_out
#Run animation.
anim = FA(fig, animate, init_func = init, frames = 500, interval = 25, blit = True)
#Save animation.
anim.save('2025.01.03 Fiddler.mp4');
plotHelper(pi/5)
shapeSheets()
def sheetLattice(option) :
fig = plt.figure(figsize = (9, 9))
ax = fig.add_subplot(xlim = (-3, 3),
ylim = (-3, 3))
clearAx(ax)
if option == 4 :
for x in [-2, 0, 2] :
for y in [-2, 0, 2] :
ax.add_patch(ridgeHelper((x, y), red, 0.9))
for x in [-3, -1, 1, 3] :
for y in [-3, -1, 1, 3] :
ax.add_patch(ridgeHelper((x, y), blue, 0.9))
smallest = [(0, 0), (1, 0), (1, 1), (0, 1), (0, 0)]
elif option == 6 :
for x in [-2, 0, 2] :
for y in [-2*mS(3), 0, 2*mS(3)] :
ax.add_patch(ridgeHelper((x, y), RC([blue, red]), 0.9))
for x in [-3, -1, 1, 3] :
for y in [-mS(3), mS(3)] :
ax.add_patch(ridgeHelper((x, y), RC([blue, red]), 0.9))
smallest = [(0, 0), (2, 0), (1, mS(3)), (0, 0)]
ax.add_patch(annoHelper(smallest, 3))
fig.savefig("2025.01.03 EC" + str(option) + ".png", bbox_inches = "tight")
def fiveStack() :
k = 5/18
x1 = 5/2*k
x2 = 1/2*k
y1 = mS(671)/36+5/72
y2 = 1+y1
fig = plt.figure(figsize = (9*x1/2, 9))
ax = fig.add_subplot(xlim = (-x1, x1),
ylim = (-2, 2))
clearAx(ax)
#Given a shape, transform it for graph.
def shearTransform(xy) :
m = 3/2
n = -1/2
transform = []
for p in xy :
transform.append((p[0]+m*p[1], n*p[0] + (m*n+1)*p[1]))
return(transform)
#Create a list of quarter circle points centered at xy, radius r, start angle, and end angle.
#Shear it, then shift down.
def createQuarter(xy, r, start, end, shift, option) :
step = (end - start) / 50
qc = []
qc.append(xy)
for i in range(51) :
qc.append((xy[0] + r*cos(start + i*step), xy[1] + r*sin(start + i*step)))
qc.append(xy)
qcshear = shearTransform(qc)
qcshift = []
for p in qcshear :
qcshift.append((p[0], p[1]+shift))
if option == 2:
cx = qcshift[0][0]
k = cx/abs(cx)
cy = (y1-5/72)*k
start = 0
end = cx/3
step = (end-start)/26
for j in range(26) :
x = start+j*step
y = -k*mS(1 - (x-cx)**2) + cy
qcshift[j+26] = (x, y)
for i in [0, 1, 25, 26, 27, 51, 52] :
print(qcshift[i])
print()
return(qcshift)
#Start with a center square and shear it.
square = [(-k, -k), (-k, k), (k, k), (k, -k), (-k, -k)]
center = shearTransform(square)
#Stack 5 layers.
for l in [-y2, -y1, 0, y1, y2] :
new_plane = []
for p in center :
#New layer 1 unit above.
new_plane.append((p[0], p[1]+l))
ax.add_patch(mpL(xy = new_plane, ec = 'k', fill = False, ls = ':', lw = 1, zorder = 2))
#Bottom Sheet.
ax.add_patch(ridgeHelper((-x1, -y1+5/72), red, 0.5))
ax.add_patch(mpL(createQuarter((-k, -k), 2*k, 0, pi/2, -y1, 1),
ls = ":",
ec = 'k',
fc = 'red',
alpha = 0.75,
lw = 2,
zorder = 3))
ax.add_patch(mpL(createQuarter((-k, -k), k*mS(2), 0, pi/2, 0, 2),
ls = ":",
ec = 'k',
fc = 'red',
alpha = 0.75,
lw = 2,
zorder = 3))
#Top Sheet.
ax.add_patch(ridgeHelper((x1, y1-5/72), blue, 0.5))
ax.add_patch(mpL(createQuarter((k, k), k*mS(2), pi, 3*pi/2, 0, 2),
ls = ":",
ec = 'k',
fc = 'blue',
alpha = 0.75,
lw = 2,
zorder = 3))
ax.add_patch(mpL(createQuarter((k, k), 2*k, pi, 3*pi/2, y1, 1),
ls = ":",
ec = 'k',
fc = 'blue',
alpha = 0.75,
lw = 2,
zorder = 3))
#Annotation.
ax.add_patch(mpL([(-x1, -y1+5/72), (x1, y1-5/72), (0, y1), (0, -y1), (-x1, -y1+5/72)], ls = ":", edgecolor ='k', lw = 1, fill = False, zorder = 4))
text = [("1", ((-x1-x2)/2, 13/8), 20, 'center', 'bottom', 0),
("1", ((-x1+x2)/2, 8/4), 20, 'center', 'top', 0),
("1", (-x1/2, -9/20), 20, 'center', 'bottom', 45),
("1", (x1/2, 9/20), 20, 'center', 'top', 45),
("1/√2", (-x1/2, -y1+0.035), 16, 'center', 'center', 0),
("1/√2", (0, -y1/2), 16, 'center', 'center', 90),
("1/√2", (-0.03, y1/2), 16, 'center', 'center', -90),
("1/√2", (x1/2, y1-0.045), 16, 'center', 'center', 0)]
for t in text :
plt.annotate(text = t[0],
xy = t[1],
c = 'k',
size = t[2],
ha = t[3],
va = t[4],
rotation= t[5],
zorder = 4)
fig.savefig("2025.01.03 EC4.2.png", bbox_inches = "tight")
sheetLattice(6)
sheetLattice(4)
fiveStack()
(-0.6944444444444444, -0.719546324832701) (-0.1388888888888889, -0.9973241026104788) (0.2809940479524692, -0.8269616232929974) (0.2876483072035383, -0.8177555999974991) (0.2933333594782255, -0.8084526560043629) (0.13888888888888878, -0.580657435943812) (-0.6944444444444444, -0.719546324832701) (-0.6944444444444444, 0.06944444444444445) (-0.30160734378525134, -0.12697410588515212) (-0.004705271840204084, -0.006509641500008101) (0.0, 1.1102230246251565e-16) (-0.008903133903133903, 0.008487404840109125) (-0.22257834757834757, 0.16212390072125027) (-0.6944444444444444, 0.06944444444444445) (0.6944444444444444, -0.06944444444444445) (0.3016073437852514, 0.12697410588515212) (0.004705271840204084, 0.006509641500008101) (0.0, -1.1102230246251565e-16) (0.008903133903133903, -0.008487404840109125) (0.22257834757834757, -0.16212390072125027) (0.6944444444444444, -0.06944444444444445) (0.6944444444444444, 0.719546324832701) (0.13888888888888895, 0.9973241026104788) (-0.2809940479524692, 0.8269616232929974) (-0.2876483072035383, 0.8177555999974992) (-0.2933333594782256, 0.808452656004363) (-0.138888888888889, 0.5806574359438121) (0.6944444444444444, 0.719546324832701)