You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

227 lines
8.2 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

from numpy import *
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from convert_formula import convert_formula # 导入转换函数
import matplotlib
# 全局配置中文字体(新增)
matplotlib.rcParams['font.sans-serif'] = ['SimHei'] # 使用黑体Windows系统常用中文字体
matplotlib.rcParams['axes.unicode_minus'] = False # 解决负号显示问题
def plot_plane_curve(a, b, M, f1, f2, title='平面曲线'):
'''
绘制平面参数曲线
参数:
a (float): 参数t的起始值
b (float): 参数t的终止值需满足 a <= b
M (int): 参数t的采样点数需为正整数
f1 (callable): X坐标关于t的函数输入一维数组输出一维数组
f2 (callable): Y坐标关于t的函数输入一维数组输出一维数组
title (str): 图形标题
'''
# 参数校验
if not (isinstance(M, int) and M > 0):
raise ValueError(f'采样点数M={M}需为正整数')
if a > b:
raise ValueError(f'参数范围需满足a={a} <= b={b}')
t = linspace(a, b, M)
X = f1(t)
Y = f2(t)
plt.figure()
plt.plot(X, Y)
plt.xlabel('X')
plt.ylabel('Y')
plt.title(title) # 标题使用用户输入的中文
plt.grid(True)
plt.show()
def plot_space_surface(a, b, M, c, d, N, F1, F2, F3, title='空间曲面'):
'''
绘制空间参数曲面
参数:
a/b (float): 参数t的取值范围a <= b
M (int): t的采样点数正整数
c/d (float): 参数s的取值范围c <= d
N (int): s的采样点数正整数
F1/F2/F3 (callable): X/Y/Z坐标关于s,t的函数输入二维网格输出二维网格
title (str): 图形标题
'''
# 参数校验
for var, name in [(M, 'M'), (N, 'N')]:
if not (isinstance(var, int) and var > 0):
raise ValueError(f'采样点数{name}={var}需为正整数')
for start, end, name in [(a, b, 't'), (c, d, 's')]:
if start > end:
raise ValueError(f'{name}参数范围需满足{start} <= {end}')
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
t = linspace(a, b, M)
s = linspace(c, d, N)
s_grid, t_grid = meshgrid(s, t)
X = F1(s_grid, t_grid)
Y = F2(s_grid, t_grid)
Z = F3(s_grid, t_grid)
ax.plot_surface(X, Y, Z, cmap='viridis')
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
ax.set_title(title) # 标题使用用户输入的中文
plt.show()
def plot_space_curve(a, b, M, F1, F2, F3, title='空间曲线'):
'''
绘制单参数空间曲线(如螺旋线)
参数:
a/b (float): 参数t的取值范围a <= b
M (int): t的采样点数正整数
F1/F2/F3 (callable): X/Y/Z坐标关于t的函数输入一维数组输出一维数组
title (str): 图形标题
'''
# 参数校验
if not (isinstance(M, int) and M > 0):
raise ValueError(f'采样点数M={M}需为正整数')
if a > b:
raise ValueError(f'参数范围需满足a={a} <= b={b}')
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
t = linspace(a, b, M)
X = F1(t)
Y = F2(t)
Z = F3(t)
ax.plot3D(X, Y, Z, color='blue', linewidth=2) # 使用plot3D绘制曲线
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
ax.set_title(title) # 标题使用用户输入的中文
plt.show()
def test_plane_and_space_curves():
# 测试平面曲线:单位圆
plot_plane_curve(
a=0, b=2*pi, M=1000,
f1=lambda t: np.cos(t),
f2=lambda t: np.sin(t),
title='单位圆(参数方程)'
)
# 测试平面曲线:抛物线y=x²
plot_plane_curve(
a=-2, b=2, M=100,
f1=lambda t: t,
f2=lambda t: t**2,
title='抛物线 y=x²参数方程'
)
# 测试空间曲面:球面
plot_space_surface(
a=0, b=pi, M=50,
c=0, d=2*pi, N=50,
F1=lambda s,t: np.sin(t)*np.cos(s),
F2=lambda s,t: np.sin(t)*np.sin(s),
F3=lambda s,t: np.cos(t),
title='球面(参数方程)'
)
# 新增测试空间曲线圆锥螺旋线半径随z轴增大
plot_space_curve(
a=0, b=8*pi, M=1000,
F1=lambda t: t * np.cos(t),
F2=lambda t: t * np.sin(t),
F3=lambda t: t,
title='圆锥螺旋线(参数方程)'
)
def UI():
'''命令行交互界面(支持用户输入采样点范围)'''
while True:
print("\n=== 解析几何绘图工具 ===")
print("1. 绘制平面曲线")
print("2. 绘制空间曲线")
print("3. 绘制空间曲面")
print("4. 退出程序")
choice = input("请选择功能输入1-4: ")
if choice == '4':
print("已退出程序")
break
# 平面曲线单参数t
elif choice == '1':
print("\n--- 平面曲线绘制 ---\n提示变量用t如输入cos(t)会自动转换为np.cos(t)参数范围支持输入pi如2*pi")
x_expr = input("X(t)表达式: ")
y_expr = input("Y(t)表达式: ")
a_input = input("请输入t的起始值如0或pi: ").strip().lower() # 支持pi输入
b_input = input("请输入t的结束值如2*pi: ").strip().lower()
try:
a = eval(a_input)
b = eval(b_input)
x_func = eval(f"lambda t: {convert_formula(x_expr)}")
y_func = eval(f"lambda t: {convert_formula(y_expr)}")
plot_plane_curve(a=a, b=b, M=1000, f1=x_func, f2=y_func, title=f"平面曲线: X(t)={x_expr}, Y(t)={y_expr}")
except Exception as e:
print(f"错误: {str(e)}")
# 空间曲线单参数t
elif choice == '2':
print("\n--- 空间曲线绘制 ---\n提示变量用t参数范围支持输入pi如8*pi")
x_expr = input("X(t)表达式: ")
y_expr = input("Y(t)表达式: ")
z_expr = input("Z(t)表达式: ")
a_input = input("请输入t的起始值如0或pi: ").strip().lower()
b_input = input("请输入t的结束值如8*pi: ").strip().lower()
try:
a = eval(a_input)
b = eval(b_input)
x_func = eval(f"lambda t: {convert_formula(x_expr)}")
y_func = eval(f"lambda t: {convert_formula(y_expr)}")
z_func = eval(f"lambda t: {convert_formula(z_expr)}")
plot_space_curve(a=a, b=b, M=10000, F1=x_func, F2=y_func, F3=z_func, title=f"空间曲线: X(t)={x_expr}, Y(t)={y_expr}, Z(t)={z_expr}")
except Exception as e:
print(f"错误: {str(e)}")
# 空间曲面双参数s/t
elif choice == '3':
print("\n--- 空间曲面绘制 ---\n提示变量用s和t参数范围支持输入pi如2*pi")
x_expr = input("X(s,t)表达式: ")
y_expr = input("Y(s,t)表达式: ")
z_expr = input("Z(s,t)表达式: ")
c_input = input("请输入s的起始值如0或pi: ").strip().lower()
d_input = input("请输入s的结束值如2*pi: ").strip().lower()
a_input = input("请输入t的起始值如0或pi: ").strip().lower()
b_input = input("请输入t的结束值如pi: ").strip().lower()
try:
c = eval(c_input)
d = eval(d_input)
a = eval(a_input)
b = eval(b_input)
x_func = eval(f"lambda s,t: {convert_formula(x_expr)}")
y_func = eval(f"lambda s,t: {convert_formula(y_expr)}")
z_func = eval(f"lambda s,t: {convert_formula(z_expr)}")
plot_space_surface(a=a, b=b, M=50, c=c, d=d, N=50, F1=x_func, F2=y_func, F3=z_func, title=f"空间曲面: X(s,t)={x_expr}, Y(s,t)={y_expr}, Z(s,t)={z_expr}")
except Exception as e:
print(f"错误: {str(e)}")
else:
print("输入无效,请重新选择")
if __name__ == "__main__":
UI() # 启动命令行界面
#test_plane_and_space_curves()