Python三维数学建模
"""
数学算式三维建模工具
用户输入数学表达式(如 "sin(x)*cos(y)"),自动生成3D曲面图
支持交互式输入、预设示例、自定义范围和网格密度
"""
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import sympy as sp
from sympy.parsing.sympy_parser import parse_expr, standard_transformations, implicit_multiplication_application
# ==================== 配置区域 ====================
DEFAULT_X_RANGE = (-5, 5) # 默认x轴范围
DEFAULT_Y_RANGE = (-5, 5) # 默认y轴范围
DEFAULT_GRID_SIZE = 60 # 默认网格密度(数值越大越精细)
DEFAULT_CMAP = 'viridis' # 默认颜色映射
# 预设示例:用户可以快速选择
PRESET_EXAMPLES = {
'1': ('双曲抛物面', 'sin(x)*cos(y)'),
'2': ('椭圆抛物面', 'x**2 + y**2'),
'3': ('马鞍面', 'x**2 - y**2'),
'4': ('正弦波纹', 'sin(x**2 + y**2)'),
'5': ('指数衰减', 'exp(-(x**2 + y**2)/5)'),
'6': ('环形波', 'cos(sqrt(x**2 + y**2))'),
'7': ('三维高斯', 'exp(-(x**2 + y**2)/4)'),
'8': ('多峰曲面', 'sin(x)*sin(y) + 0.5*cos(x*y)'),
}
def parse_expression(expr_str: str):
"""
安全解析用户输入的数学表达式
使用sympy解析,支持常见数学函数和运算
参数:
expr_str: 字符串表达式,如 "sin(x)*cos(y)"
返回:
(sympy表达式, 变量列表)
"""
# 定义允许的变量:x, y
variables = {'x': sp.Symbol('x'), 'y': sp.Symbol('y')}
# 定义允许的数学函数映射
allowed_functions = {
'sin': sp.sin, 'cos': sp.cos, 'tan': sp.tan,
'asin': sp.asin, 'acos': sp.acos, 'atan': sp.atan,
'sinh': sp.sinh, 'cosh': sp.cosh, 'tanh': sp.tanh,
'exp': sp.exp, 'log': sp.log, 'log10': sp.log10,
'sqrt': sp.sqrt, 'abs': sp.abs,
'pi': sp.pi, 'e': sp.E,
}
# 添加转换:支持隐式乘法(如 "2x" 自动转为 "2*x")
transformations = standard_transformations + (implicit_multiplication_application,)
try:
# 解析表达式
expr = parse_expr(
expr_str,
local_dict=allowed_functions,
global_dict={},
transformations=transformations
)
# 检查表达式中包含的变量
used_symbols = expr.free_symbols
if not used_symbols.issubset(set(variables.values())):
unknown = used_symbols - set(variables.values())
raise ValueError(f"表达式中包含未知变量: {unknown},请只使用 x 和 y")
return expr, variables
except Exception as e:
raise ValueError(f"表达式解析失败: {str(e)}")
def plot_3d_expression(expr_str: str,
x_range=DEFAULT_X_RANGE,
y_range=DEFAULT_Y_RANGE,
grid_size=DEFAULT_GRID_SIZE,
cmap=DEFAULT_CMAP,
save_path=None):
"""
根据数学表达式绘制3D曲面图
参数:
expr_str: 数学表达式字符串,如 "sin(x)*cos(y)"
x_range: x轴范围 (min, max)
y_range: y轴范围 (min, max)
grid_size: 网格密度
cmap: 颜色映射
save_path: 保存图片路径(可选)
"""
# 1. 解析表达式
expr, variables = parse_expression(expr_str)
x_sym = variables['x']
y_sym = variables['y']
# 2. 将sympy表达式转换为可调用的numpy函数
try:
f = sp.lambdify((x_sym, y_sym), expr, modules=['numpy'])
except Exception as e:
raise ValueError(f"表达式转换失败: {str(e)}")
# 3. 生成网格数据
x_vals = np.linspace(x_range[0], x_range[1], grid_size)
y_vals = np.linspace(y_range[0], y_range[1], grid_size)
X, Y = np.meshgrid(x_vals, y_vals)
# 4. 计算Z值
try:
Z = f(X, Y)
# 处理无穷大或NaN值
Z = np.nan_to_num(Z, nan=0.0, posinf=0.0, neginf=0.0)
except Exception as e:
raise ValueError(f"计算Z值时出错: {str(e)}")
# 5. 创建3D图形
fig = plt.figure(figsize=(12, 9))
ax = fig.add_subplot(111, projection='3d')
# 绘制曲面
surf = ax.plot_surface(X, Y, Z,
cmap=cmap,
linewidth=0,
antialiased=True,
alpha=0.9)
# 添加颜色条
fig.colorbar(surf, ax=ax, shrink=0.5, aspect=10, label='Z值')
# 设置坐标轴标签
ax.set_xlabel('X', fontsize=12)
ax.set_ylabel('Y', fontsize=12)
ax.set_zlabel('Z', fontsize=12)
# 设置标题
title = f'z = {expr_str}'
ax.set_title(title, fontsize=14, pad=20)
# 自动调整视角 - 使用一个较好的默认视角
ax.view_init(elev=25, azim=-60)
# 设置z轴范围,使图形更美观
z_max = np.max(np.abs(Z))
if z_max > 0:
ax.set_zlim(-z_max * 1.1, z_max * 1.1)
# 添加网格
ax.grid(True, linestyle='--', alpha=0.3)
# 调整布局
plt.tight_layout()
# 保存图片
if save_path:
plt.savefig(save_path, dpi=150, bbox_inches='tight')
print(f"图片已保存至: {save_path}")
# 显示图形
plt.show()
return fig, ax
def print_presets():
"""打印预设示例"""
print("\n" + "=" * 50)
print("预设示例(可直接输入编号选择):")
print("=" * 50)
for key, (name, expr) in PRESET_EXAMPLES.items():
print(f" {key}. {name:12} -> z = {expr}")
print("=" * 50)
def interactive_mode():
"""交互式模式:用户输入表达式并生成3D图"""
print("\n" + "=" * 55)
print("🧊 数学算式三维建模工具 v1.0")
print("=" * 55)
print(" 使用说明:")
print(" - 输入数学表达式,如: sin(x)*cos(y)")
print(" - 支持函数: sin, cos, tan, exp, log, sqrt, abs 等")
print(" - 支持运算符: +, -, *, /, ** (幂运算)")
print(" - 输入 'list' 查看预设示例")
print(" - 输入 'quit' 或 'exit' 退出程序")
print("=" * 55)
# 默认参数
x_range = DEFAULT_X_RANGE
y_range = DEFAULT_Y_RANGE
grid_size = DEFAULT_GRID_SIZE
cmap = DEFAULT_CMAP
while True:
try:
# 获取用户输入
user_input = input("\n 请输入表达式 (或命令): ").strip()
if not user_input:
continue
# 处理命令
if user_input.lower() in ('quit', 'exit', 'q'):
print("再见!")
break
if user_input.lower() == 'list':
print_presets()
continue
# 检查是否为预设示例编号
if user_input in PRESET_EXAMPLES:
name, expr = PRESET_EXAMPLES[user_input]
print(f"选择预设: {name} -> z = {expr}")
expr_str = expr
else:
expr_str = user_input
# 额外参数设置(可选)
print("\n 当前参数: x∈[{}, {}], y∈[{}, {}], 网格={}".format(
x_range[0], x_range[1], y_range[0], y_range[1], grid_size))
# 询问是否修改参数
change_params = input(" 修改参数? (y/n, 默认n): ").strip().lower()
if change_params == 'y':
try:
x_min = float(input(f" x最小值 (当前{x_range[0]}): ") or x_range[0])
x_max = float(input(f" x最大值 (当前{x_range[1]}): ") or x_range[1])
y_min = float(input(f" y最小值 (当前{y_range[0]}): ") or y_range[0])
y_max = float(input(f" y最大值 (当前{y_range[1]}): ") or y_range[1])
grid = int(input(f" 网格密度 (当前{grid_size}): ") or grid_size)
x_range = (x_min, x_max)
y_range = (y_min, y_max)
grid_size = max(10, min(200, grid)) # 限制范围
except ValueError:
print("参数格式错误,使用默认值")
# 绘制3D图
print(f" 正在生成 3D 曲面: z = {expr_str} ...")
plot_3d_expression(expr_str, x_range, y_range, grid_size, cmap)
print("✅ 绘图完成!")
except KeyboardInterrupt:
print("\n 再见!")
break
except Exception as e:
print(f" 错误: {str(e)}")
print("请检查表达式语法,或输入 'list' 查看示例")
def main():
"""主函数"""
# 如果有命令行参数,直接绘制
import sys
if len(sys.argv) > 1:
expr_str = sys.argv[1]
print(f"绘制表达式: z = {expr_str}")
try:
plot_3d_expression(expr_str)
except Exception as e:
print(f"错误: {str(e)}")
print("使用方法: python script.py 'sin(x)*cos(y)'")
else:
# 交互式模式
interactive_mode()
if __name__ == "__main__":
main()
```
使用与交互
运行脚本后,您可以直接输入数学表达式(如 sin(x)*cos(y))即可生成3D曲面图。程序会实时解析并渲染,支持调整视角和缩放。
· 输入方式:支持直接输入表达式(如 x**2 + y**2),或输入数字编号(如 1)快速选择预设示例。输入 list 可查看所有预设,输入 quit 退出程序。
· 参数微调:每次绘图前可修改X/Y轴范围(默认-5~5)和网格密度(默认60),网格越大曲面越精细但渲染稍慢。
· 交互操作:生成的3D图支持鼠标拖拽旋转、滚轮缩放,右键平移,方便从任意角度观察曲面形态。
· 视觉优化:自动调整Z轴范围、添加颜色条和网格线,曲面颜色映射(默认为viridis)可清晰反映高度变化。