codexsupport-polygon-reactions.py
support-polygon-reactions.py
"""Original planar support examples: reaction fractions and a lifted foot."""
from pathlib import Path
import matplotlib.pyplot as plt
from matplotlib.patches import Polygon
import numpy as np
def reactions(point):
x, y = point
return np.array([1 - x - y, x, y])
def main():
feet = np.array([[0, 0], [1, 0], [0, 1]])
inside, outside, walking = np.array([0.3, 0.2]), np.array([0.7, 0.5]), np.array([0.6, 0.6])
fractions = reactions(inside)
assert np.allclose(fractions, [0.5, 0.3, 0.2])
assert np.allclose(fractions @ feet, inside)
assert np.isclose(np.sum(fractions), 1)
assert np.allclose(fractions * 98.1, [49.05, 29.43, 19.62])
assert np.isclose(reactions(outside)[0], -0.2)
assert np.isclose(reactions(walking)[0], -0.2)
assert np.isclose(min(inside[0], inside[1], (1 - sum(inside)) / np.sqrt(2)), 0.2)
fig, (triangle, lifting) = plt.subplots(1, 2, figsize=(10, 4.4), dpi=100,
layout="constrained")
fig.set_facecolor("white")
for ax in (triangle, lifting):
ax.add_patch(Polygon(feet, closed=True, facecolor="#dceaf1", edgecolor="#286f99",
linewidth=1.8, zorder=2))
ax.scatter(feet[:, 0], feet[:, 1], color="#286f99", s=42, zorder=5)
ax.set(xlim=(-0.12, 1.22), ylim=(-0.12, 1.25), aspect="equal", xlabel="x (m)", ylabel="y (m)")
ax.set_xticks([0, 0.5, 1])
ax.set_yticks([0, 0.5, 1])
ax.grid(alpha=0.15)
triangle.set_title("Three supports: reactions must be nonnegative")
for (x, y), label, offset in zip(feet, ["1", "2", "3"], [(7, 4), (7, 4), (7, 4)]):
triangle.annotate(label, (x, y), xytext=offset, textcoords="offset points", color="#286f99")
triangle.scatter(*inside, color="#52762a", s=45, zorder=6)
triangle.annotate("c = (0.30, 0.20)\nN = (49.05, 29.43, 19.62) N", inside,
xytext=(0.04, 0.70), fontsize=9,
arrowprops={"arrowstyle": "->", "color": "#52762a"})
triangle.scatter(*outside, color="#9f4b27", marker="x", s=55, linewidth=2, zorder=6)
triangle.annotate("Outside: (0.70, 0.50)\nwould require N₁ = −19.62 N", outside,
xytext=(0.38, 1.05), fontsize=9,
arrowprops={"arrowstyle": "->", "color": "#9f4b27"})
lifting.add_patch(Polygon([[0, 0], [1, 0], [1, 1], [0, 1]], closed=True,
facecolor="#eeeeee", edgecolor="#888888", linestyle="--", zorder=1))
lifting.scatter(1, 1, marker="x", color="#9f4b27", s=65, linewidth=2, zorder=6)
lifting.annotate("Lifted foot", (1, 1), xytext=(0.65, 1.17), fontsize=9,
arrowprops={"arrowstyle": "->", "color": "#9f4b27"})
lifting.scatter(*walking, color="#9f4b27", s=45, zorder=6)
lifting.annotate("c = (0.60, 0.60)\nInside square; outside triangle", walking,
xytext=(0.05, 0.91), fontsize=9,
arrowprops={"arrowstyle": "->", "color": "#9f4b27"})
lifting.text(0.05, 0.20, "Remaining support region", fontsize=9, color="#286f99")
lifting.set_title("Lifting a foot changes the support polygon")
fig.savefig(Path(__file__).with_suffix(".png").name, facecolor="white")
plt.close(fig)
if __name__ == "__main__":
main()