Graphviz 图形可视化教程 / 06 - 布局引擎
第 06 章 · 布局引擎
6.1 引擎概览
Graphviz 提供 7+ 种布局引擎,每种引擎针对不同的图形拓扑结构优化:
| 引擎 | 算法类别 | 方向性支持 | 推荐节点数 | 核心原理 |
|---|---|---|---|---|
| dot | 层次布局 | 有向 | 任意 | Sugiyama 分层算法 |
| neato | 力导向 | 无向 | < 100 | 弹簧-质点模型 |
| fdp | 力导向 | 无向 | < 1000 | Fruchterman-Reingold |
| sfdp | 多尺度力导向 | 无向 | > 1000 | 多层次力导向 |
| twopi | 放射布局 | 有/无向 | < 500 | 径向树布局 |
| circo | 圆形布局 | 有/无向 | < 200 | 圆弧布局 |
| osage | 矩形布局 | 有/无向 | 任意 | 矩形嵌套 |
| patchwork | 矩形树图 | 有/无向 | 任意 | Squarified Treemap |
6.2 dot 引擎
dot 是最常用的引擎,适合有向图、层次结构图。使用 Sugiyama 分层算法。
工作原理
- 拓扑排序:确定节点的层级
- 交叉减少:最小化边的交叉
- 节点放置:在层级内安排节点位置
- 边路由:计算边的路径
布局方向
digraph DotTB {
// TB — 从上到下(默认)
rankdir=TB
node [fontname="Microsoft YaHei" shape=box style=rounded]
A -> B -> C -> D
B -> E
}
digraph DotLR {
// LR — 从左到右
rankdir=LR
node [fontname="Microsoft YaHei" shape=box style=rounded]
A -> B -> C -> D
B -> E
}
digraph DotBT {
// BT — 从下到上
rankdir=BT
node [fontname="Microsoft YaHei" shape=box style=rounded]
A -> B -> C -> D
}
digraph DotRL {
// RL — 从右到左
rankdir=RL
node [fontname="Microsoft YaHei" shape=box style=rounded]
A -> B -> C -> D
}
dot 专属属性
| 属性 | 说明 | 常用值 |
|---|---|---|
rankdir | 布局方向 | TB、LR、BT、RL |
rank | 强制排名 | same、min、max、source、sink |
nodesep | 同层节点间距 | 0.25(默认) |
ranksep | 层间距离 | 0.5(默认) |
concentrate | 合并边 | true、false |
mclimit | 迭代次数 | 1.0(默认) |
适用场景
digraph DotUseCase {
rankdir=LR
node [fontname="Microsoft YaHei" shape=box style="filled,rounded" fillcolor="#E3F2FD" color="#1976D2"]
edge [fontname="Microsoft YaHei" fontsize=9 color="#666666"]
"dot 引擎" -> "流程图" [label="✓"]
"dot 引擎" -> "DAG 依赖图" [label="✓"]
"dot 引擎" -> "类层次图" [label="✓"]
"dot 引擎" -> "状态机" [label="✓"]
"dot 引擎" -> "网络拓扑" [label="✗" color="#F44336"]
"dot 引擎" -> "社交网络" [label="✗" color="#F44336"]
}
6.3 neato 引擎
neato 使用 弹簧-质点模型(Spring Model),适合小型无向图。
工作原理
- 每条边是一根弹簧,试图拉近相连的节点
- 每对节点之间有排斥力,防止重叠
- 通过迭代计算达到力平衡
graph NeatoExample {
layout=neato
overlap=false
node [fontname="Microsoft YaHei" shape=circle style=filled fillcolor="#E8F5E9" color="#388E3C"]
edge [color="#9E9E9E"]
A -- B -- C -- D -- A
A -- C
B -- D
E -- A
E -- B
E -- C
E -- D
}
neato 专属属性
| 属性 | 说明 | 常用值 |
|---|---|---|
overlap | 重叠处理 | false、scale、prism |
sep | 节点分离 | +10、0.5 |
maxiter | 最大迭代次数 | 100(默认) |
epsilon | 收敛阈值 | 0.0001(默认) |
start | 随机种子 | random、数值 |
6.4 fdp 引擎
fdp(Force-Directed Placement)是 neato 的改进版,使用 Fruchterman-Reingold 算法,性能更好。
graph FdpExample {
layout=fdp
overlap=false
node [fontname="Microsoft YaHei" shape=box style=rounded]
edge [color="#9E9E9E"]
subgraph cluster_group1 {
label="组 1"
A -- B -- C
}
subgraph cluster_group2 {
label="组 2"
D -- E -- F
}
A -- D
C -- F
B -- E
}
neato vs fdp 对比
| 特性 | neato | fdp |
|---|---|---|
| 算法 | 弹簧模型 | Fruchterman-Reingold |
| 性能 | 小图优 | 中大图优 |
| 子图感知 | 弱 | 较强 |
| 重叠处理 | 需手动设置 | 自动处理 |
| 推荐节点数 | < 100 | < 1000 |
6.5 sfdp 引擎
sfdp(Scalable Force-Directed Placement)是多尺度力导向布局,适合大型图。
graph SfdpExample {
layout=sfdp
overlap=false
node [fontname="Microsoft YaHei" shape=point width=0.15]
// 大型随机图(自动生成)
A -- B -- C -- D -- E -- F -- G -- H
A -- E -- I -- J -- K -- L
B -- F -- J -- M -- N
C -- G -- K -- N -- O
D -- H -- L -- O -- P
}
适用场景
- 社交网络图
- 知识图谱
- 依赖关系网络(节点数 > 1000)
6.6 twopi 引擎
twopi 使用 放射状布局,根节点居中,其余节点沿同心圆排列。
graph TwopiExample {
layout=twopi
ranksep=1.5
node [fontname="Microsoft YaHei" shape=box style="filled,rounded" fillcolor="#E3F2FD" color="#1976D2"]
edge [color="#9E9E9E"]
// 根节点(默认第一个或 root 属性指定)
Root [fillcolor="#FFCDD2" color="#C62828" label="根节点"]
Root -> {A B C D}
A -> {A1 A2 A3}
B -> {B1 B2}
C -> {C1 C2 C3 C4}
D -> {D1}
}
twopi 专属属性
| 属性 | 说明 | 常用值 |
|---|---|---|
root | 根节点 | 节点 ID 或 central |
ranksep | 圆环间距 | 1.0、1.5 |
适用场景
- 组织架构图
- 文件目录结构
- 辐射状知识图谱
6.7 circo 引擎
circo 使用 圆形布局,适合循环结构。
digraph CircoExample {
layout=circo
node [fontname="Microsoft YaHei" shape=circle style=filled fillcolor="#E8F5E9" color="#388E3C"]
edge [fontname="Microsoft YaHei" fontsize=9 color="#9E9E9E"]
A -> B -> C -> D -> E -> A
// 额外的非循环连接
A -> C [style=dashed color="#F44336"]
B -> D [style=dashed color="#F44336"]
}
适用场景
- 循环流水线
- 环形网络拓扑
- 周期性流程
- 有限状态机的环形展示
6.8 osage 引擎
osage 使用 矩形布局,按子图分组进行矩形嵌套。
graph OsageExample {
layout=osage
node [fontname="Microsoft YaHei" shape=box style=filled]
subgraph cluster_前端 {
label="前端"
style=filled
fillcolor="#E3F2FD"
color="#1976D2"
React [fillcolor="#BBDEFB"]
Vue [fillcolor="#BBDEFB"]
}
subgraph cluster_后端 {
label="后端"
style=filled
fillcolor="#E8F5E9"
color="#388E3C"
Go [fillcolor="#C8E6C9"]
Java [fillcolor="#C8E6C9"]
Python [fillcolor="#C8E6C9"]
}
subgraph cluster_数据 {
label="数据"
style=filled
fillcolor="#F3E5F5"
color="#7B1FA2"
MySQL [fillcolor="#E1BEE7"]
Redis [fillcolor="#E1BEE7"]
Mongo [fillcolor="#E1BEE7"]
}
}
6.9 patchwork 引擎
patchwork 生成 矩形树图(Treemap),面积表示层次权重。
graph PatchworkExample {
layout=patchwork
node [fontname="Microsoft YaHei" shape=box style=filled]
subgraph cluster_root {
label="市场份额"
style=filled fillcolor="#FAFAFA"
subgraph cluster_A {
label="公司 A"
style=filled fillcolor="#E3F2FD" color="#1976D2"
A1 [width=3 height=2 fillcolor="#BBDEFB" label="产品 1"]
A2 [width=1 height=1 fillcolor="#BBDEFB" label="产品 2"]
}
subgraph cluster_B {
label="公司 B"
style=filled fillcolor="#E8F5E9" color="#388E3C"
B1 [width=2 height=2 fillcolor="#C8E6C9" label="产品 3"]
B2 [width=1.5 height=1 fillcolor="#C8E6C9" label="产品 4"]
}
subgraph cluster_C {
label="公司 C"
style=filled fillcolor="#FFF3E0" color="#FF9800"
C1 [width=1 height=1 fillcolor="#FFE0B2" label="产品 5"]
}
}
}
6.10 引擎选择指南
决策树
digraph EngineDecision {
rankdir=TB
node [fontname="Microsoft YaHei" fontsize=10]
edge [fontname="Microsoft YaHei" fontsize=8]
// 决策节点
Q1 [shape=diamond label="有向边?\n(有层次关系)" style=filled fillcolor="#E3F2FD" color="#1976D2"]
Q2 [shape=diamond label="环形结构?" style=filled fillcolor="#E3F2FD" color="#1976D2"]
Q3 [shape=diamond label="节点数 > 1000?" style=filled fillcolor="#E3F2FD" color="#1976D2"]
Q4 [shape=diamond label="树形/辐射?" style=filled fillcolor="#E3F2FD" color="#1976D2"]
Q5 [shape=diamond label="需要分组?" style=filled fillcolor="#E3F2FD" color="#1976D2"]
// 结果节点
dot [shape=box label="dot ✓" style="filled,rounded" fillcolor="#C8E6C9" color="#388E3C"]
circo [shape=box label="circo ✓" style="filled,rounded" fillcolor="#C8E6C9" color="#388E3C"]
twopi [shape=box label="twopi ✓" style="filled,rounded" fillcolor="#C8E6C9" color="#388E3C"]
sfdp [shape=box label="sfdp ✓" style="filled,rounded" fillcolor="#C8E6C9" color="#388E3C"]
fdp [shape=box label="fdp ✓" style="filled,rounded" fillcolor="#C8E6C9" color="#388E3C"]
neato [shape=box label="neato ✓" style="filled,rounded" fillcolor="#C8E6C9" color="#388E3C"]
osage [shape=box label="osage ✓" style="filled,rounded" fillcolor="#C8E6C9" color="#388E3C"]
Q1 -> dot [label="是"]
Q1 -> Q2 [label="否"]
Q2 -> circo [label="是"]
Q2 -> Q4 [label="否"]
Q4 -> twopi [label="是"]
Q4 -> Q3 [label="否"]
Q3 -> sfdp [label="是"]
Q3 -> Q5 [label="否"]
Q5 -> osage [label="是"]
Q5 -> fdp [label="否\n(< 1000 节点)"]
Q3 -> fdp [label="否\n(< 1000 节点)" style=dashed]
}
场景对照表
| 场景 | 推荐引擎 | 备选引擎 | 理由 |
|---|---|---|---|
| 流程图 | dot | — | 层次结构完美适配 |
| 状态机 | dot | circo | 状态转换有层次 |
| 类图 | dot | — | 继承关系天然层次 |
| 网络拓扑 | fdp | neato | 无明显层次 |
| 社交网络 | sfdp | fdp | 节点多 |
| 组织架构 | twopi | dot | 树形辐射 |
| 目录结构 | twopi | dot | 层次树 |
| 循环流水线 | circo | — | 环形结构 |
| 分组展示 | osage | — | 矩形分组 |
| 面积权重 | patchwork | — | Treemap |
| ER 图 | dot | — | 实体关系层次 |
注意事项
⚠️ 引擎不可混用:一个 DOT 文件只能用一种引擎。切换引擎需用命令行参数
-K或-T。
⚠️ neato 的 overlap:默认不处理重叠,必须设置
overlap=false。
⚠️ dot 的 rank:
rank=same只在 dot 引擎中有效。
⚠️ 大图性能:
sfdp是处理大图(>1000 节点)的最佳选择。
⚠️ circo 的循环:需要明确的环形结构才能获得好效果。
扩展阅读
下一章:07 - 子图与集群 — 使用子图和集群组织复杂图形。