我需要绘制一个带有graphviz / dot的图表,其中节点之间存在共同的边缘类型,并且我试图找到为每种类型的边缘定义标签的方法,然后在图中多次使用该标签。
例如,想象一下传统的吊扇FSM示例,它最初处于关闭状态,每当有人拉绳子时,它会根据风扇的速度变为新状态:
Pull Pull Pull
OFF ------> HIGH ------> MED ------> LOW
^ |
| Pull |
+------------------------------------+
每个边缘都被命名为#34; Pull"我可以使用以下方法在点中定义:
digraph fan {
OFF -> HIGH [label="Pull"];
HIGH -> MED [label="Pull"];
MED -> LOW [label="Pull"];
LOW -> OFF [label="Pull"];
}
但我不想每次都指定相同的文字标签,因为
我希望dot有一个语法可以让我为我的边缘类型定义名称,例如:
digraph fan {
edge_a [label="Pull"];
OFF -> HIGH edge_a;
HIGH -> MED edge_a;
MED -> LOW edge_a;
LOW -> OFF edge_a;
}
但当然真正做的是创建一个名为" Pull"和未标记的边缘。
我在网上搜索了几个小时却没有成功。任何人都知道如何预先定义边缘类型以在多个位置使用?
更新: @vaettchen had suggested定义边缘类型,然后列出该边缘类型的所有过渡,然后定义下一个边缘类型,然后是它的过渡。虽然这在技术上可以解决我的问题,但它会引入其他几个,因为我今天的图表看起来像:
digraph {
subgraph cluster_1 {
a -> b [label="type x", color=red, style=solid];
b -> a [label="type y", color=green, style=dashed];
b -> c [label="type x", color=red, style=solid];
c -> b [label="type y", color=green, style=dashed];
c -> d [label="type z", color=blue, style=dotted];
}
subgraph cluster_2 {
d -> e [label="type x", color=red, style=solid];
e -> d [label="type y", color=green, style=dashed];
e -> f [label="type x", color=red, style=solid];
f -> e [label="type y", color=green, style=dashed];
f -> c [label="type z", color=blue, style=dotted];
}
}
并且重新排列边缘类型I在双向边缘彼此相邻的代码中失去直接的视觉清晰度(a-> b和b-> a)和I' d必须明确列出每个子图中的节点,并且我必须将子图内部边缘定义拉到主图中:
digraph {
edge [label="type x", color=red, style=solid];
a -> b;
b -> c;
d -> e;
e -> f;
edge [label="type y", color=green, style=dashed];
b -> a;
c -> b;
e -> d;
f -> e;
edge [label="type z", color=blue, style=dotted];
c -> d;
f -> c;
subgraph cluster_1 {
a; b; c;
}
subgraph cluster_2 {
d; e; f;
}
}
因此,虽然它可以解决我提出的问题并且我很欣赏这个建议,但我不确定它是否值得权衡,因为你最终得到了相当于你必须定义的C程序所有变量都在函数之外,并按类型而不是逻辑关联来组织它们。
要明确的是,鉴于以上示例,我真正希望的是如果这样的" edge_type"定义关键字存在:
digraph {
edge_type edge_x [label="type x", color=red, style=solid];
edge_type edge_y [label="type y", color=green, style=dashed];
edge_type edge_z [label="type z", color=blue, style=dotted];
subgraph cluster_1 {
a -> b edge_x;
b -> a edge_y;
b -> c edge_x;
c -> b edge_y;
c -> d edge_z;
}
subgraph cluster_2 {
d -> e edge_x;
e -> d edge_y;
e -> f edge_x;
f -> e edge_y;
f -> c edge_z;
}
}
答案 0 :(得分:3)
我认为我使用m4得到了您的解决方案(感谢Simon)。使用和调整您的示例,我创建了一个名为/mtn/sda1/bla/bla
的文件:
gv.m4
并使用简单命令
转换它digraph {
define(`edge_x',`[label="type x", color=red, style=solid]')
define(`edge_y',`[label="type y", color=green, style=dashed]')
define(`edge_z',`[label="type z", color=blue, style=dotted]')
subgraph cluster_1 {
a -> b edge_x;
b -> a edge_y;
b -> c edge_x;
c -> b edge_y;
c -> d edge_z;
}
subgraph cluster_2 {
d -> e edge_x;
e -> d edge_y;
e -> f edge_x;
f -> e edge_y;
f -> c edge_z;
}
}
现在包含您定义的边
m4 gv.m4 > gv.dot
并产生预期的图表:
你可以用m4做更多的事情 - 在graphViz中缺少的东西,比如维护和(甚至有条件地)包括子文件。例如,如果您将两个子图放在两个单独的文件digraph {
subgraph cluster_1 {
a -> b [label="type x", color=red, style=solid];
b -> a [label="type y", color=green, style=dashed];
b -> c [label="type x", color=red, style=solid];
c -> b [label="type y", color=green, style=dashed];
c -> d [label="type z", color=blue, style=dotted];
}
subgraph cluster_2 {
d -> e [label="type x", color=red, style=solid];
e -> d [label="type y", color=green, style=dashed];
e -> f [label="type x", color=red, style=solid];
f -> e [label="type y", color=green, style=dashed];
f -> c [label="type z", color=blue, style=dotted];
}
}
和gv1.txt
中,这将很有效:
gv2.txt
答案 1 :(得分:2)
不是一个真正的答案,而是"思考的食物"因为我不认为graphviz
中存在命名标签:您可以为以下边缘定义默认标签。如果您的工作流程允许在一个位置定义边缘,那么这很有效。例如:
digraph rs
{
node[ shape = box, style = rounded]
edge[ label = "pull" ];
{ A B } -> C;
G -> H;
C -> D[ label = "stop" ];
edge[ label = "push"];
D -> { E F };
edge[ color = red, fontcolor = red ];
{ E F } -> G;
}
产生
我也尝试用
实现你的diagrammdigraph fan
{
splines = ortho;
node [ shape=box ]
edge [ xlabel = "Pull", minlen = 4 ];
{ rank = same; OFF -> HIGH -> LOW; }
LOW:s -> OFF:s;
}
产生
所以它看起来不错,但所有的调整很难扩展。