做 Manim 动画时,我想让抛物线 $ y=x^2+bx+2 $随着系数 b 的变革,自动、精准地表现它与 x 轴的交点。
手写求根公式不但繁琐,还要本身处理处罚鉴别式为负的环境,稍不留意 math.sqrt 就会让整个动画瓦解。
本文我们就用 SymPy 彻底办理这个痛点。
1. 痛点场景还原
假设我要做一个演示:固定 a=1, c=2,让 b 从 -3 滑到 3,观察抛物线与 x 轴交点个数的变革。
如果纯手算,我大概会如许写 Manim 代码:- from manim import *
- import math
- class PainfulDemo(Scene):
- def construct(self):
- a, c = 1, 2
- b_tracker = ValueTracker(-3)
- axes = Axes(x_range=[-5,5], y_range=[-1,6])
- # 抛物线
- graph = always_redraw(lambda: axes.plot(
- lambda x: a*x**2 + b_tracker.get_value()*x + c
- ))
- # 计算交点 —— 这里就是噩梦开始的地方
- def get_roots():
- b = b_tracker.get_value()
- disc = b**2 - 4*a*c
- if disc >= 0:
- root1 = (-b + math.sqrt(disc)) / (2*a) # 负数平方根直接报错
- root2 = (-b - math.sqrt(disc)) / (2*a)
- return [root1, root2]
- else:
- return [] # 如果忘了判断,上面一行就炸了
- dots = always_redraw(lambda: VGroup(*[
- Dot(axes.coords_to_point(r, 0)) for r in get_roots()
- ]))
- self.add(axes, graph, dots)
- self.play(b_tracker.animate.set_value(3), run_time=5)
- self.wait(1)
复制代码
- 我必须手动写出求根公式,反复查抄符号。
- 鉴别式 0 \(两个交点,\) \Delta=0 \(一个交点,\) \Delta0 $,抛物线与 x 轴有两个赤色交点。
- 当 b 颠末 $ -\sqrt{8} \approx -2.828 \(时,两交点靠拢,**重合为一个点**(\) \Delta=0 $),此时左上角表现「交点个数:1」。
- 紧接着 $ \Delta $变成负数,全部红点消散,抛物线悬浮在x 轴上方,与 x 轴无交点。
- 当 b 凌驾 $ \sqrt{8} $时,两点再次出现并徐徐阔别。
整个过程,黄色顶点不绝精准地落在抛物线最低点,随 b 移动而滑动。
左上角的 $ \Delta $ 数值和交点个数同步革新,完全不须要手动干预。
</ul>5. 小结
SymPy 在 Manim 动画里的脚色很纯粹:把数学盘算还给盘算机,把视觉表达留给你。
手算求根公式、判定鉴别式、求导数零点……这些重复且易错的体力活,SymPy 一句 solve、一句 diff 就能完善代庖。
动画代码的逻辑因此变得清楚——你只负责告诉 Manim “什么东西应该画在什么位置”,而“位置怎么算”就让 SymPy 这个符号大脑去完成。
免责声明:如果侵犯了您的权益,请联系站长及时删除侵权内容,谢谢合作!qidao123.com:ToB企服之家,中国第一个企服评测及软件市场,开放入驻,技术点评得现金. |