Rust图形生成库dot-generator的使用,dot-generator可高效生成DOT语言描述的图形结构
Rust图形生成库dot-generator的使用
dot-generator是一个高效的Rust库,用于生成DOT语言描述的图形结构。DOT语言是Graphviz工具使用的图形描述语言,广泛用于可视化各种图形结构。
安装
在项目目录中运行以下Cargo命令:
cargo add dot-generator
或者在Cargo.toml中添加:
dot-generator = "0.2.0"
使用示例
简单图形示例
use dot_generator::*;
use dot_structures::*;
fn main() {
// 创建一个有向图
let graph = graph!(strict di id!("example");
node!("a"; attr!("shape", "circle")),
node!("b"; attr!("shape", "square")),
edge!(node_id!("a") => node_id!("b")),
stmt_list!(
attr!("rankdir", "LR")
)
);
// 将图转换为DOT语言字符串
let dot_string = graph.to_string();
println!("{}", dot_string);
}
输出结果:
strict digraph example {
rankdir=LR;
a [shape=circle];
b [shape=square];
a -> b;
}
复杂图形示例
use dot_generator::*;
use dot_structures::*;
fn main() {
let graph = graph!(strict di id!("network");
node!("router";
attr!("shape", "box"),
attr!("color", "red"),
attr!("label", "Main Router")
),
node!("server1";
attr!("shape", "ellipse"),
attr!("color", "blue"),
attr!("label", "Web Server")
),
node!("server2";
attr!("shape", "ellipse"),
attr!("color", "green"),
attr!("label", "DB Server")
),
edge!(node_id!("router") => node_id!("server1");
attr!("label", "100Mbps"),
attr!("color", "gray")
),
edge!(node_id!("router") => node_id!("server2");
attr!("label", "1Gbps"),
attr!("color", "black")
),
stmt_list!(
attr!("rankdir", "TB"),
attr!("label", "Network Diagram"),
attr!("labelloc", "t")
)
);
println!("{}", graph.to_string());
}
主要特性
- 类型安全:所有图形元素都使用Rust类型系统进行验证
- 流畅的API:使用宏提供简洁的构建语法
- 高效:生成DOT语言描述非常高效
- 灵活:支持Graphviz的所有主要功能
完整示例Demo
状态机示例
use dot_generator::*;
use dot_structures::*;
fn main() {
// 创建一个状态机图
let state_machine = graph!(di id!("state_machine");
// 定义状态节点
node!("Idle";
attr!("shape", "ellipse"),
attr!("color", "blue"),
attr!("label", "Idle State")
),
node!("Processing";
attr!("shape", "ellipse"),
attr!("color", "green"),
attr!("label", "Processing State")
),
node!("Error";
attr!("shape", "doublecircle"),
attr!("color", "red"),
attr!("label", "Error State")
),
// 定义状态转移边
edge!(node_id!("Idle") => node_id!("Processing");
attr!("label", "on_start"),
attr!("color", "black")
),
edge!(node_id!("Processing") => node_id!("Idle");
attr!("label", "on_complete"),
attr!("color", "green")
),
edge!(node_id!("Processing") => node_id!("Error");
attr!("label", "on_error"),
attr!("color", "red"),
attr!("style", "dashed")
),
edge!(node_id!("Error") => node_id!("Idle");
attr!("label", "on_reset"),
attr!("color", "blue")
),
// 图属性
stmt_list!(
attr!("rankdir", "LR"),
attr!("label", "State Machine Diagram"),
attr!("labelloc", "t")
)
);
println!("{}", state_machine.to_string());
}
这个完整示例展示了如何使用dot-generator创建状态机图,包含三种状态和四种状态转移条件,并添加了丰富的属性设置。
1 回复
Rust图形生成库dot-generator使用指南
介绍
dot-generator是一个Rust库,用于高效生成DOT语言描述的图形结构。DOT是一种图形描述语言,常用于可视化图形结构,可以被Graphviz等工具渲染成图片。这个库提供了类型安全的方式来构建图形,避免了手动拼接字符串的麻烦。
安装
在Cargo.toml中添加依赖:
[dependencies]
dot-generator = "0.1"
dot = "0.1" # 可选,用于输出DOT格式
基本用法
创建简单图形
use dot_generator::*;
use dot::*;
fn main() {
// 创建一个有向图
let graph = graph::digraph()
.set(graph::id("G")) // 设置图形ID
.edge(node_id("a"), node_id("b")) // 添加边a->b
.edge(node_id("b"), node_id("c")) // 添加边b->c
.edge(node_id("c"), node_id("a")); // 添加边c->a
println!("{}", graph.to_dot()); // 输出DOT格式
}
输出DOT格式:
digraph G {
a -> b;
b -> c;
c -> a;
}
添加属性
use dot_generator::*;
use dot::*;
fn main() {
// 创建带有属性的图形
let graph = graph::digraph()
.set(graph::id("example"))
.set(graph::attr("rankdir", "LR")) // 设置图形属性:从左到右布局
.node(
node_id("start")
.attr("shape", "box") // 设置节点形状
.attr("color", "red") // 设置节点颜色
)
.node(
node_id("end")
.attr("shape", "ellipse")
.attr("color", "blue")
)
.edge(
edge(node_id("start"), node_id("end"))
.attr("label", "process") // 设置边标签
.attr("style", "dashed") // 设置边样式
);
println!("{}", graph.to_dot());
}
创建子图
use dot_generator::*;
use dot::*;
fn main() {
// 创建包含子图的图形
let graph = graph::digraph()
.set(graph::id("cluster_example"))
.subgraph(
subgraph("cluster_a")
.set(graph::attr("label", "Process A")) // 设置子图标签
.node(node_id("a1"))
.node(node_id("a2"))
.edge(node_id("a1"), node_id("a2")) // 子图内部边
)
.subgraph(
subgraph("cluster_b")
.set(graph::attr("label", "Process B"))
.node(node_id("b1"))
.node(node_id("b2"))
.edge(node_id("b1"), node_id("b2"))
)
.edge(node_id("a1"), node_id("b2")); // 子图之间的边
println!("{}", graph.to_dot());
}
高级特性
使用宏简化创建
use dot_generator::*;
use dot::*;
fn main() {
// 使用宏简化图形创建
let graph = digraph!("G" => {
rankdir = "LR";
node!("start" => {
shape = "box";
color = "red";
});
node!("end" => {
shape = "ellipse";
color = "blue";
});
edge!("start" -> "end" => {
label = "process";
style = "dashed";
});
});
println!("{}", graph.to_dot());
}
从数据结构生成图形
use dot_generator::*;
use dot::*;
// 定义节点结构体
struct Node {
id: String,
label: String,
}
// 定义边结构体
struct Edge {
from: String,
to: String,
relation: String,
}
// 从数据结构生成DOT图形
fn generate_graph(nodes: Vec<Node>, edges: Vec<Edge>) -> String {
let mut graph = graph::digraph().set(graph::id("data_structure"));
// 添加所有节点
for node in nodes {
graph = graph.node(
node_id(&node.id)
.attr("label", &node.label)
);
}
// 添加所有边
for edge in edges {
graph = graph.edge(
edge(node_id(&edge.from), node_id(&edge.to))
.attr("label", &edge.relation)
);
}
graph.to_dot()
}
fn main() {
let nodes = vec![
Node { id: "a".to_string(), label: "Node A".to_string() },
Node { id: "b".to_string(), label: "Node B".to_string() },
];
let edges = vec![
Edge { from: "a".to_string(), to: "b".to_string(), relation: "connects".to_string() },
];
println!("{}", generate_graph(nodes, edges));
}
输出到文件
use std::fs::File;
use std::io::Write;
use dot_generator::*;
use dot::*;
fn main() -> std::io::Result<()> {
// 创建简单图形
let graph = graph::digraph()
.set(graph::id("file_example"))
.edge(node_id("a"), node_id("b"))
.edge(node_id("b"), node_id("c"));
// 将图形写入文件
let mut file = File::create("example.dot")?;
file.write_all(graph.to_dot().as_bytes())?;
Ok(())
}
完整示例
下面是一个结合了多种特性的完整示例:
use dot_generator::*;
use dot::*;
use std::fs::File;
use std::io::Write;
// 定义项目结构
struct Project {
name: String,
modules: Vec<Module>,
}
struct Module {
name: String,
functions: Vec<String>,
}
fn generate_project_graph(project: Project) -> String {
let mut graph = graph::digraph()
.set(graph::id(&project.name))
.set(graph::attr("rankdir", "TB"))
.set(graph::attr("compound", "true"));
// 为每个模块创建子图
for module in project.modules {
let cluster_name = format!("cluster_{}", module.name);
graph = graph.subgraph(
subgraph(&cluster_name)
.set(graph::attr("label", &module.name))
.set(graph::attr("style", "filled"))
.set(graph::attr("color", "lightgrey"))
);
// 添加模块中的函数节点
for func in module.functions {
let node_id = format!("{}_{}", module.name, func);
graph = graph.node(
node_id(&node_id)
.attr("label", &func)
.attr("shape", "box")
);
}
}
// 添加模块间的依赖关系
graph = graph.edge(
edge(node_id("core_initialize"), node_id("network_connect"))
.attr("label", "uses")
.attr("style", "dashed")
);
graph.to_dot()
}
fn main() -> std::io::Result<()> {
// 创建项目结构
let project = Project {
name: "RustProject".to_string(),
modules: vec![
Module {
name: "core".to_string(),
functions: vec!["initialize".to_string(), "shutdown".to_string()],
},
Module {
name: "network".to_string(),
functions: vec!["connect".to_string(), "disconnect".to_string()],
},
],
};
// 生成图形
let dot_output = generate_project_graph(project);
// 输出到控制台
println!("{}", dot_output);
// 写入文件
let mut file = File::create("project.dot")?;
file.write_all(dot_output.as_bytes())?;
Ok(())
}
注意事项
-
生成的DOT文件可以使用Graphviz工具渲染成图片:
dot -Tpng example.dot -o example.png
-
对于大型图形,考虑使用
graph::strict()
创建严格图形,可以避免重复边 -
节点ID必须是有效的DOT标识符,如果包含特殊字符,需要使用引号包裹
-
使用子图(cluster)时,子图名称必须以"cluster_"开头才能被Graphviz识别为集群
dot-generator提供了类型安全的方式来构建图形结构,避免了手动拼接字符串可能带来的错误,是生成DOT图形的理想选择。