痛点还原:手动推导
2026/6/26 1:13:08 网站建设 项目流程

假设我们要展示从 (x+2)(x−3) 展开到 x2−x−6 的过程。

传统做法会这样写:

# 原始因式 expr_origin = MathTex("(x + 2)(x - 3)") # 手动计算中间步骤(心算 or 草稿纸) # ... ... # 合并同类项 expr_result = MathTex("x^2 - x - 6") # 然后动画切换切换... self.play(Transform(expr_origin, expr_result))

问题显而易见:

  • 容易算错(特别是系数复杂时)
  • 无法自动化(换个新公式就得重写代码)
  • 缺乏动态生成的灵活性

我们真正需要的是一个能自动处理代数变形,并且把结果无缝喂给Manim的管道。

2. SymPy 登场:代数变形的“发动机”

SymPy 是Python的符号计算库,简单说就是能让计算机帮你推导数学公式

核心武器:expand()factor()

from sympy import symbols, expand, factor, latex x = symbols("x") # 原始表达式:因式形式 expr_factored = (x + 2) * (x - 3) # 一键展开! expr_expanded = expand(expr_factored) print(expr_expanded) # 输出:x**2 - x - 6 # 再一键因式分解! expr_back = factor(expr_expanded) print(expr_back) # 输出:(x - 3)*(x + 2)

expand()方法可以帮助我们将因式展开;

factor()方法则是分解因式。

SymPy不仅能返回计算结果,还能生成LaTeX 字符串,这正是Manim渲染公式需要的格式:

from sympy import latex latex_code = latex(expr_expanded) print(latex_code) # 输出:x^{2} - x - 6

有了这个“发动机”,我们只需要告诉 SymPy 起点和终点,中间的所有代数变形它都能自动计算。

3. Manim 联动实战:让公式自动推导

下面通过一个曲线绘制的示例来演示SymPy如何让Manim动画更加简单。

为了能够绘制曲线的方法能够通用,我们封装几个函数:

from sympy import symbols, sympify, solve, Eq, latex, lambdify def plot_function_curve(axes, equation_str, x_range, plot_range): """ 绘制函数曲线 Args: axes: 坐标系对象 equation_str: 方程字符串,如 "x**2 - x - 6" x_range: 绘图 x 范围,如 [-3.5, 4.5] plot_range: 用于 sympy 求解的 x 范围 Returns: graph: 曲线对象 graph_label: 曲线标签 """ x = symbols("x") expr = sympify(equation_str) # 创建可调用函数 f = lambdify(x, expr, modules="numpy") # 绘制曲线 graph = axes.plot(f, x_range=x_range, color=YELLOW, stroke_width=3) # 创建标签 graph_label = axes.get_graph_label( graph, label=f"f(x)={latex(expr)}", x_val=x_range[1], direction=UP * 3 ) return graph, graph_label def find_roots(equation_str): """ 使用 SymPy 求解方程的根 Args: equation_str: 方程字符串,如 "x**2 - x - 6" Returns: roots: 实数根列表 """ x = symbols("x") expr = sympify(equation_str) # 求解方程 f(x) = 0 solutions = solve(Eq(expr, 0), x) # 只保留实数根 roots = [] for sol in solutions: if sol.is_real: roots.append(float(sol)) return roots def create_root_markers(axes, roots): """ 创建零点标记和标签 Args: axes: 坐标系对象 roots: 根的列表 Returns: root_dots: 零点标记组 root_labels: 零点标签组 """ root_dots = VGroup() root_labels = VGroup() for rx in roots: # 在零点处画点 dot = Dot(axes.c2p(rx, 0), color=RED, radius=0.1) # 添加坐标标签 label = MathTex(f"({rx}, 0)", font_size=30, color=RED).next_to(dot, UP * 0.5) root_dots.add(dot) root_labels.add(label) return root_dots, root_labels

其中:

  1. plot_function_curve:根据曲线方程的字符串(比如"x**2 - x - 6")来绘制曲线
  2. find_roots:求解曲线方程的根,也就是和曲线和 X 轴的交点
  3. create_root_markers:把曲线方程的根标记出来

有了上面封装的函数,绘制一个曲线的动画代码就非常简洁了。

class PlotQuadraticFunction(Scene): def construct(self): # 1. 创建坐标系 axes = Axes( x_range=[-4, 5, 1], # x 轴范围:-4 到 5,步长 1 y_range=[-8, 10, 2], # y 轴范围:-8 到 10,步长 2 x_length=8, y_length=6, axis_config={"color": BLUE, "include_numbers": True, "font_size": 24}, x_axis_config={"numbers_to_include": range(-4, 6)}, y_axis_config={"numbers_to_include": range(-8, 11, 2)}, ) axes_labels = axes.get_axis_labels(x_label="x", y_label="f(x)") # 定义方程 equation = "x**2 - x - 6" # 绘制函数图像 graph, graph_label = plot_function_curve( axes, equation, x_range=[-3.5, 4.5], plot_range=[-4, 5] ) # 使用 SymPy 求解零点 roots = find_roots(equation) # 创建零点标记 root_dots, root_labels = create_root_markers(axes, roots) # 动画展示 self.play(Create(axes), Write(axes_labels)) self.wait() self.play(Create(graph), Write(graph_label)) self.wait() self.play( LaggedStart( *[Create(dot) for dot in root_dots], *[Write(label) for label in root_labels], lag_ratio=0.3, ) ) self.wait()

上面的代码看着长,其实关键的就一行:equation = "x**2 - x - 6"

其他部分都是渲染坐标系,创建各种元素的动画等等。

生成的效果如下:

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询