manim-mindmap 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,326 @@
1
+ Metadata-Version: 2.4
2
+ Name: manim-mindmap
3
+ Version: 0.1.0
4
+ Summary: A mind map plugin for manim
5
+ License-Expression: MIT
6
+ Author: jj-math
7
+ Author-email: liwei.0028@163.com
8
+ Requires-Python: >=3.12
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Programming Language :: Python :: 3.12
11
+ Classifier: Programming Language :: Python :: 3.13
12
+ Classifier: Programming Language :: Python :: 3.14
13
+ Requires-Dist: manim (>=0.18.0)
14
+ Project-URL: Bug Tracker, https://github.com/jj-math/manim-mindmap/issues
15
+ Project-URL: Documentation, https://github.com/jj-math/manim-mindmap#readme
16
+ Project-URL: Homepage, https://github.com/jj-math/manim-mindmap
17
+ Project-URL: Repository, https://github.com/jj-math/manim-mindmap
18
+ Description-Content-Type: text/markdown
19
+
20
+ # Manim 思维导图插件
21
+
22
+ ## 简介
23
+
24
+ Manim 作为一个优秀的动画引擎,始终缺少思维导图的支持,这便是该项目的初衷。
25
+
26
+ 我自己作为一个数学内容的创作者(B站博主“**究尽数学**”)和 Manim 的使用者,深知内容创作本身就是需要花费心思、精心打磨的。为了让其他创作者更好的专注于内容,特意开源思维导图插件。希望大家积极使用和优化项目。
27
+
28
+ 作为第一款思维导图插件(截至项目提交,没有找到同类 Manim 插件),开发经历了大概三个阶段。
29
+
30
+ ### 第一版:简单递归
31
+
32
+ 后序遍历:将同级的兄弟节点,放在Group容器中,通过Group的arrange方法排列、对齐;然后将这些兄弟节点的父节点,放在它们的前(上)面,并居中;再将父节点与它的子节点作为一个整体,视为一个新的节点,与其他兄弟节点重复前面的操作,直至排到根节点,结束递归,完成布局。
33
+
34
+ 该实现简单粗暴,但布局方法和Group中对象*高度耦合*,丧失了灵活性,严重限制了动画的实现。
35
+
36
+ ### 第二版:Reingold-Tilford算法
37
+
38
+ 在使用了第一个版本一段时间之后,为了**更丰富、更灵活**的动画效果,查找了关于‘树的布局算法’。最先进入视野的是Reingold和Tilford的算法,算法提出了5个布局原则,一定程度上,第一版采用的就是该算法。但是具体实现是通过节点类,该类记录节点的尺寸,当前节点相对于父节点的位置(priem),以及以当前节点为根的子树的偏移量(mod)。然后通过两次遍历,完成树的布局。第一次后序遍历:计算节点的位置priem和mod,而且要消除子树间发遮挡;第二次前序遍历:第一次遍历的过程中,只是计算,并不真实的应用于作为节点的VMobject对像,最终的位置确定,在此完成。
39
+
40
+ 基于该算法,实现了节点类,也因此实现了低耦合,丰富了动画效果。但是,我在代码实现中,为避免子树的遮挡,将子树包在一个框中作为一个整体,然后与左邻居作碰撞检测,进行分离。实现虽然简单,但不会满足紧致的布局原则。这是我留下的一个坑,也是一个心病。
41
+
42
+ ### 第三版:Walker算法及其改进
43
+
44
+ 为了提高Reingold-Tilford算法中子树碰撞检测的效率,Walker改进了算法,又有人改进了Walker的算法,其具体的算法,可参考论文:《Improving Walker's Algorithm to Run in Linear Time》。
45
+
46
+ 这次的实现,严格参考了论文的算法:虽然在Manim动画中,限于屏幕的大小,一般思维导图节点不会太多,子树遮挡的性能提升其实影响不大;除了提高算法效率,更主要的是布局紧密;而且布局算法和作为节点内容的VMobject是完全分离的,如果对我动画部分的实现不满意,完全可以基于布局算法,开发自己的动画(就问你够不够灵活)。
47
+
48
+ ## 使用方法
49
+
50
+ 我开源的就是最好的第三版,用法也是关于第三版的。通过 pip 进行安装:
51
+
52
+ `pip install manim-mindmap`
53
+
54
+ 在 Manim 项目中,导入插件:
55
+
56
+ ```python
57
+ from manim-mindmap import *
58
+ ```
59
+
60
+ 导入的类如下:
61
+ + MindMap:一个思维导图类
62
+ + Node:思维导图节点类
63
+ + NodeStyle:思维导图的布局参数类(布局方向、节点的间距、节点的样式等)
64
+ + 动画类:LayoutAnimation
65
+ + RemoveNode:在思维导图中移除节点
66
+ + InsertNode:向思维导图中添加节点
67
+ + ScaleNode:放缩思维导图中的节点
68
+ + AlterNode:替换节点中的内容
69
+
70
+ 具体的使用方法,请参考后续的代码。
71
+
72
+ ### 动画类 InsertNode:插入节点
73
+
74
+ 场景中已经显示一个思维导图,向其中添加一个或多个节点,并呈现添加的动画效果:
75
+
76
+ ```python
77
+ node_style = NodeStyle(direction=DOWN)
78
+
79
+ root = Node(Tex(r'圆周率').to_edge(UP))
80
+ A = Node(Tex(r'圆的面积'))
81
+ B = Node(Tex(r'圆的周长'))
82
+ C = Node(Tex(r'球的\\体积'))
83
+
84
+ D = Node(Tex(r'圆的面积公式'))
85
+ E = Node(Tex(r'圆的周长公式'))
86
+
87
+ F = Node(Tex(r'球的表面积'))
88
+
89
+ G = Node(Tex(r'正方形'))
90
+ H = Node(Tex(r'长方形'))
91
+ self.play(
92
+ InsertNode(self,{root:[A,B,C]},node_style),
93
+ )
94
+ self.wait()
95
+ self.play(
96
+ InsertNode(self,{A:[D,E],B:[F],C:[G,H]},node_style),
97
+ )
98
+ ```
99
+
100
+ 参数说明:父节点作为字典的键,表示被插入的节点;对应的值,为节点列表,表示待插入的节点。
101
+ 需要注意:node_style 作为思维导图全局外观的参数,在修改时也会呈现动画效果。比如节点外框的颜色、连接线的粗细,布局的方向等等
102
+
103
+ ### 动画类 ScaleNode:放缩节点
104
+
105
+ 场景中已经显示一个思维导图,放缩一个或多个节点,并呈现添加的动画效果(思维导图沿用上面示例):
106
+
107
+ ```python
108
+ self.play(
109
+ ScaleNode(self,{C:1.2},node_style),
110
+ )
111
+ ```
112
+
113
+ 参数说明:节点作为被放大、缩小的节点,值对应节点放缩的数值。
114
+
115
+ ### 动画类 AlterNode:修改或替换节点
116
+
117
+ 场景中已经显示一个思维导图,替换节点中的 VMobject ,并呈现添加的动画效果(思维导图沿用上面示例):
118
+
119
+ ```python
120
+ self.play(
121
+ AlterNode(self,{root:Tex(r'圆周率$\pi$')},node_style),
122
+ )
123
+ ```
124
+
125
+ 参数说明:待修改的的节点作为键,替换用的VMobject作为值。
126
+
127
+ ### 动画类 RemoveNode:移除节点
128
+
129
+ 场景中已经显示一个思维导图,移除节点,并呈现添加的动画效果(思维导图沿用上面示例):
130
+
131
+ ```python
132
+ self.play(
133
+ RemoveNode(self,[B,C],node_style),
134
+ )
135
+ self.wait()
136
+
137
+ self.play(
138
+ RemoveNode(self,root,node_style),
139
+ )
140
+ ```
141
+
142
+ 参数说明:待移除的节点可以是一个,也可以是多个。注意,移除一个节点时,意味着移除以该节点为根的子树;所以,如果该节点是根节点,将移除整个思维导图。
143
+
144
+ ### 动画类:LayoutAnimation
145
+
146
+ 动画类RemoveNode、InsertNode、ScaleNode和AlterNode,都继承于LayoutAnimation。这四个动画,如果操作的是同一个思维导图,在一个play中,不能同时使用;如下的使用方式是错的:
147
+
148
+ ```python
149
+ self.play(
150
+ RemoveNode(self,node1),
151
+ InsertNode(self,node2)
152
+ )
153
+ ```
154
+
155
+ 如果需要同时添加和移除等操作,可以使用LayoutAnimation。使用方法如下:
156
+
157
+ ```python
158
+ node_style = NodeStyle(direction=DOWN)
159
+ root = Node(Tex(r'圆周率').to_edge(UP))
160
+ A = Node(Tex(r'圆的面积'))
161
+ B = Node(Tex(r'圆的周长'))
162
+ C = Node(Tex(r'球的\\体积'))
163
+
164
+ D = Node(Tex(r'圆的面积公式'))
165
+ E = Node(Tex(r'圆的周长公式'))
166
+
167
+ F = Node(Tex(r'球的表面积'))
168
+
169
+ root.add_child(A)
170
+ root.add_child(B)
171
+ root.add_child(C)
172
+
173
+ B.add_child(F)
174
+
175
+ C.add_child(D)
176
+ C.add_child(E)
177
+
178
+ self.play(
179
+ LayoutAnimation(self,root,node_style)
180
+ )
181
+ self.wait()
182
+
183
+ G = Node(Tex(r'正方形'))
184
+ H = Node(Tex(r'长方形'))
185
+
186
+ C.add_child(G)
187
+ F.add_child(H)
188
+
189
+ self.play(
190
+ LayoutAnimation(self,root,node_style)
191
+ )
192
+ self.wait()
193
+
194
+ F.scale(1.5)
195
+
196
+ self.play(
197
+ LayoutAnimation(self,root,node_style)
198
+ )
199
+ self.wait()
200
+
201
+ C.remove_child(G)
202
+ root.remove_child(C)
203
+
204
+ self.play(
205
+ LayoutAnimation(self,root,node_style)
206
+ )
207
+ self.wait()
208
+ ```
209
+
210
+ 通过各个节点的`add_child`、`remove_child`、`scale`和`alter_content`方法,实现插入、移除、放缩和修改节点。然后,将根节点传入LayoutAnimation,会将所有的动画效果收集返回。
211
+
212
+ 如果不想通过节点类 Node 组织思维导图,可以考虑 MindMap 类。
213
+
214
+ ### MindMap 类
215
+
216
+ 通过 MindMap 类,解析思维导图结构数据,形成节点的树结构,完成布局,其中“思维导图数据结构”如下:
217
+
218
+ ```python
219
+ mindmap = {
220
+ 'node':r'球体积',
221
+ 'text':'用于TTS讲解的文本',
222
+ 'child':[
223
+ {
224
+ 'node':r'公元前3世纪',#或者为VMobject、Mobject对象
225
+ 'child':[
226
+ {
227
+ 'node':r'阿基米德平衡法',
228
+ }
229
+ ]
230
+ },
231
+ {
232
+ 'node':r'公元3世纪',
233
+ 'child':[
234
+ {
235
+ 'node':r'《九章算术》',
236
+ },
237
+ {
238
+ 'node':r'刘徽:牟合方盖',
239
+ 'child':[
240
+ {
241
+ 'node':r'球与牟合方盖的关系',
242
+ },
243
+ {
244
+ 'node':r'牟合方盖体积?',
245
+ }
246
+ ]
247
+ }
248
+ ]
249
+ },
250
+ {
251
+ 'node':r'公元5世纪',
252
+ 'child':[
253
+ {
254
+ 'node':r'祖暅:开立圆术',
255
+ }
256
+ ]
257
+ },
258
+ {
259
+ 'node':r'公元17世纪',
260
+ 'child':[
261
+ {
262
+ 'node':r'开普勒',
263
+ },
264
+ {
265
+ 'node':r'卡瓦列里原理',
266
+ }
267
+ ]
268
+ },
269
+ {
270
+ 'node':r'公元18世纪',
271
+ 'child':[
272
+ {
273
+ 'node':r'松永良弼:会玉术',
274
+ }
275
+ ]
276
+ }
277
+ ]
278
+ }
279
+ ```
280
+
281
+ 将上面结构的参数 `mindmap` 传给 MindMap 类,然后可以遍历 MindMap 实例的各个节点
282
+
283
+ ```python
284
+ mind = MindMap(mindmap)
285
+ mind.scale_to_fit_width(12)
286
+ for node in mind.dfs_walker():
287
+ if node.connector:
288
+ self.play(
289
+ Create(node.connector),
290
+ run_time = 0.5
291
+ )
292
+ self.play(
293
+ Create(node.surr_rect),
294
+ Write(node.vmobject)
295
+ )
296
+ self.wait()
297
+ ```
298
+
299
+ MindMap 类还实现了子节点,后代节点和子树的方法:
300
+
301
+ ```python
302
+ children = mind.get_children(ID = (0,1))
303
+ self.play(
304
+ *[
305
+ Wiggle(child) for child in children
306
+ ]
307
+ )
308
+ self.wait()
309
+
310
+ descendants = mind.get_descendants(ID = (0,1))
311
+ self.play(
312
+ *[
313
+ Wiggle(descendant) for descendant in descendants
314
+ ]
315
+ )
316
+ ```
317
+
318
+ 其中,参数 ID 是一个元组,对应一个节点:
319
+ + 根节点是:`(0,)`
320
+ + 根节点的第一个、第二个子节点分别是:`(0,0),(0,1)`
321
+
322
+ ## 开发计划
323
+
324
+ + 添加其他的布局算法
325
+ + 时序图
326
+ + 鱼骨图
@@ -0,0 +1,307 @@
1
+ # Manim 思维导图插件
2
+
3
+ ## 简介
4
+
5
+ Manim 作为一个优秀的动画引擎,始终缺少思维导图的支持,这便是该项目的初衷。
6
+
7
+ 我自己作为一个数学内容的创作者(B站博主“**究尽数学**”)和 Manim 的使用者,深知内容创作本身就是需要花费心思、精心打磨的。为了让其他创作者更好的专注于内容,特意开源思维导图插件。希望大家积极使用和优化项目。
8
+
9
+ 作为第一款思维导图插件(截至项目提交,没有找到同类 Manim 插件),开发经历了大概三个阶段。
10
+
11
+ ### 第一版:简单递归
12
+
13
+ 后序遍历:将同级的兄弟节点,放在Group容器中,通过Group的arrange方法排列、对齐;然后将这些兄弟节点的父节点,放在它们的前(上)面,并居中;再将父节点与它的子节点作为一个整体,视为一个新的节点,与其他兄弟节点重复前面的操作,直至排到根节点,结束递归,完成布局。
14
+
15
+ 该实现简单粗暴,但布局方法和Group中对象*高度耦合*,丧失了灵活性,严重限制了动画的实现。
16
+
17
+ ### 第二版:Reingold-Tilford算法
18
+
19
+ 在使用了第一个版本一段时间之后,为了**更丰富、更灵活**的动画效果,查找了关于‘树的布局算法’。最先进入视野的是Reingold和Tilford的算法,算法提出了5个布局原则,一定程度上,第一版采用的就是该算法。但是具体实现是通过节点类,该类记录节点的尺寸,当前节点相对于父节点的位置(priem),以及以当前节点为根的子树的偏移量(mod)。然后通过两次遍历,完成树的布局。第一次后序遍历:计算节点的位置priem和mod,而且要消除子树间发遮挡;第二次前序遍历:第一次遍历的过程中,只是计算,并不真实的应用于作为节点的VMobject对像,最终的位置确定,在此完成。
20
+
21
+ 基于该算法,实现了节点类,也因此实现了低耦合,丰富了动画效果。但是,我在代码实现中,为避免子树的遮挡,将子树包在一个框中作为一个整体,然后与左邻居作碰撞检测,进行分离。实现虽然简单,但不会满足紧致的布局原则。这是我留下的一个坑,也是一个心病。
22
+
23
+ ### 第三版:Walker算法及其改进
24
+
25
+ 为了提高Reingold-Tilford算法中子树碰撞检测的效率,Walker改进了算法,又有人改进了Walker的算法,其具体的算法,可参考论文:《Improving Walker's Algorithm to Run in Linear Time》。
26
+
27
+ 这次的实现,严格参考了论文的算法:虽然在Manim动画中,限于屏幕的大小,一般思维导图节点不会太多,子树遮挡的性能提升其实影响不大;除了提高算法效率,更主要的是布局紧密;而且布局算法和作为节点内容的VMobject是完全分离的,如果对我动画部分的实现不满意,完全可以基于布局算法,开发自己的动画(就问你够不够灵活)。
28
+
29
+ ## 使用方法
30
+
31
+ 我开源的就是最好的第三版,用法也是关于第三版的。通过 pip 进行安装:
32
+
33
+ `pip install manim-mindmap`
34
+
35
+ 在 Manim 项目中,导入插件:
36
+
37
+ ```python
38
+ from manim-mindmap import *
39
+ ```
40
+
41
+ 导入的类如下:
42
+ + MindMap:一个思维导图类
43
+ + Node:思维导图节点类
44
+ + NodeStyle:思维导图的布局参数类(布局方向、节点的间距、节点的样式等)
45
+ + 动画类:LayoutAnimation
46
+ + RemoveNode:在思维导图中移除节点
47
+ + InsertNode:向思维导图中添加节点
48
+ + ScaleNode:放缩思维导图中的节点
49
+ + AlterNode:替换节点中的内容
50
+
51
+ 具体的使用方法,请参考后续的代码。
52
+
53
+ ### 动画类 InsertNode:插入节点
54
+
55
+ 场景中已经显示一个思维导图,向其中添加一个或多个节点,并呈现添加的动画效果:
56
+
57
+ ```python
58
+ node_style = NodeStyle(direction=DOWN)
59
+
60
+ root = Node(Tex(r'圆周率').to_edge(UP))
61
+ A = Node(Tex(r'圆的面积'))
62
+ B = Node(Tex(r'圆的周长'))
63
+ C = Node(Tex(r'球的\\体积'))
64
+
65
+ D = Node(Tex(r'圆的面积公式'))
66
+ E = Node(Tex(r'圆的周长公式'))
67
+
68
+ F = Node(Tex(r'球的表面积'))
69
+
70
+ G = Node(Tex(r'正方形'))
71
+ H = Node(Tex(r'长方形'))
72
+ self.play(
73
+ InsertNode(self,{root:[A,B,C]},node_style),
74
+ )
75
+ self.wait()
76
+ self.play(
77
+ InsertNode(self,{A:[D,E],B:[F],C:[G,H]},node_style),
78
+ )
79
+ ```
80
+
81
+ 参数说明:父节点作为字典的键,表示被插入的节点;对应的值,为节点列表,表示待插入的节点。
82
+ 需要注意:node_style 作为思维导图全局外观的参数,在修改时也会呈现动画效果。比如节点外框的颜色、连接线的粗细,布局的方向等等
83
+
84
+ ### 动画类 ScaleNode:放缩节点
85
+
86
+ 场景中已经显示一个思维导图,放缩一个或多个节点,并呈现添加的动画效果(思维导图沿用上面示例):
87
+
88
+ ```python
89
+ self.play(
90
+ ScaleNode(self,{C:1.2},node_style),
91
+ )
92
+ ```
93
+
94
+ 参数说明:节点作为被放大、缩小的节点,值对应节点放缩的数值。
95
+
96
+ ### 动画类 AlterNode:修改或替换节点
97
+
98
+ 场景中已经显示一个思维导图,替换节点中的 VMobject ,并呈现添加的动画效果(思维导图沿用上面示例):
99
+
100
+ ```python
101
+ self.play(
102
+ AlterNode(self,{root:Tex(r'圆周率$\pi$')},node_style),
103
+ )
104
+ ```
105
+
106
+ 参数说明:待修改的的节点作为键,替换用的VMobject作为值。
107
+
108
+ ### 动画类 RemoveNode:移除节点
109
+
110
+ 场景中已经显示一个思维导图,移除节点,并呈现添加的动画效果(思维导图沿用上面示例):
111
+
112
+ ```python
113
+ self.play(
114
+ RemoveNode(self,[B,C],node_style),
115
+ )
116
+ self.wait()
117
+
118
+ self.play(
119
+ RemoveNode(self,root,node_style),
120
+ )
121
+ ```
122
+
123
+ 参数说明:待移除的节点可以是一个,也可以是多个。注意,移除一个节点时,意味着移除以该节点为根的子树;所以,如果该节点是根节点,将移除整个思维导图。
124
+
125
+ ### 动画类:LayoutAnimation
126
+
127
+ 动画类RemoveNode、InsertNode、ScaleNode和AlterNode,都继承于LayoutAnimation。这四个动画,如果操作的是同一个思维导图,在一个play中,不能同时使用;如下的使用方式是错的:
128
+
129
+ ```python
130
+ self.play(
131
+ RemoveNode(self,node1),
132
+ InsertNode(self,node2)
133
+ )
134
+ ```
135
+
136
+ 如果需要同时添加和移除等操作,可以使用LayoutAnimation。使用方法如下:
137
+
138
+ ```python
139
+ node_style = NodeStyle(direction=DOWN)
140
+ root = Node(Tex(r'圆周率').to_edge(UP))
141
+ A = Node(Tex(r'圆的面积'))
142
+ B = Node(Tex(r'圆的周长'))
143
+ C = Node(Tex(r'球的\\体积'))
144
+
145
+ D = Node(Tex(r'圆的面积公式'))
146
+ E = Node(Tex(r'圆的周长公式'))
147
+
148
+ F = Node(Tex(r'球的表面积'))
149
+
150
+ root.add_child(A)
151
+ root.add_child(B)
152
+ root.add_child(C)
153
+
154
+ B.add_child(F)
155
+
156
+ C.add_child(D)
157
+ C.add_child(E)
158
+
159
+ self.play(
160
+ LayoutAnimation(self,root,node_style)
161
+ )
162
+ self.wait()
163
+
164
+ G = Node(Tex(r'正方形'))
165
+ H = Node(Tex(r'长方形'))
166
+
167
+ C.add_child(G)
168
+ F.add_child(H)
169
+
170
+ self.play(
171
+ LayoutAnimation(self,root,node_style)
172
+ )
173
+ self.wait()
174
+
175
+ F.scale(1.5)
176
+
177
+ self.play(
178
+ LayoutAnimation(self,root,node_style)
179
+ )
180
+ self.wait()
181
+
182
+ C.remove_child(G)
183
+ root.remove_child(C)
184
+
185
+ self.play(
186
+ LayoutAnimation(self,root,node_style)
187
+ )
188
+ self.wait()
189
+ ```
190
+
191
+ 通过各个节点的`add_child`、`remove_child`、`scale`和`alter_content`方法,实现插入、移除、放缩和修改节点。然后,将根节点传入LayoutAnimation,会将所有的动画效果收集返回。
192
+
193
+ 如果不想通过节点类 Node 组织思维导图,可以考虑 MindMap 类。
194
+
195
+ ### MindMap 类
196
+
197
+ 通过 MindMap 类,解析思维导图结构数据,形成节点的树结构,完成布局,其中“思维导图数据结构”如下:
198
+
199
+ ```python
200
+ mindmap = {
201
+ 'node':r'球体积',
202
+ 'text':'用于TTS讲解的文本',
203
+ 'child':[
204
+ {
205
+ 'node':r'公元前3世纪',#或者为VMobject、Mobject对象
206
+ 'child':[
207
+ {
208
+ 'node':r'阿基米德平衡法',
209
+ }
210
+ ]
211
+ },
212
+ {
213
+ 'node':r'公元3世纪',
214
+ 'child':[
215
+ {
216
+ 'node':r'《九章算术》',
217
+ },
218
+ {
219
+ 'node':r'刘徽:牟合方盖',
220
+ 'child':[
221
+ {
222
+ 'node':r'球与牟合方盖的关系',
223
+ },
224
+ {
225
+ 'node':r'牟合方盖体积?',
226
+ }
227
+ ]
228
+ }
229
+ ]
230
+ },
231
+ {
232
+ 'node':r'公元5世纪',
233
+ 'child':[
234
+ {
235
+ 'node':r'祖暅:开立圆术',
236
+ }
237
+ ]
238
+ },
239
+ {
240
+ 'node':r'公元17世纪',
241
+ 'child':[
242
+ {
243
+ 'node':r'开普勒',
244
+ },
245
+ {
246
+ 'node':r'卡瓦列里原理',
247
+ }
248
+ ]
249
+ },
250
+ {
251
+ 'node':r'公元18世纪',
252
+ 'child':[
253
+ {
254
+ 'node':r'松永良弼:会玉术',
255
+ }
256
+ ]
257
+ }
258
+ ]
259
+ }
260
+ ```
261
+
262
+ 将上面结构的参数 `mindmap` 传给 MindMap 类,然后可以遍历 MindMap 实例的各个节点
263
+
264
+ ```python
265
+ mind = MindMap(mindmap)
266
+ mind.scale_to_fit_width(12)
267
+ for node in mind.dfs_walker():
268
+ if node.connector:
269
+ self.play(
270
+ Create(node.connector),
271
+ run_time = 0.5
272
+ )
273
+ self.play(
274
+ Create(node.surr_rect),
275
+ Write(node.vmobject)
276
+ )
277
+ self.wait()
278
+ ```
279
+
280
+ MindMap 类还实现了子节点,后代节点和子树的方法:
281
+
282
+ ```python
283
+ children = mind.get_children(ID = (0,1))
284
+ self.play(
285
+ *[
286
+ Wiggle(child) for child in children
287
+ ]
288
+ )
289
+ self.wait()
290
+
291
+ descendants = mind.get_descendants(ID = (0,1))
292
+ self.play(
293
+ *[
294
+ Wiggle(descendant) for descendant in descendants
295
+ ]
296
+ )
297
+ ```
298
+
299
+ 其中,参数 ID 是一个元组,对应一个节点:
300
+ + 根节点是:`(0,)`
301
+ + 根节点的第一个、第二个子节点分别是:`(0,0),(0,1)`
302
+
303
+ ## 开发计划
304
+
305
+ + 添加其他的布局算法
306
+ + 时序图
307
+ + 鱼骨图
@@ -0,0 +1,31 @@
1
+ [project]
2
+ name = "manim-mindmap"
3
+ version = "0.1.0"
4
+ description = "A mind map plugin for manim"
5
+ authors = [
6
+ {name = "jj-math",email = "liwei.0028@163.com"}
7
+ ]
8
+ readme = "README.md"
9
+ license = "MIT"
10
+
11
+ requires-python = ">=3.12"
12
+ dependencies = [
13
+ "manim>=0.18.0",
14
+ ]
15
+
16
+ [project.urls]
17
+ Homepage = "https://github.com/jj-math/manim-mindmap"
18
+ Repository = "https://github.com/jj-math/manim-mindmap"
19
+ Documentation = "https://github.com/jj-math/manim-mindmap#readme"
20
+ "Bug Tracker" = "https://github.com/jj-math/manim-mindmap/issues"
21
+
22
+ [tool.poetry]
23
+ packages = [{include = "manim_mindmap", from = "src"}]
24
+
25
+ [build-system]
26
+ requires = ["poetry-core>=2.0.0,<3.0.0"]
27
+ build-backend = "poetry.core.masonry.api"
28
+
29
+ [tool.poetry.group.dev.dependencies]
30
+ pytest = "^8.0"
31
+ pylint = "^3.0"
@@ -0,0 +1,3 @@
1
+ from .nodes import Node,NodeStyle,bfs_walker,dfs_walker
2
+ from .mindmap import MindMap
3
+ from .animations import *
@@ -0,0 +1 @@
1
+ from .tidy_tree import *