首页 > 教程 > manim边学边做--MathTex

manim边学边做--MathTex

时间:2024-06-28 | 来源: | 阅读:141

话题: T

上一篇介绍的SingleStringMathTex主要用来显示只有一行的数学公式,对于复杂的数学公式,可以使用MathTex类。 MathTex类继承自SingleStringMathTex,在其基础之上增加了更多的功能。其实,MathTex是制作数学动画时常用的类,反而SingleStringMa

上一篇介绍的 SingleStringMathTex 主要用来显示只有一行的数学公式,
对于复杂的数学公式,可以使用 MathTex 类。

MathTex 类继承自 SingleStringMathTex ,在其基础之上增加了更多的功能。
其实, MathTex 是制作数学动画时常用的类,反而 SingleStringMathTex 用的不多。

MathTex manim 各个模块中的位置大致如上图中所示。

1. 主要参数

MathTex 的主要参数有:

参数名称 类型 说明
tex_strings list 多个latex格式的公式
arg_separator string 多个公式之间的间隔
substrings_to_isolate list 将公式中分离成一个个小部分
tex_to_color_map dict 公式中不同部分的颜色设置
tex_environment str 不熟悉latex的话不要设置

2. 主要方法

MathTex 继承了 SingleStringMathTex 之后,扩展了不少新的方法,可以更好的控制和展示数学公式。

名称 说明
get_part_by_tex 获取 latex公式 中的一部分
get_parts_by_tex 获取 latex公式 中的多个部分
index_of_part 公式的某部分在整个公式中的索引
index_of_part_by_tex 某个tex string在整个公式中的索引
set_color_by_tex 根据某个 tex string 设置颜色
set_color_by_tex_to_color_map 用字典的形式设置多个 tex string 的颜色
set_opacity_by_tex 根据某个 tex string 设置透明度
sort_alphabetically 按字母顺序排列 latex公式 中的各个部分

MathTex 的大部分方法都要配合 substrings_to_isolate 参数来一起使用,
通过 substrings_to_isolate 将完整的数学公式划分成一个个小部分,然后设置不同的样式。

3. 使用示例

下面的使用示例,大部分是结合 参数 方法 一起使用的。

3.1. 公式之间的间隔

MathTex 支持输入多个公式,多个公式之间默认是空格分隔,可以通过 arg_separator 参数设置不同的分隔。

tex = MathTex("z", "=", 
              "\sqrt{x^2+y^2}")
tex = MathTex("z", "=", 
              "\sqrt{x^2+y^2}", 
              arg_separator="\quad")

\quad 表示设置4个空格。

3.2. 拆分公式

拆分公式非常有用,拆分之后,可以对公式的一部分进行操作.
比如设置颜色,透明度,甚至可以在公式的不同部分应用不同的动画,做出更酷炫的展现形式。

默认情况下,公式是一个整体,哪怕用公式中的一个字符去获取,也会得到整个公式。

tex = MathTex("z=\sqrt{x^2+y^2}")
print(f"{len(tex) =}")
## 输出结果:
# len(tex) =1

part = tex.get_part_by_tex("x")
print(f"{part = }")
## 输出结果:
# part = SingleStringMathTex('z=\\sqrt{x^2+y^2}')

所以,先使用 substrings_to_isolate 参数拆分公式,
然后就可以使用 get_part_by_tex get_parts_by_tex 这些函数来获取公式的不同部分。

tex = MathTex("y=ax^2+bx+c", 
              substrings_to_isolate=["x", "y"])
print(f"{len(tex) =}")
## 输出结果:
# len(tex) =6

part = tex.get_part_by_tex("y")
print(f"{part = }")
## 输出结果:
# part = SingleStringMathTex('y')

parts = tex.get_parts_by_tex("x")
print(f"{parts = }")
## 输出结果:
# parts = VGroup(SingleStringMathTex('x'), 
#                SingleStringMathTex('x'))

从上面的示例中看出,对于公式 \(y=ax^2+bx+c\) ,按 \(x,y\) 分割之后,
整个公式被分成了6份,所以 len(tex)=6 ,分成了:

  1. \(y\)
  2. \(=a\)
  3. \(x\)
  4. \(^2+b\)
  5. \(x\)
  6. \(+c\)

也就是说, substrings_to_isolate 中指定的 \(x,y\) 作为了整个公式的分割点。

tex.get_part_by_tex("y") 得到的是包含 \(y\) 的那部分公式,因为 \(y\) substrings_to_isolate 中,
所以上面示例中返回的是 part = SingleStringMathTex('y')
如果是 tex.get_part_by_tex("a") 的话,返回的将是 part = SingleStringMathTex('=a')

上面分成的6个部分中,有两个部分包含 \(x\)
所以 parts = tex.get_parts_by_tex("x") 返回的 VGroup 包含两个元素。

通过 index_of_part index_of_part_by_tex 可以根据索引来获取公式被分割的各个部分。

tex = MathTex("y=ax^2+bx+c", 
              substrings_to_isolate=["x", "y"])

part = tex.get_part_by_tex("b")
print(tex.index_of_part(part))
## 输出结果
# 3

print(tex.index_of_part_by_tex("b"))
## 输出结果
# 3

在分成的6个部分中, \(b\) 所在的部分是 第4个 index 是从 0 开始的,所以示例中输出结果为 3

之所以要拆分公式,就是为了对不同的部分进行不同的操作,下面的示例样式拆分之后带来的应用。

3.3. 公式着色

使用拆分前,虽然也可以通过 color 属性给公式着色,但是只能给整个公式设置一个颜色:

tex = MathTex(
    "z=\sqrt{x^2+y^2}",
    color=RED,
)

拆分之后,可以通过 set_color_by_tex 给不同的部分设置不同的颜色:

tex = MathTex("z", "=", "\sqrt{x^2+y^2}", 
              substrings_to_isolate=["x", "y", "z"])
tex.set_color_by_tex("x", RED)
tex.set_color_by_tex("y", GREEN)
tex.set_color_by_tex("z", BLUE)

同时设置多个颜色,也可以用 set_color_by_tex_to_color_map 方法:

tex.set_color_by_tex_to_color_map({
    "x": BLUE, "y": RED, "z": GREEN
})

上面三种方式着色后的效果如下:

3.4. 透明度设置

除了颜色,拆分之后,也可以给不同的部分设置透明度。

tex = MathTex(
    "z",
    "=",
    "\sqrt{x^2+y^2}",
    substrings_to_isolate=["x", "y", "z"],
)
tex.set_opacity_by_tex("x", 0.4)
tex.set_opacity_by_tex("y", 0.4)
tex.set_opacity_by_tex("z", 0.6)
tex.set_color_by_tex_to_color_map({
    "x": BLUE, "y": RED, "z": GREEN
})

\(x,y,z\) 方别设置的不同的透明度和颜色,和未设置透明度时的对比如下:

3.5. 排序

最后这个是排序功能,是将数学公式的各个部分按照 ASCII 码的顺序排序。
比如,排序前(正常的公式从左到右的顺序排列各个部分):

tex = MathTex("c>a>b", 
              substrings_to_isolate=["a", "b", "c"])

for i in range(len(tex)):
    print(tex[i])

## 输出结果:
# SingleStringMathTex('c')
# SingleStringMathTex('>')
# SingleStringMathTex('a')
# SingleStringMathTex('>')
# SingleStringMathTex('b')

排序后:

tex.sort_alphabetically()
for i in range(len(tex)):
    print(tex[i])

## 输出结果:
# SingleStringMathTex('>')
# SingleStringMathTex('>')
# SingleStringMathTex('a')
# SingleStringMathTex('b')
# SingleStringMathTex('c')

按照 ASCII 码的顺序重新排列了各个部分。

这样排列有什么用呢?通过动画来显示公式时,渲染的顺序不一样。
排序前,从左到右一次显示 c, >, a, >, b
排序后,显示顺序为变为 >, >, a, b, c

4. 附件

文中完整的代码放在网盘中了( math_tex.py ),
下载地址: 完整代码 (访问密码: 6872)


湘ICP备2022002427号-10湘公网安备:43070202000427号
© 2013~2019 haote.com 好特网