用mManim探索有向图【Graph】的布局函数
在manim中有Circular Layou,Kamada Kawai Layout,Partite Layout,Planar Layout,Random Layout,Shell Layout,Spectral Layout,Sprial Layout,Spring Layout,Tree Layout 函数,它们都有自己的特点。下面是Manim中不同布局函数的简要解释,包括每个布局的用途、特点以及适用场景的简要描述。
一,介绍
1.Circular Layou
Circular Layout 是一种图形布局方法,用于在一个圆形范围内均匀分布图形中的节点(或顶点)。在这种布局中,节点按照圆周均匀排列,形成一个圆,使得节点之间的距离尽可能相等。这种布局特别适合展示网络结构、群体关系或层次结构,因为它能够有效地利用空间并提供良好的可视化效果。
主要优点: 均匀分布:节点在圆周上均匀分布,视觉上很平衡。 增强可读性:通过减少节点之间的重叠,确保节点的标签和链接更加清晰。 适用性广:适用于各种类型的图(如社交网络、树形结构等),特别是当关系相对对称或没有明显方向时。 视觉吸引力:圆形布局通常更具吸引力,并能够引导观众的视线。 使用场景: 社交网络分析:可以用来展示用户之间的连接和交互。 数据可视化:适合显示类别之间的关系,例如产品特性和相互作用。 生物信息学:在基因组学或生态学中,展示物种或基因之间的关系。
2. Kamada Kaway Layout
- 用途: 常用于绘制图结构,特别是在网络图或连接图中。
- 解释: 基于力导向算法,Kamada-Kaway布局试图最小化节点之间的距离,使图形结构在视觉上看起来更为平衡。
- 特点: 可以很好地展示复杂的连接关系,优先考虑局部连接。
3. Partite Layout
- 用途: 用于可视化分层或分组关系的图。
- 解释: 将节点分为不同的组,并在图中以不同的水平显示这些组,有助于清晰地展示节点之间的连接关系。
- 特点: 非常适合展示二分图或多分图结构,保持组与组之间的距离。
4. Planar Layout
- 用途: 专门用于展示平面图。
- 解释: 以一种不相交的方式将节点排列,并确保没有边线交叉,有助于清晰地可视化图形。
- 特点: 适合于平面图的视觉化应用,能够保持视觉的整洁性和可读性。
5. Random Layout
- 用途: 随机展示节点的布局。
- 解释: 节点的排列没有特定的模式,通常用于快速实验或初步可视化,没有明确的线性或层次结构。
- 特点: 虽然没有结构性,但适合于快速生成可视化,缺乏可读性和美观。
6. Shell Layout
- 用途: 用于环形结构的展示。
- 解释: 节点被放置在同心圆或者环形中,可以展现节点之间的层次或群体。
- 特点: 适合展示具有环形结构的图,特别是当节点具有层次性时,视觉效果较好。
7. Spectral Layout
- 用途: 基于图的谱特征进行节点位置的布局,适用于复杂图形的展示。
- 解释: 通过分析图的拉普拉斯矩阵,利用特征值分解来确定节点的位置,能够反映节点之间的关系。
- 特点: 能够有效地减少图的边的交叉,适合于复杂图的数据表示。
8. Spiral Layout
- 用途: 用于螺旋结构的节点排列。
- 解释: 节点沿着一个螺旋形的路径排列,通常用于展示时间序列数据或具有顺序性质的结构。
- 特点: 适合展示时间演变或是逐步发展关系的图,视觉上独特。
9. Spring Layout
- 用途: 基于物理模拟进行节点布置,常用于社交网络或图形结构。
- 解释: 使用力导向算法,模拟节点之间的相互作用(如弹簧吸引或推斥)来获得节点的位置,从而使图形结构尽可能平衡。
- 特点: 能够直观地反映节点间的连接强度,适合展示复杂的网络关系。
10. Tree Layout
- 用途: 可视化层次性的数据结构,如树、家谱图或组织结构图。
- 解释: 节点根据层次结构排列,根节点位于顶部或中间,子节点分布在下方或侧面,清楚地呈现父子关系。
- 特点: 强调层级关系,提供一种清晰且直观的图形表示。
这些布局功能在Manim中为用户提供了多样化的图形可视化工具,方便展示不同类型和结构的数据,非常适合用于教育、演示和科学研究等场景。
二,应用
1.Circular Layout
-
圆形布局:将顶点放在一个圆上
-
示例1:
from manim import * class CircularLayout(Scene): def construct(self): graph = Graph( [1, 2, 3, 4, 5, 6], [(1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 1), (5, 1), (1, 3), (3, 5)], layout="circular", labels=True ) self.add(graph)
运行结果:
示例2:
class CircularLayout(Scene):
def construct(self):
graph = Graph(
[1, 2, 3, 4, 5, 6],
[(1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 1), (5, 1), (1, 3), (3, 5)],
layout="circular",
labels=True,
vertex_config={1: {"fill_color": BLUE}},
edge_config={(1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 1): {"stroke_color": RED}} # Fixed line
)
self.add(graph)
运行结果:
示例3:
from manim import *
class CircularLayout04(Scene):
def construct(self):
points=[1, 2, 3, 4, 5, 6]
edges = [
(1, 2), (2, 3), (3, 4), (4, 5),
(5, 6), (6, 1), (5, 1), (1, 3), (3, 5)
]
# 定义外环边
outer_edges = [(1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 1)]
in_edges = [(5, 1), (1, 3), (3, 5)]
# 使用字典生成边配置,将外环边设置为红色,内部边设置为黄色
edge_config = {edge: {"stroke_color": RED} for edge in outer_edges}
edge_config.update({edge: {"stroke_color": YELLOW_E} for edge in in_edges})
graph = Graph(
points,
edges,
layout="circular",
labels=True,
vertex_config={vertex: {"fill_color": BLUE}for vertex in points}, # 配置顶点
edge_config=edge_config # 使用合并后的边配置字典
)
self.add(graph)
运行结果:
2. Kamada Kaway Layout
-
Kamada Kawai Layout:尝试放置顶点,以便尊重它们之间的给定距离
-
示例1:
from manim import * class KamadaKawaiLayout(Scene): def construct(self): from collections import defaultdict distances: dict[int, dict[int, float]] = defaultdict(dict) # set desired distances distances[1][2] = 1 # distance between vertices 1 and 2 is 1 distances[2][3] = 1 # distance between vertices 2 and 3 is 1 distances[3][4] = 2 # etc distances[4][5] = 3 distances[5][6] = 5 distances[6][1] = 8 graph = Graph( [1, 2, 3, 4, 5, 6], [(1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 1)], layout="kamada_kawai", layout_config={"dist": distances}, layout_scale=4, labels=True ) self.add(graph)
运行结果:
示例2:
class KamadaKawaiLayout(Scene):
def construct(self):
from collections import defaultdict
distances: dict[int, dict[int, float]] = defaultdict(dict)
# set desired distances
distances[1][2] = 1 # distance between vertices 1 and 2 is 1
distances[2][3] = 1 # distance between vertices 2 and 3 is 1
distances[3][4] = 1 # etc
distances[4][5] = 1
distances[5][6] = 1
distances[6][1] = 1
distances[2][5] = 2
distances[2][4] = 2.5
graph = Graph(
[1, 2, 3, 4, 5, 6],
[(1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 1)],
layout="kamada_kawai",
layout_config={"dist": distances},
layout_scale=4,
labels=True,
vertex_config={2: {"fill_color": BLUE}} # 配置顶点
)
self.add(graph)
运行结果:
3. Partite Layout
-
Partite Layout:将顶点放置在不同的分区中
-
示例1:
from manim import * class PartiteLayout(Scene): def construct(self): graph = Graph( [1, 2, 3, 4, 5, 6], [(1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 1), (5, 1), (1, 3), (3, 5)], layout="partite", layout_config={"partitions": [[1,2],[3,4],[5,6]]}, labels=True ) self.add(graph)
运行结果:
示例2:
class PartiteLayout(Scene):
def construct(self):
graph = Graph(
[1, 2, 3, 4, 5, 6],
[(1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 1), (5, 1), (1, 3), (3, 5)],
layout="partite",
layout_config={"partitions": [[1,5],[3,6],[5,6]]},
labels=True
)
self.add(graph)
运行结果: