"""Generate assets/fwd_diagram.png — schematic of the FWD test for the app.""" import numpy as np import matplotlib matplotlib.use("Agg") import matplotlib.pyplot as plt from matplotlib.patches import Rectangle, FancyArrowPatch plt.rcParams.update({"font.size": 11, "figure.dpi": 200}) OFFSETS = [0, 200, 300, 450, 600, 900, 1200, 1500, 1800] fig, ax = plt.subplots(figsize=(11, 4.4)) ax.set_xlim(-260, 2050) ax.set_ylim(-165, 105) ax.axis("off") # layers layers = [(0, -34, "#4a4a52", "AC — h$_{AC}$", "white"), (-34, -76, "#c9a86a", "Base — h$_{Base}$", "#4d3d18"), (-76, -124, "#e3d5b8", "Subbase — h$_{Subbase}$", "#6d5f3a"), (-124, -165, "#a4b58c", "Subgrade (semi-infinite)", "#33402a")] for top, bot, c, lab, tc in layers: ax.add_patch(Rectangle((-260, bot), 2310, top - bot, fc=c, ec="none")) ax.text(2020, (top + bot) / 2, lab, ha="right", va="center", fontsize=10.5, color=tc, fontweight="bold") # falling weight + plate ax.add_patch(Rectangle((-55, 62), 110, 34, fc="#8b95a5", ec="#5d6673")) ax.add_patch(FancyArrowPatch((0, 60), (0, 12), arrowstyle="-|>", mutation_scale=18, lw=2, color="#333", linestyle=(0, (4, 3)))) ax.text(0, 100, "falling weight — 707 kPa", ha="center", fontsize=10.5) ax.add_patch(Rectangle((-150, 0), 300, 9, fc="#3d4451", ec="none")) ax.text(-170, 14, "plate r = 150 mm", ha="right", fontsize=9.5) # geophones + basin basin_y = [-30 * np.exp(-x / 550) for x in OFFSETS] ax.plot(OFFSETS, basin_y, "--", color="#ff6b6b", lw=1.8, zorder=5) ax.text(700, -12, "deflection basin", color="#e04848", fontsize=9.5) for x in OFFSETS: ax.plot(x, 14, "v", ms=8, color="#10a37f" if x == 0 else "#5436da", zorder=6) ax.text(x, 26, f"D{x}", ha="center", fontsize=8.6) ax.text(1050, 55, "9 geophones record the deflection basin (μm)", ha="center", fontsize=10, color="#444") # strain markers ax.plot(0, -32, "o", ms=10, mfc="none", mec="#ff8f8f", mew=2, zorder=6) ax.text(50, -28, r"$\varepsilon_t$ — AC tensile strain (fatigue)", fontsize=10.5, color="#ffb3b3", fontweight="bold") ax.plot(0, -126, "o", ms=10, mfc="none", mec="#2e6bc4", mew=2, zorder=6) ax.text(50, -140, r"$\varepsilon_c$ — subgrade compressive strain (rutting)", fontsize=10.5, color="#1d4e94", fontweight="bold") fig.tight_layout() fig.savefig("assets/fwd_diagram.png", bbox_inches="tight", facecolor="white") print("wrote assets/fwd_diagram.png")