codexwing-planform-equal-area.py
wing-planform-equal-area.py
"""Compare three wing planforms with identical span and projected area.
Tested with Python 3.14, NumPy 2.3.5 and Matplotlib 3.10.7.
Run from the output directory; writes wing-planform-equal-area.png there.
"""
import numpy as np
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
fig, axs = plt.subplots(1, 3, figsize=(9, 3.6), dpi=100, facecolor='white')
y = np.linspace(-5, 5, 301)
for ax, taper, sweep, title in zip(axs, (False, True, True), (0, 0, 0.45),
('Rectangular', 'Tapered', 'Swept and tapered')):
c = 3 - .4 * np.abs(y) if taper else np.full_like(y, 2.)
lead = sweep * np.abs(y)
ax.fill_between(y, lead, lead+c, color='#b9dceb', edgecolor='#17465d', linewidth=1.6)
ax.plot([0, 0], [-.6, 5.2], '--', lw=.7, color='gray')
ax.annotate('', xy=(5, -.6), xytext=(-5, -.6), arrowprops={'arrowstyle':'<->', 'color':'#333'})
ax.text(0, -1.05, 'span b = 10 m', ha='center', fontsize=10)
ax.set_title(title, fontsize=11)
ax.text(0, 5.0, 'area S = 20 m²', ha='center', fontsize=10)
ax.set_aspect('equal')
ax.set_xlim(-5.8, 5.8)
ax.set_ylim(5.6, -1.6)
ax.axis('off')
axs[0].annotate('', xy=(-5.35, 2), xytext=(-5.35, 0), arrowprops={'arrowstyle':'<->'})
axs[0].text(-5.65, 1, '2 m', rotation=90, va='center', ha='center', fontsize=9)
fig.suptitle('Equal span and area do not determine wing planform', fontsize=13, y=.96)
fig.text(.5, .04, 'Top views • geometric examples, not equal aerodynamic performance', ha='center', fontsize=10)
fig.subplots_adjust(left=.03, right=.98, bottom=.13, top=.84, wspace=.15)
fig.savefig('wing-planform-equal-area.png', facecolor='white', dpi=100)
plt.close(fig)