codexscrew-thread-pitch-and-lead.py
screw-thread-pitch-and-lead.py
"""Illustrative unwrapped thread geometry; save PNG in the current directory.
Tested with Python 3.14.4, NumPy 2.3.5 and Matplotlib 3.10.7.
Curves are ideal reference helices, not manufactured thread profiles.
"""
from pathlib import Path
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
import numpy as np
turn = np.linspace(0, 1, 301)
pitch = 2.0 # millimetres, same in both examples
colors = ["#1766a0", "#ba5518", "#237b43"]
plt.rcParams.update({"font.size": 10, "figure.facecolor": "white"})
fig, axes = plt.subplots(1, 2, figsize=(8.6, 4.8), dpi=100, sharey=True)
fig.subplots_adjust(left=0.08, right=0.985, top=0.79, bottom=0.20, wspace=0.20)
fig.suptitle("Same pitch, different advance per turn", fontsize=15, y=0.96)
for ax, starts in zip(axes, [1, 3], strict=True):
lead = starts * pitch
for offset in range(-4, 6):
ax.plot(turn, lead * turn + offset * pitch, color="#d4d4d4", lw=1.1)
for start in range(starts):
curve = lead * turn + start * pitch
assert np.isclose(curve[-1] - curve[0], lead)
ax.plot(turn, curve, color=colors[start], lw=2.3)
ax.scatter([0, 1], [curve[0], curve[-1]], color=colors[start], s=20, zorder=4)
ax.annotate("", xy=(-0.045, 2), xytext=(-0.045, 0),
arrowprops={"arrowstyle": "<->", "color": "#333333"})
ax.text(0.025, 1, "p = 2 mm", fontsize=9, va="center",
bbox={"facecolor": "white", "edgecolor": "none", "alpha": 0.9})
ax.annotate("", xy=(1.065, lead), xytext=(1.065, 0),
arrowprops={"arrowstyle": "<->", "color": colors[0]})
ax.text(1.095, lead / 2, f"L = {lead:.0f} mm", rotation=90, va="center", fontsize=9,
color=colors[0])
ax.set(xlim=(-0.09, 1.22), ylim=(-0.5, 10.7), xlabel="Angular position / one turn")
ax.set_title("One start" if starts == 1 else "Three starts", fontsize=12)
ax.set_xticks([0, 0.5, 1])
ax.set_yticks([0, 2, 4, 6, 8, 10])
ax.grid(alpha=0.15)
ax.spines[["top", "right"]].set_visible(False)
axes[0].set_ylabel("Axial position (mm)")
fig.text(0.5, 0.085, "Unwrapped cylindrical surfaces: colored lines track one turn of each start.",
ha="center", fontsize=10)
fig.text(0.5, 0.04, "Gray continuations repeat; ridge shapes and thread depth are not shown.",
ha="center", fontsize=10)
fig.savefig(Path("screw-thread-pitch-and-lead.png"), facecolor="white")
plt.close(fig)