codexexterior-product-oriented-area-and-shear.py
exterior-product-oriented-area-and-shear.py
"""Original oriented-area comparison: u wedge v = u wedge (v + u).
Tested with Python 3.14, NumPy 2.3.5 and Matplotlib 3.10.7.
Write basename.png to the current working directory.
"""
from pathlib import Path
import matplotlib.pyplot as plt
from matplotlib.patches import Polygon
import numpy as np
def main():
plt.rcParams.update({"font.size": 12, "axes.titlesize": 14})
u = np.array([3.0, 1.0])
v = np.array([1.0, 2.0])
fig, axes = plt.subplots(1, 2, figsize=(11.2, 4.5), dpi=120)
fig.patch.set_facecolor("white")
for ax, other, label, title in zip(
axes, [v, v+u], ["v = (1, 2)", "v + u = (4, 3)"],
["Original pair", "Sheared pair, same area"]
):
points = np.array([[0., 0.], u, u+other, other])
ax.add_patch(Polygon(points, closed=True, facecolor="#c7e9c0",
edgecolor="#238b45", linewidth=2))
for vector, color in [(u, "#2166ac"), (other, "#c65102")]:
ax.annotate("", vector, xytext=(0, 0),
arrowprops={"arrowstyle": "-|>", "color": color, "lw": 2.6})
ax.annotate("u = (3, 1)", u, xytext=(9, -13), textcoords="offset points",
color="#2166ac", fontsize=11)
ax.annotate(label, other, xytext=(-3, 12), textcoords="offset points",
color="#c65102", fontsize=11)
center = points.mean(axis=0)
ax.text(center[0], center[1], "Area = +5", ha="center", va="center",
fontsize=12, color="#145a26",
bbox={"facecolor": "white", "edgecolor": "none", "alpha": 0.85})
ax.scatter(points[:, 0], points[:, 1], color="#333333", s=15)
ax.set(xlim=(-0.5, 7.8), ylim=(-0.4, 4.8), xlabel="x", ylabel="y",
title=title, xticks=[0, 2, 4, 6], yticks=[0, 2, 4])
ax.set_aspect("equal")
ax.grid(alpha=0.22)
ax.text(0.02, 0.97, "Reverse the order: area = −5",
transform=ax.transAxes, va="top", fontsize=10)
fig.suptitle(r"$u\wedge v = u\wedge(v+u) = 5e_1\wedge e_2$", fontsize=18)
fig.subplots_adjust(left=0.05, right=0.985, bottom=0.15, top=0.80, wspace=0.20)
fig.savefig(Path(__file__).with_suffix(".png").name, facecolor="white", transparent=False)
plt.close(fig)
if __name__ == "__main__":
main()