from PIL import Image, ImageDraw, ImageFont
from IPython.display import display
FONT = "/home/ubuntu/.fonts/NotoSansCJKsc-Regular.otf"
W, H = 720, 420
px, py = 70, 40 # 画布边距
x0, x1 = 0.0, 4.0 # x 域
def f(t):
return np.exp(-0.6 * t) * np.cos(3.0 * t)
ts = np.linspace(x0, x1, 721)
ys = f(ts)
ymin, ymax = float(min(ys)), float(max(ys))
img = Image.new("RGB", (W, H), "white")
d = ImageDraw.Draw(img)
font_l = ImageFont.truetype(FONT, 22)
font_t = ImageFont.truetype(FONT, 26)
def sx(t): return px + (t - x0) / (x1 - x0) * (W - 2 * px)
def sy(v): return H - py - (v - ymin) / (ymax - ymin) * (H - 2 * py)
# 坐标轴
d.line([(px, H - py), (W - px, H - py)], fill="black", width=2)
d.line([(px, py), (px, H - py)], fill="black", width=2)
for tick in np.linspace(x0, x1, 5):
d.text((sx(tick) - 8, H - py + 6), f"{tick:.1f}", fill="black", font=font_l)
for frac in np.linspace(0, 1, 5):
v = ymin + frac * (ymax - ymin)
d.text((6, sy(v) - 10), f"{v:+.1f}", fill="black", font=font_l)
# 曲线
pts = [(sx(t), sy(v)) for t, v in zip(ts, ys)]
d.line(pts, fill="#1f5fbf", width=3)
d.text((W // 2 - 130, 6), "衰减振荡曲线(构建时生成)", fill="black", font=font_t)
d.text((W - 60, H - py + 28), "t", fill="black", font=font_l)
d.text((30, 8), "幅值", fill="black", font=font_l)
display(img)