在计算机里画一条圆,无非是把“无限光滑”的几何对象翻译成“有限离散”的数值坐标。SymPy 负责把几何语言写成符号方程,NumPy 负责把符号方程变成高速向量运算,Matplotlib 再把数值结果还原成肉眼可见的图形。下面以半径为 RhR_hRh 的圆为例,完整地走一遍从符号到像素的全过程。
1 符号方程
圆在极坐标下的参数方程十分简洁:
x(ψ)=Rhcosψ,y(ψ)=Rhsinψ,ψ∈[0,2π). x(\psi)=R_h\cos\psi,\quad y(\psi)=R_h\sin\psi, \quad \psi\in[0,2\pi). x(ψ)=Rhcosψ,y(ψ)=Rhsinψ,ψ∈[0,2π).
用 SymPy 写成一个 2×12\times 12×1 的矩阵即可:
S(ψ)=[RhcosψRhsinψ]. \mathbf S(\psi)=\begin{bmatrix}R_h\cos\psi\\R_h\sin\psi\end{bmatrix}. S(ψ)=[RhcosψRhsinψ].
2 编译
符号表达式不能直接喂给 CPU,需要借助 lambdify
做一次“即时编译”。它把 SymPy 的 cos,sin\cos,\sincos,sin 映射到 NumPy 的 np.cos,np.sin
,于是整个表达式立刻获得向量化能力,一次可处理上百万个 ψ\psiψ 值。
3 采样
在 [0,2π)[0,2\pi)[0,2π) 上等间隔地撒 nnn 个点,既避免首尾重叠,又保证视觉上的均匀。
ψk=2πkn,k=0,1,…,n−1.
\psi_k=\frac{2\pi k}{n},\quad k=0,1,\dots,n-1.
ψk=n2πk,k=0,1,…,n−1.
4 数值化与可视化
把采样点代入编译后的函数,得到两个长度 nnn 的浮点数组 x_vals, y_vals
。对它们做一次散点或折线绘制,圆就出现在屏幕上了。
下面给出可直接运行的完整代码,复制即得结果。
"""
Circle discretization: SymPy -> NumPy -> Matplotlib
author: you
"""
import numpy as np
import sympy as sy
import matplotlib.pyplot as plt
# -------------------------------------------------
# 1) 符号定义:S(psi) = (R_h cos psi, R_h sin psi)
# -------------------------------------------------
R_h = 5.0 # 固定半径
psi = sy.symbols('psi') # 角度变量
S = sy.Matrix([R_h * sy.cos(psi),
R_h * sy.sin(psi)])
# -------------------------------------------------
# 2) 编译:把符号表达式变成 NumPy 向量化函数
# -------------------------------------------------
x_fn = sy.lambdify(psi, S[0], modules='numpy')
y_fn = sy.lambdify(psi, S[1], modules='numpy')
# -------------------------------------------------
# 3) 采样:在 [0, 2π) 生成 n 个角度
# -------------------------------------------------
n = 200
psi_vals = np.linspace(0, 2*np.pi, n, endpoint=False)
# -------------------------------------------------
# 4) 数值化:计算离散坐标
# -------------------------------------------------
x_vals = x_fn(psi_vals)
y_vals = y_fn(psi_vals)
# -------------------------------------------------
# 5) 可视化:把点连成圆
# -------------------------------------------------
plt.figure(figsize=(4, 4))
plt.plot(x_vals, y_vals, lw=2, color='#1f77b4')
plt.scatter(x_vals[::10], y_vals[::10], color='k', s=10) # 稀疏点标记
plt.gca().set_aspect('equal')
plt.title(f'Circle, $R_h = {R_h}$')
plt.xlabel('$x$')
plt.ylabel('$y$')
plt.tight_layout()
plt.show()
运行后,你将看到一个半径为 555 的圆,既保留了符号方程的精确,也展现了数值离散的效率。