import math
from math import acos as cosI
from math import asin as sinI
from math import cos as cos
from math import sin as sin
from math import pi as pi
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 mpP
from matplotlib.patches import Rectangle as mpR
import matplotlib.pyplot as plt
import numpy as np
#Colors
f = ['#EEEEEE', #light grey
'#FFFFFF', #white
'#535353', #border grey
'#4286F5'] #blue you
a = (mS(3) - 1) / 2
b = (1 - a) / 2
c = 5/4 + a / 2
d = 5/4 - a / 2
#Corridors.
def rect(c, h, w, fc, z):
return(mpR(c,
height = h,
width = w,
edgecolor = None,
facecolor = fc,
zorder = z))
def wall(ax, x, y, ls, z):
return(ax.plot(x, y, ls = ls, lw = 2, color = f[2], zorder = z))
#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)
def spyB() :
fig = plt.figure(figsize = (12, 8))
ax = fig.add_subplot(xlim = (-1.01, 2.02),
ylim = (-0.01, 2.02))
ax = clearAx(ax)
ax.add_patch(rect((-1, 0),
3,
2,
f[0],
1))
ax.add_patch(rect((-1, 1),
2,
1,
f[1],
2))
wall(ax, (-1, 1), (0, 0), '-', 3)
wall(ax, (-1, 1), (1, 1), '-', 3)
wall(ax, (0, 0), (0, 2.5), '-', 3)
wall(ax, (1, 1), (0, 2.5), '-', 3)
ax.plot(0.5, 2, ms = 20, marker = 'o', c = f[3], zorder = 5)
text = [("(0, 0)", (0, 0), 'right', 'bottom'),
("(0, 1)", (0, 1), 'right', 'bottom'),
("(a, 0)", (a, 0), 'right', 'bottom'),
("(1/2+a/2,", (0.6, b+0.06), 'right', 'center'),
(" 1/2-a/2)", (0.6, b-0.06), 'right', 'center'),
("(1, 1-a)", (1, 1-a), 'left', 'center'),
("(1/2, 2)", (0.5, 2), 'right', 'top'),
("(5/4 + a/2,", (5/4 + a/2, 5/4 - a/2), 'left', 'center'),
(" 5/4 - a/2)", (5/4 + a/2, 0.95), 'left', 'center')]
#Mirror
ax.add_patch(mpP([(a, 0), (1, 1-a), (1, 0), (a, 0)], ec = f[2], fc = f[3], lw = 2))
#Mirror Extension.
wall(ax, (1, c), (1-a, d), ':', 3)
#From top left corner
wall(ax, (0, 1-b), (1, b), ':', 3)
wall(ax, (0, 1), (1, 1-a), ':', 3)
#From You.
wall(ax, (0.5, 1), (2, 1-a), ':', 3)
wall(ax, (0.5, c), (2, d), ':', 3)
for t in text :
plt.annotate(text = t[0],
xy = t[1],
c = 'k',
size = 20,
ha = t[2],
va = t[3],
zorder = 3)
fig.savefig("2024.07.08fiddler.png", bbox_inches = 'tight')
spyB()
def getScans():
def dist(p1, p2) :
d = mS((p1[0]-p2[0])**2 + (p1[1]-p2[1])**2)
return(d)
def theta(x_o, y_o) :
t = cosI(dist((5/4 + a/2, 5/4 - a/2), (x_o, y_o)) / dist((1/2, 2), (x_o, y_o)))
return(t)
#Generate three tuples and a theta from you-mirror-corridor.
#Angle from you to corridor is 𝜋-2θ
scans = []
for i in range(1000, 388, -1):
#Point of reflection, will be origin for each iteration.
x_o = i/1000
y_o = x_o - a
x_you = 1/2 - x_o
y_you = 2 - y_o
t = theta(x_o, y_o)
tu = pi - 2*t
#Rotate you about origin, multiply to extend sight, add shift back.
x_c = 2*x_you*cos(tu) - 2*y_you*sin(tu) + x_o
y_c = 2*y_you*cos(tu) + 2*x_you*sin(tu) + y_o
scans.append([(1/2, 2), (x_o, y_o), (x_c, y_c), t])
return(scans)
scans = getScans()
matplotlib.rc_file_defaults()
fig = plt.figure(figsize = (12, 8))
ax = fig.add_subplot(xlim = (-1.01, 2.02),
ylim = (0, 2.03))
ax.set_title("Minimum 45° Mirror to Spy", fontsize = 24)
#Remove axes and ticks.
ax = clearAx(ax)
font = {'size' : 24}
#Twelve artists:
#Piece 1, Piece 2, Piece 3,
#Slice 1, Slice 2, Slice 3,
#z1, z2, z3.
#Center Shape,
#z
#(x, y)
#Setup - corridors, whitespace, mirror, you
c = rect((-1.01, 0), 3, 2, f[0], 1)
wh = rect((-1.01, 1), 2, 1, f[1], 3)
m = mpP([(a, 0), (1, 1-a), (1, 0), (a, 0)], ec = f[2], fc = f[3], lw = 2, zorder = 2)
y = mpC(xy = (0.5, 2), radius = 0.065, fc = f[3], zorder = 3)
#Sight, Reflection
s = mpP([(1/2, 2), (1, (1-a)/2)], ec = f[3], fc = None, lw = 2, zorder = 2)
r = mpP([(1, (1-a)/2), (0,1)], ec = f[3], fc = None, lw = 2, zorder = 2)
#Walls
w0 = mpP([(-1.01, 0), (1, 0)], ec = f[2], fc = None, lw = 3, zorder = 4)
w1 = mpP([(-1.01, 1), (1, 1)], ec = f[2], fc = None, lw = 3, zorder = 4)
w2 = mpP([(0, 0), (0, 2.5)], ec = f[2], fc = None, lw = 3, zorder = 4)
w3 = mpP([(1, 0), (1, 2.5)], ec = f[2], fc = None, lw = 3, zorder = 4)
def init():
"""Initialize seven artists."""
ax.add_patch(c)
ax.add_patch(wh)
ax.add_patch(m)
ax.add_patch(y)
ax.add_patch(w0)
ax.add_patch(w1)
ax.add_patch(w2)
ax.add_patch(w3)
ax.add_patch(s)
ax.add_patch(r)
return c, wh, m, y, w0, w1, w2, w3, s, r
def animate(i):
#Get current scan.
scan = scans[i]
#Update sight and reflection
s.set_xy(scan[0:2])
r.set_xy(scan[1:3])
return c, wh, m, y, w0, w1, w2, w3, s, r
#Run animation.
anim = FA(fig, animate, init_func = init, frames = 612, interval = 10, blit = True)
#Save animation.
anim.save('2024.07.05fiddler.mp4');