"""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)