Python数学可视化——显函数、隐函数及复杂曲线的交互式绘图技术

Python数学可视化——显函数、隐函数及复杂曲线的交互式绘图技术

Python数学可视化——显函数、隐函数及复杂曲线的交互式绘图技术

一、引言

在科学计算和数据分析中,函数与方程的可视化是理解数学关系和物理现象的重要工具。本文基于Python的Tkinter和Matplotlib库,实现一个功能完善的函数与方程可视化工具,支持显函数、隐函数、特殊曲线(如心形线)及物理场分布(如电势)的交互式绘图,并提供安全的表达式解析、图像保存等功能。

二、核心技术架构

2.1 系统架构与技术选型

  • 界面层:使用Tkinter构建GUI,包含类型选择、表达式输入、预设函数下拉菜单等控件
  • 计算层
    • 显函数:通过np.linspace生成采样点,安全计算函数值
    • 隐函数:基于等高线算法contour绘制等值线
    • 安全机制:通过正则表达式过滤非法字符,限制白名单函数防止代码注入
  • 可视化层:Matplotlib实现图表渲染,支持动态更新和交互式工具条

2.2 安全表达式解析

defis_valid_expression(expr):"""验证表达式安全性""" allowed_chars =set("0123456789.+-*/()xy^np_sin_cos_tan_exp_sqrt_log_pi_ ") invalid_chars =set(expr.replace('.','').replace('_',''))- allowed_chars if invalid_chars:raise ValueError(f"非法字符: {''.join(invalid_chars)}")# 括号匹配检查 stack =[]for char in expr:if char =='(': stack.append(char)elif char ==')':ifnot stack:raise ValueError("括号不匹配") stack.pop()if stack:raise ValueError("括号不匹配")returnTruedefsafe_eval(expr, namespace):"""安全执行表达式""" expr = expr.replace('^','**')# 替换幂运算符 allowed_funcs ={'np': np,'sin': np.sin,'cos': np.cos,'tan': np.tan,'exp': np.exp,'sqrt': np.sqrt,'log': np.log,'pi': np.pi } safe_globals ={"__builtins__":None} safe_locals ={**allowed_funcs,**namespace} compiled_code =compile(expr,'<string>','eval')returneval(compiled_code, safe_globals, safe_locals)

三、显函数可视化

3.1 核心实现

defplot_explicit_function(self, f, x_range, title):"""绘制显函数""" self.fig.clear() ax = self.fig.add_subplot(111) ax.set_facecolor('white') x = np.linspace(x_range[0], x_range[1],1000) y = np.array([f(xi)for xi in x])# 逐点计算防止数组错误 ax.plot(x, y,'b-', linewidth=2.5) ax.set_title(title) ax.grid(True, linestyle='--', alpha=0.6) self.optimize_ticks(ax, x_range,(y.min(), y.max()))

3.2 案例演示

案例1:三次函数
# 预设函数定义 self.explicit_presets ={"三次函数":{"func":lambda x: x**3-3*x,"expr":"x**3 - 3*x","x_range":(-2.5,2.5),"title":"三次函数: $y = x^3 - 3x$",}}
在这里插入图片描述
案例2:双曲线
plot_explicit("1/x", x_range=(-5,5))# 输入表达式直接绘制
在这里插入图片描述

四、隐函数可视化

4.1 核心实现

defplot_implicit_equation(self, eq, x_range, y_range):"""绘制隐函数F(x,y)=0""" x = np.linspace(x_range[0], x_range[1],500) y = np.linspace(y_range[0], y_range[1],500) X, Y = np.meshgrid(x, y) Z = eq(X, Y) self.fig.contour(X, Y, Z, levels=[0], colors='red', linewidths=2.5) self.fig.contourf(X, Y, Z, alpha=0.6)# 填充色显示数值分布 self.fig.colorbar(label='F(x,y)')

4.2 案例演示

案例1:圆方程
# 预设隐函数 self.implicit_presets["圆"]={"eq":lambda x, y: x**2+ y**2-4,"title":"圆: $x^2 + y^2 = 4$",}
在这里插入图片描述
案例2:笛卡尔叶形线
plot_implicit("x**3 + y**3 - 3*x*y", x_range=(-3,3), y_range=(-3,3))
在这里插入图片描述

五、特色曲线与物理应用

5.1 心形线(数学艺术)

defplot_heart_curve(self):"""笛卡尔心形线""" eq =lambda x,y:(x**2+ y**2-1)**3- x**2*y**3 self.plot_implicit_equation(eq, x_range=(-1.5,1.5), y_range=(-1.5,1.5)) self.fig.contourf(..., colors='pink', alpha=0.4)# 填充爱心区域
在这里插入图片描述

5.2 电势分布(物理应用)

defplot_electric_potential(self):"""点电荷电势分布""" charges =[{"x":-1,"y":0,"q":1},{"x":1,"y":0,"q":-1}] x = np.linspace(-2.5,2.5,500) y = np.linspace(-2,2,500) X,Y = np.meshgrid(x,y) V =sum(charge['q']/np.sqrt((X-c['x'])**2+(Y-c['y'])**2)for c in charges) self.fig.contourf(X,Y,V, cmap='coolwarm')# 温度映射显示电势 self.fig.scatter([c['x']],[c['y']], s=300, c=['red','blue'], marker='+-')
在这里插入图片描述

六、交互式GUI设计

6.1 界面布局

def__init__(self, root): self.root = root self.root.geometry("1200x800")# 左侧控制面板 left_frame = ttk.LabelFrame(root, text="可视化选项") ttk.Radiobutton(left_frame, text="显函数", variable=self.viz_type, value="explicit") ttk.Radiobutton(left_frame, text="隐函数", variable=self.viz_type, value="implicit") ttk.Radiobutton(left_frame, text="心形线", variable=self.viz_type, value="heart")# 右侧绘图区域 self.canvas = FigureCanvasTkAgg(self.fig, master=right_frame) self.toolbar = NavigationToolbar2Tk(self.canvas, toolbar_frame)# 集成缩放工具

6.2 动态控件更新

defupdate_controls(self):"""根据选择类型显示对应控件"""if self.viz_type.get()=="explicit": self.explicit_frame.pack() self.update_preset_options(self.explicit_presets.keys())elif self.viz_type.get()=="implicit": self.implicit_frame.pack() self.update_preset_options(self.implicit_presets.keys())# 隐藏其他面板

七、高级功能

7.1 图像保存

defsave_image(self): filename = simpledialog.askstring("保存","文件名")if filename: self.fig.savefig(f"{filename}.png", dpi=150, bbox_inches="tight") messagebox.showinfo("成功",f"保存至: {os.path.abspath(filename)}")

7.2 公式渲染

defget_function_label(self, expr):"""生成LaTeX公式""" expr = expr.replace('np.sin','\\sin').replace('**','^') expr = re.sub(r'(\d)/(\d)',r'\\frac{\1}{\2}', expr)# 自动转换分数returnf"${expr}$"

八、教学与应用场景

8.1 教学场景

  • 基础数学:演示函数图像变换(平移、缩放、翻转)
  • 解析几何:对比显式方程与隐式方程的几何意义
  • 高等数学:展示参数方程(如心形线)与极坐标方程
  • 大学物理:可视化电场、磁场等物理场分布

8.2 扩展方向

  1. 支持极坐标绘图
  2. 添加导数/积分可视化
  3. 集成3D绘图功能(使用mpl_toolkits.mplot3d)
  4. 开发数据导入功能(CSV/Excel)

九、总结

本文实现的函数可视化工具具备以下特点:

  1. 安全性:通过表达式过滤和白名单机制防止代码注入
  2. 交互性:支持实时切换函数类型、调整参数、缩放图表
  3. 扩展性:预设函数与自定义输入结合,方便扩展新类型
  4. 专业性:支持LaTeX公式渲染、物理场可视化等专业需求

该工具可广泛应用于数学教学、工程仿真、科学研究等领域,帮助用户快速建立数学表达式与图形之间的直观联系。

十、完整代码

import tkinter as tk from tkinter import ttk, messagebox, simpledialog import numpy as np import matplotlib.pyplot as plt from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk from matplotlib.figure import Figure import matplotlib.patches as patches from matplotlib import ticker from matplotlib.colors import ListedColormap import re import os # 设置matplotlib支持中文显示 plt.rcParams["font.family"]=["SimHei","WenQuanYi Micro Hei","Heiti TC","Arial Unicode MS",] plt.rcParams["axes.unicode_minus"]=False# 解决负号显示问题classFunctionVisualizer:def__init__(self, root): self.root = root self.root.title("函数与方程可视化工具") self.root.geometry("1200x800") self.root.minsize(1000,700)# 设置主题颜色 self.bg_color ="#f5f5f5" self.frame_color ="#ffffff" self.button_color ="#3b82f6" self.button_text_color ="#ffffff"# 预设函数分组(显函数/隐函数) self.explicit_presets ={"三次函数":{"func":lambda x: x**3-3* x,"expr":"x**3 - 3*x","x_range":(-2.5,2.5),"title":"三次函数: $y = x^3 - 3x$",},"双曲线":{"func":lambda x:1/ x,"expr":"1/x","x_range":(-5,5),"title":"双曲线: $y = \\frac{1}{x}$",},"指数函数":{"func":lambda x: np.exp(x),"expr":"np.exp(x)","x_range":(-3,3),"title":"指数函数: $y = e^x$",},} self.implicit_presets ={"圆":{"eq":lambda x, y: x**2+ y**2-4,"expr":"x**2 + y**2 - 4","x_range":(-3,3),"y_range":(-3,3),"title":"圆: $x^2 + y^2 = 4$",},"椭圆":{"eq":lambda x, y: x**2/4+ y**2/9-1,"expr":"x**2/4 + y**2/9 - 1","x_range":(-3,3),"y_range":(-4,4),"title":"椭圆: $\\frac{x^2}{4} + \\frac{y^2}{9} = 1$",},"双曲线(隐式)":{"eq":lambda x, y: x**2- y**2-1,"expr":"x**2 - y**2 - 1","x_range":(-3,3),"y_range":(-3,3),"title":"双曲线: $x^2 - y^2 = 1$",},"笛卡尔叶形线":{"eq":lambda x, y: x**3+ y**3-3* x * y,"expr":"x**3 + y**3 - 3*x*y","x_range":(-3,3),"y_range":(-3,3),"title":"笛卡尔叶形线: $x^3 + y^3 = 3xy$",},}# 创建主框架 main_frame = ttk.Frame(self.root, padding=10) main_frame.pack(fill=tk.BOTH, expand=True)# 创建左侧控制面板 left_frame = ttk.LabelFrame( main_frame, text="函数与方程可视化选项", padding=10, width=375) left_frame.pack(side=tk.LEFT, fill=tk.Y, padx=(0,10)) left_frame.pack_propagate(False)# 固定宽度# 创建右侧绘图区域 right_frame = ttk.Frame(main_frame) right_frame.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True)# 创建绘图区域和工具栏容器 self.plot_frame = ttk.Frame(right_frame) self.plot_frame.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)# 初始化绘图区域 self.fig = Figure(figsize=(8,6), dpi=100) self.canvas = FigureCanvasTkAgg(self.fig, master=self.plot_frame) self.canvas.get_tk_widget().pack(fill=tk.BOTH, expand=True)# 添加工具栏 self.toolbar_frame = ttk.Frame(right_frame, height=40) self.toolbar_frame.pack(fill=tk.X, padx=5, pady=(0,5)) self.toolbar = NavigationToolbar2Tk(self.canvas, self.toolbar_frame) self.toolbar.update()# 添加控制选项 self.create_controls(left_frame)# 初始显示 self.plot_predefined_function()defcreate_controls(self, parent):"""创建控制选项""" ttk.Label(parent, text="选择可视化类型:", font=("SimHei",10,"bold")).pack( anchor=tk.W, pady=(0,10))# 可视化类型选择 self.viz_type = tk.StringVar(value="explicit") types =[("显函数","explicit"),("隐函数","implicit"),("心形线","heart"),("电势分布","potential"),]for text, value in types: ttk.Radiobutton( parent, text=text, variable=self.viz_type, value=value, command=self.update_controls,).pack(anchor=tk.W, padx=5, pady=2)# 预设函数下拉菜单(动态更新选项) self.preset_frame = ttk.LabelFrame(parent, text="预设函数", padding=10) self.preset_frame.pack(fill=tk.X, pady=10)# 动态选项变量 self.preset_functions = tk.StringVar() self.preset_combobox = ttk.Combobox( self.preset_frame, textvariable=self.preset_functions, width=30) self.preset_combobox.pack(fill=tk.X, pady=5) ttk.Button( self.preset_frame, text="绘制预设函数", command=self.plot_predefined_function,).pack(fill=tk.X, pady=5)# 显函数输入 self.explicit_frame = ttk.LabelFrame(parent, text="显函数输入", padding=10) self.explicit_frame.pack(fill=tk.X, pady=10) ttk.Label(self.explicit_frame, text="函数表达式 (例如 x**2):").pack(anchor=tk.W) self.explicit_entry = ttk.Entry(self.explicit_frame, width=30) self.explicit_entry.insert(0,"x**3 - 3*x") self.explicit_entry.pack(fill=tk.X, pady=5) ttk.Label(self.explicit_frame, text="X范围 (min,max):").pack(anchor=tk.W) self.x_range_entry = ttk.Entry(self.explicit_frame, width=30) self.x_range_entry.insert(0,"-2.5,2.5") self.x_range_entry.pack(fill=tk.X, pady=5) ttk.Button( self.explicit_frame, text="绘制显函数", command=self.plot_explicit ).pack(fill=tk.X, pady=5)# 隐函数输入 self.implicit_frame = ttk.LabelFrame(parent, text="隐函数输入", padding=10) self.implicit_frame.pack(fill=tk.X, pady=10) ttk.Label(self.implicit_frame, text="方程表达式 (例如 x**2 + y**2 - 4):").pack( anchor=tk.W ) self.implicit_entry = ttk.Entry(self.implicit_frame, width=30) self.implicit_entry.insert(0,"x**3 + y**3 - 3*x*y") self.implicit_entry.pack(fill=tk.X, pady=5) ttk.Label(self.implicit_frame, text="X范围 (min,max):").pack(anchor=tk.W) self.implicit_x_range_entry = ttk.Entry(self.implicit_frame, width=30) self.implicit_x_range_entry.insert(0,"-3,3") self.implicit_x_range_entry.pack(fill=tk.X, pady=5) ttk.Label(self.implicit_frame, text="Y范围 (min,max):").pack(anchor=tk.W) self.implicit_y_range_entry = ttk.Entry(self.implicit_frame, width=30) self.implicit_y_range_entry.insert(0,"-3,3") self.implicit_y_range_entry.pack(fill=tk.X, pady=5) ttk.Button( self.implicit_frame, text="绘制隐函数", command=self.plot_implicit ).pack(fill=tk.X, pady=5)# 保存图像按钮 ttk.Button(parent, text="保存图像", command=self.save_image).pack( side=tk.BOTTOM, pady=10)# 初始更新控件状态 self.update_controls()defupdate_controls(self):"""更新控件状态""" viz_type = self.viz_type.get()# 隐藏所有输入面板 self.preset_frame.pack_forget() self.explicit_frame.pack_forget() self.implicit_frame.pack_forget()# 显示对应面板if viz_type =="explicit": self.explicit_frame.pack(fill=tk.X, pady=10) self.update_preset_options(self.explicit_presets.keys())# 显函数预设elif viz_type =="implicit": self.implicit_frame.pack(fill=tk.X, pady=10) self.update_preset_options(self.implicit_presets.keys())# 隐函数预设elif viz_type =="heart": self.plot_heart_curve()elif viz_type =="potential": self.plot_electric_potential()# 显示预设框架 self.preset_frame.pack(fill=tk.X, pady=10)defupdate_preset_options(self, options=None):"""动态更新预设函数选项"""if options isNone: options =[] self.preset_combobox["values"]=list(options)if options: self.preset_functions.set(list(options)[0])# 默认选择第一个defplot_predefined_function(self):"""绘制预设函数""" viz_type = self.viz_type.get() selected = self.preset_functions.get() self.fig.clear() ax = self.fig.add_subplot(111) ax.set_facecolor("white") self.fig.set_facecolor("white")if viz_type =="explicit"and selected in self.explicit_presets: data = self.explicit_presets[selected] self.plot_explicit_function( f=data["func"], x_range=data["x_range"], title=data["title"])# 更新显函数输入框 self.explicit_entry.delete(0, tk.END) self.explicit_entry.insert(0, data["expr"]) self.x_range_entry.delete(0, tk.END) self.x_range_entry.insert(0,f"{data['x_range'][0]},{data['x_range'][1]}")elif viz_type =="implicit"and selected in self.implicit_presets: data = self.implicit_presets[selected] self.plot_implicit_equation( eq=data["eq"], x_range=data["x_range"], y_range=data["y_range"], title=data["title"],)# 更新隐函数输入框 self.implicit_entry.delete(0, tk.END) self.implicit_entry.insert(0, data["expr"]) self.implicit_x_range_entry.delete(0, tk.END) self.implicit_x_range_entry.insert(0,f"{data['x_range'][0]},{data['x_range'][1]}") self.implicit_y_range_entry.delete(0, tk.END) self.implicit_y_range_entry.insert(0,f"{data['y_range'][0]},{data['y_range'][1]}") self.canvas.draw()defis_valid_expression(self, expr):"""验证表达式是否为有效的数学表达式"""# 允许的字符:数字、运算符、函数名、xy变量、小数点、括号、空格 allowed_chars =set("0123456789.+-*/()xy^np_sin_cos_tan_exp_sqrt_log_pi_ ")# 移除所有允许的字符,检查是否还有剩余 cleaned = expr.replace('.','').replace('_','') invalid_chars =set(cleaned)- allowed_chars if invalid_chars:raise ValueError(f"非法字符: {''.join(invalid_chars)}")# 检查括号匹配 stack =[]for char in expr:if char =='(': stack.append(char)elif char ==')':ifnot stack:raise ValueError("括号不匹配:缺少左括号") stack.pop()if stack:raise ValueError("括号不匹配:缺少右括号")returnTruedefsafe_eval(self, expr, namespace):"""安全地执行表达式计算"""try: self.is_valid_expression(expr)# 替换常见函数别名 expr = expr.replace('^','**')# 替换^为**# 白名单函数和变量 allowed_funcs ={'np': np,'sin': np.sin,'cos': np.cos,'tan': np.tan,'exp': np.exp,'sqrt': np.sqrt,'log': np.log,'pi': np.pi,'arctan2': np.arctan2,}# 创建安全命名空间 safe_globals ={"__builtins__":None} safe_locals ={**allowed_funcs,**namespace}# 使用编译后的代码提高安全性 compiled_code =compile(expr,'<string>','eval')returneval(compiled_code, safe_globals, safe_locals)except Exception as e:raise ValueError(f"表达式错误: {str(e)}")defplot_explicit(self):"""绘制用户输入的显函数"""try: func_str = self.explicit_entry.get().strip() x_range_str = self.x_range_entry.get().strip()ifnot func_str ornot x_range_str:raise ValueError("请输入函数表达式和X范围")# 解析x范围 x_min, x_max =map(float, x_range_str.split(","))if x_min >= x_max:raise ValueError("X范围的最小值必须小于最大值")# 生成x值 x_vals = np.linspace(x_min, x_max,1000)# 安全计算y值(逐个点计算,避免数组错误) y_vals = np.zeros_like(x_vals)for i, x inenumerate(x_vals): y_vals[i]= self.safe_eval(func_str,{'x': x})# 绘制函数 self.plot_explicit_function( f=lambda x: y_vals, x_range=(x_min, x_max), title=f"显函数: $y = {self.get_function_label(func_str)}$",) self.canvas.draw()except Exception as e: messagebox.showerror("错误",f"绘制显函数时出错: {str(e)}")defplot_implicit(self):"""绘制用户输入的隐函数(修复网格点数不匹配问题)"""try: eq_str = self.implicit_entry.get().strip() x_range_str = self.implicit_x_range_entry.get().strip() y_range_str = self.implicit_y_range_entry.get().strip()ifnot eq_str ornot x_range_str ornot y_range_str:raise ValueError("请输入完整的方程表达式和范围")# 解析范围 x_min, x_max =map(float, x_range_str.split(",")) y_min, y_max =map(float, y_range_str.split(","))if x_min >= x_max or y_min >= y_max:raise ValueError("范围的最小值必须小于最大值")# 创建向量化的方程函数(直接处理数组输入) eq =lambda X, Y: self.safe_eval(eq_str,{'x': X,'y': Y})# 调用隐函数绘图函数,使用默认分辨率500(与函数内部一致) self.plot_implicit_equation( eq=eq, x_range=(x_min, x_max), y_range=(y_min, y_max), title=f"隐函数: ${self.get_function_label(eq_str)} = 0$",) self.canvas.draw()except Exception as e: messagebox.showerror("错误",f"绘制隐函数时出错: {str(e)}")except Exception as e: messagebox.showerror("错误",f"绘制隐函数时出错: {str(e)}")defplot_explicit_function(self, f, x_range=(-5,5), title="显函数图像"):""" 绘制显函数 y = f(x) 的图像 参数: f: 函数对象 x_range: x轴范围 title: 图像标题 """ self.fig.clear() ax = self.fig.add_subplot(111)# 设置背景为白色 ax.set_facecolor("white") self.fig.set_facecolor("white")# 创建网格和样式 ax.grid(True, linestyle="--", alpha=0.6) ax.spines["left"].set_position("zero") ax.spines["bottom"].set_position("zero") ax.spines["right"].set_visible(False) ax.spines["top"].set_visible(False)# 生成数据 x = np.linspace(x_range[0], x_range[1],1000)try: y = f(x)except Exception as e: messagebox.showerror("函数错误",f"计算函数值时出错: {str(e)}")return# 绘制函数曲线 ax.plot(x, y,"b-", linewidth=2.5)# 设置标题和标签 ax.set_title(title, fontsize=16, pad=20) ax.set_xlabel("x", fontsize=12, labelpad=-10, x=1.02) ax.set_ylabel("y", fontsize=12, labelpad=-20, y=1.02, rotation=0)# 优化坐标轴刻度 self.optimize_ticks(ax, x_range,(np.min(y), np.max(y))) self.fig.tight_layout()defplot_implicit_equation( self, eq, x_range=(-3,3), y_range=(-3,3), resolution=500, levels=[0], cmap="viridis", title="隐函数图像",):""" 绘制隐函数 F(x, y) = 0 的图像 参数: eq: 函数对象 x_range, y_range: 绘图范围 resolution: 网格分辨率 levels: 绘制等高线的值 cmap: 颜色映射 title: 图像标题 """ self.fig.clear() ax = self.fig.add_subplot(111)# 设置背景为白色 ax.set_facecolor("white") self.fig.set_facecolor("white")# 创建网格 x = np.linspace(x_range[0], x_range[1], resolution) y = np.linspace(y_range[0], y_range[1], resolution) X, Y = np.meshgrid(x, y)# 计算方程值try: Z = eq(X, Y)except Exception as e: messagebox.showerror("方程错误",f"计算方程值时出错: {str(e)}")return# 绘制等高线 (隐函数曲线) contour = ax.contour(X, Y, Z, levels=levels, colors="red", linewidths=2.5)# 添加填充色显示方程值的变化 (只在需要时)iflen(levels)>1: ax.contourf( X, Y, Z, levels=np.linspace(Z.min(), Z.max(),100), cmap=cmap, alpha=0.6)# 添加颜色条 cbar = self.fig.colorbar(contour) cbar.set_label("F(x, y)", rotation=270, labelpad=20)# 设置网格和样式 ax.grid(True, linestyle="--", alpha=0.4) ax.set_aspect("equal")# 设置标题和标签 ax.set_title(title, fontsize=16, pad=20) ax.set_xlabel("x", fontsize=12) ax.set_ylabel("y", fontsize=12)# 添加零线 ax.axhline(0, color="black", linewidth=0.8, alpha=0.7) ax.axvline(0, color="black", linewidth=0.8, alpha=0.7)# 优化坐标轴刻度 self.optimize_ticks(ax, x_range, y_range) self.fig.tight_layout()defoptimize_ticks(self, ax, x_range, y_range):"""优化坐标轴刻度,避免刻度过于密集""" x_min, x_max = x_range y_min, y_max = y_range # 根据数据范围自动设置刻度 x_span = x_max - x_min y_span = y_max - y_min # 设置合理的刻度间隔 x_major_locator = ticker.MaxNLocator(nbins=7) y_major_locator = ticker.MaxNLocator(nbins=7) ax.xaxis.set_major_locator(x_major_locator) ax.yaxis.set_major_locator(y_major_locator)defplot_heart_curve(self):"""绘制心形线""" self.fig.clear()# 创建图像和子图 ax1 = self.fig.add_subplot(111) ax1.set_aspect("equal") ax1.set_title("心形线: $(x^2+y^2-1)^3 - x^2y^3 = 0$", fontsize=14)# 设置背景为白色 ax1.set_facecolor("white") self.fig.set_facecolor("white")# 定义心形线方程defheart_eq(x, y):return(x**2+ y**2-1)**3- x**2* y**3# 生成网格 x = np.linspace(-1.5,1.5,500) y = np.linspace(-1.5,1.5,500) X, Y = np.meshgrid(x, y) Z = heart_eq(X, Y)# 绘制心形线 contour = ax1.contour(X, Y, Z, levels=[0], colors="red", linewidths=3)# 填充颜色 ax1.contourf(X, Y, Z, levels=[-1000,0], colors=["pink"], alpha=0.4)# 添加网格和样式 ax1.grid(True, linestyle="--", alpha=0.3) ax1.set_xlim(-1.5,1.5) ax1.set_ylim(-1.5,1.5)# 优化坐标轴刻度 self.optimize_ticks(ax1,(-1.5,1.5),(-1.5,1.5)) self.fig.tight_layout() self.canvas.draw()defplot_electric_potential(self):"""可视化点电荷系统的电势分布""" self.fig.clear() ax = self.fig.add_subplot(111)# 设置背景为白色 ax.set_facecolor("white") self.fig.set_facecolor("white")# 定义两个点电荷的位置和电荷量 charges =[{"x":-1,"y":0,"q":1},# 正电荷{"x":1,"y":0,"q":-1},# 负电荷]# 创建网格 x = np.linspace(-2.5,2.5,500) y = np.linspace(-2,2,500) X, Y = np.meshgrid(x, y)# 计算电势 (k=1) V = np.zeros_like(X)for charge in charges: r = np.sqrt((X - charge["x"])**2+(Y - charge["y"])**2) V += charge["q"]/ r # 避免除以零 V = np.nan_to_num(V, posinf=10, neginf=-10)# 绘制电势等高线 (使用contourf创建填充等高线) levels = np.linspace(-10,10,21) contourf = ax.contourf(X, Y, V, levels=levels, cmap="coolwarm", alpha=0.8) contour = ax.contour(X, Y, V, levels=levels, colors="k", linewidths=0.5) ax.clabel(contour, inline=True, fontsize=8)# 绘制电荷位置for charge in charges: color ="red"if charge["q"]>0else"blue" marker ="+"if charge["q"]>0else"_" ax.scatter( charge["x"], charge["y"], s=300, c=color, marker=marker, linewidths=2) ax.text( charge["x"], charge["y"]+0.2,f"{charge['q']}q", ha="center", fontsize=12, weight="bold",)# 设置标题和标签 ax.set_title("两个点电荷的电势分布", fontsize=16, pad=20) ax.set_xlabel("x (m)", fontsize=12) ax.set_ylabel("y (m)", fontsize=12)# 添加网格和样式 ax.set_aspect("equal") ax.grid(True, linestyle="--", alpha=0.4)# 添加坐标轴 ax.axhline(0, color="k", linewidth=0.8, alpha=0.7) ax.axvline(0, color="k", linewidth=0.8, alpha=0.7)# 添加物理公式 ax.text(1.5,1.8,r"$V = \sum \frac{kq_i}{r_i}$", fontsize=14, bbox=dict(facecolor="white", alpha=0.8),)# 添加颜色条 cbar = self.fig.colorbar(contourf, label="电势 (V)")# 优化坐标轴刻度 self.optimize_ticks(ax,(-2.5,2.5),(-2,2)) self.fig.tight_layout() self.canvas.draw()defget_function_label(self, func_str):"""生成函数的LaTeX标签"""# 安全检查,防止恶意代码ifany( word in func_str.lower()for word in["import","os","sys","subprocess"]):raise ValueError("检测到不安全的代码")# 直接使用原始字符串,不再进行转义 safe_str = func_str # 替换常见的数学函数 replacements ={r'np\.sin\(([^)]+)\)':r'\sin(\1)',r'np\.cos\(([^)]+)\)':r'\cos(\1)',r'np\.tan\(([^)]+)\)':r'\tan(\1)',r'np\.exp\(([^)]+)\)':r'\exp(\1)',r'np\.sqrt\(([^)]+)\)':r'\sqrt{\1}',r'np\.log\(([^)]+)\)':r'\ln(\1)',r'np\.pi':r'\pi',r'\*\*':r'^',r'\*':r'\cdot',}# 应用所有替换,捕获可能的正则表达式错误for pattern, replacement in replacements.items():try: safe_str = re.sub(pattern, replacement, safe_str)except re.error as e:continue# 跳过有问题的替换# 处理分数 - 更稳健的方法if'/'in safe_str:# 只替换不包含字母的分数表达式if re.search(r'\d+\.?\d*/\d+\.?\d*', safe_str): parts = safe_str.split('/')iflen(parts)==2: numerator = parts[0].strip() denominator = parts[1].strip() safe_str =r'\frac{'+ numerator +'}{'+ denominator +'}'return safe_str defsave_image(self):"""保存当前图像"""try: filename = simpledialog.askstring("保存图像","请输入文件名:", initialvalue="function_plot.png")if filename:ifnot filename.endswith(".png"): filename +=".png" self.fig.savefig(filename, dpi=150, bbox_inches="tight") messagebox.showinfo("成功",f"图像已保存至: {os.path.abspath(filename)}")except Exception as e: messagebox.showerror("保存错误",f"保存图像时出错: {e}")defmain(): root = tk.Tk()# 设置样式 style = ttk.Style() style.configure("TFrame", background="#f5f5f5") style.configure("TLabelframe", background="#ffffff", relief="sunken") style.configure("TLabelframe.Label", background="#ffffff", font=("SimHei",10,"bold")) style.configure("TButton", padding=5)# 尝试设置中文字体try: plt.rcParams["font.family"]=["SimHei"]except:try: plt.rcParams["font.family"]=["WenQuanYi Micro Hei"]except:try: plt.rcParams["font.family"]=["Heiti TC"]except:try: plt.rcParams["font.family"]=["Arial Unicode MS"]except: plt.rcParams["font.family"]=["DejaVu Sans","sans-serif"]print("警告: 未找到中文字体,图表文字可能无法正确显示") app = FunctionVisualizer(root) root.mainloop()if __name__ =="__main__": main()

Read more

解锁DeepSeek潜能:Docker+Ollama打造本地大模型部署新范式

解锁DeepSeek潜能:Docker+Ollama打造本地大模型部署新范式

🐇明明跟你说过:个人主页 🏅个人专栏:《深度探秘:AI界的007》 🏅 🔖行路有良友,便是天堂🔖 目录 一、引言 1、什么是Docker 2、什么是Ollama 二、准备工作 1、操作系统 2、镜像准备 三、安装 1、安装Docker 2、启动Ollama 3、拉取Deepseek大模型 4、启动Deepseek  一、引言 1、什么是Docker Docker:就像一个“打包好的App” 想象一下,你写了一个很棒的程序,在自己的电脑上运行得很好。但当你把它发给别人,可能会遇到各种问题: * “这个软件需要 Python 3.8,但我只有 Python 3.6!

By Ne0inhk
深挖 DeepSeek 隐藏玩法·智能炼金术2.0版本

深挖 DeepSeek 隐藏玩法·智能炼金术2.0版本

前引:屏幕前的你还在AI智能搜索框这样搜索吗?“这道题怎么写”“苹果为什么红”“怎么不被发现翘课” ,。看到此篇文章的小伙伴们!请准备好你的思维魔杖,开启【霍格沃茨模式】,看我如何更新秘密的【知识炼金术】,我们一起来解锁更加刺激的剧情!友情提醒:《《《前方高能》》》 目录 在哪使用DeepSeek 如何对提需求  隐藏玩法总结 几个高阶提示词 职场打工人 自媒体创作 电商实战 程序员开挂 非适用场地 “服务器繁忙”如何解决 (1)硅基流动平台 (2)Chatbox + API集成方案 (3)各大云平台 搭建个人知识库 前置准备 下载安装AnythingLLM 选择DeepSeek作为AI提供商 创作工作区 导入文档 编辑  编辑 小编寄语 ——————————————————————————————————————————— 在哪使用DeepSeek 我们解锁剧情前,肯定要知道在哪用DeepSeek!咯,为了照顾一些萌新朋友,它的下载方式我放在下面了,拿走不谢!  (1)

By Ne0inhk
【AI大模型】DeepSeek + 通义万相高效制作AI视频实战详解

【AI大模型】DeepSeek + 通义万相高效制作AI视频实战详解

目录 一、前言 二、AI视频概述 2.1 什么是AI视频 2.2 AI视频核心特点 2.3 AI视频应用场景 三、通义万相介绍 3.1 通义万相概述 3.1.1 什么是通义万相 3.2 通义万相核心特点 3.3 通义万相技术特点 3.4 通义万相应用场景 四、DeepSeek + 通义万相制作AI视频流程 4.1 DeepSeek + 通义万相制作视频优势 4.1.1 DeepSeek 优势 4.1.2 通义万相视频生成优势 4.2

By Ne0inhk
【DeepSeek微调实践】DeepSeek-R1大模型基于MS-Swift框架部署/推理/微调实践大全

【DeepSeek微调实践】DeepSeek-R1大模型基于MS-Swift框架部署/推理/微调实践大全

系列篇章💥 No.文章01【DeepSeek应用实践】DeepSeek接入Word、WPS方法详解:无需代码,轻松实现智能办公助手功能02【DeepSeek应用实践】通义灵码 + DeepSeek:AI 编程助手的实战指南03【DeepSeek应用实践】Cline集成DeepSeek:开源AI编程助手,终端与Web开发的超强助力04【DeepSeek开发入门】DeepSeek API 开发初体验05【DeepSeek开发入门】DeepSeek API高级开发指南(推理与多轮对话机器人实践)06【DeepSeek开发入门】Function Calling 函数功能应用实战指南07【DeepSeek部署实战】DeepSeek-R1-Distill-Qwen-7B:本地部署与API服务快速上手08【DeepSeek部署实战】DeepSeek-R1-Distill-Qwen-7B:Web聊天机器人部署指南09【DeepSeek部署实战】DeepSeek-R1-Distill-Qwen-7B:基于vLLM 搭建高性能推理服务器10【DeepSeek部署实战】基于Ollama快速部署Dee

By Ne0inhk