"""Original analytic Möbius-band model; output the matching PNG to the CWD.""" from pathlib import Path import matplotlib matplotlib.use("Agg") import matplotlib.pyplot as plt import numpy as np plt.rcParams.update({"font.size": 12, "figure.facecolor": "white"}) R, a = 2., .55 def surface(theta, w): return ((R + w * np.cos(theta / 2)) * np.cos(theta), (R + w * np.cos(theta / 2)) * np.sin(theta), w * np.sin(theta / 2)) def normal(theta): return (np.cos(theta) * np.sin(theta / 2), np.sin(theta) * np.sin(theta / 2), -np.cos(theta / 2)) fig = plt.figure(figsize=(10.6, 5.3), layout="constrained") left = fig.add_subplot(1, 2, 1, projection="3d") right = fig.add_subplot(1, 2, 2) t, w = np.meshgrid(np.linspace(0, 2 * np.pi, 160), np.linspace(-a, a, 22)) left.plot_surface(*surface(t, w), color="#d7e4ee", alpha=.65, linewidth=0, antialiased=True, shade=True) boundary = np.linspace(0, 4 * np.pi, 801) left.plot(*surface(boundary, a), color="#087e8b", lw=2.4, label="Single boundary") core = np.linspace(0, 2 * np.pi, 401) left.plot(*surface(core, 0), color="#303030", lw=1.6, ls=":", label="Core circle") for theta in np.linspace(.45, 5.75, 7): left.quiver(*surface(theta, 0), *normal(theta), length=.65, color="#747474", linewidth=1.4, arrow_length_ratio=.23) for theta, color, label in [(0., "#c45b12", r"$n(0)$"), (2 * np.pi, "#2855a6", r"$n(2\pi)$")]: left.quiver(*surface(theta, 0), *normal(theta), length=1.15, color=color, linewidth=3, arrow_length_ratio=.19) x, y, z = surface(theta, 0) nx, ny, nz = normal(theta) left.text(x + 1.25 * nx, y + 1.25 * ny, z + 1.25 * nz, label, color=color, fontsize=13) left.set(xlim=(-2.7, 2.7), ylim=(-2.7, 2.7), zlim=(-1.45, 1.45), title="Opposite normals at the same point") left.set_box_aspect((1, 1, .55), zoom=1.35) left.view_init(elev=26, azim=-57) left.set_axis_off() left.legend(loc="lower left", frameon=False, fontsize=11) theta = np.linspace(0, 4 * np.pi, 601) right.plot(theta, np.cos(theta / 2), color="#333333", lw=2.6) right.axhline(0, color="#aaaaaa", lw=.8) for x, y, color in [(0, 1, "#c45b12"), (2 * np.pi, -1, "#2855a6"), (4 * np.pi, 1, "#087e8b")]: right.scatter([x], [y], color=color, s=65, zorder=3) right.set(xticks=[0, np.pi, 2*np.pi, 3*np.pi, 4*np.pi], xticklabels=["0", r"$\pi$", r"$2\pi$", r"$3\pi$", r"$4\pi$"], xlim=(-.25, 4*np.pi + .25), ylim=(-1.28, 1.28), xlabel=r"Travel parameter $\theta$", ylabel=r"Ambient comparison $n(\theta)\cdot n(0)$", title=r"$n(\theta)\cdot n(0)=\cos(\theta/2)$") right.text(2*np.pi, -.93, "One circuit:\nreversed at starting point", ha="center", va="bottom", fontsize=11, color="#2855a6") right.text(4*np.pi-.18, .91, "Two circuits:\noriginal direction", ha="right", va="top", fontsize=11, color="#087e8b") right.grid(alpha=.18) fig.suptitle("Möbius band: normal reversal after one circuit", fontsize=17) fig.supxlabel("Mathematical model, not measured data; the graph is not parallel transport", fontsize=11) fig.savefig(Path(__file__).with_suffix(".png").name, dpi=120, facecolor="white") plt.close(fig)