Graphviz выводит беспорядок
Я пытаюсь визуализировать следующие данные в точечном формате с помощью GraphViz:
digraph n {
node [nodesep=2.0, fontsize=11];
graph [ overlap=false];
edge[weight=0.2];
A -> B [label="I/5"]
A -> A [label="*/0"]
A -> C [label="ii/2"]
A -> H [label="vii/1"]
B -> D [label="iii/1"]
B -> E [label="IV/2"]
B -> F [label="V/2"]
B -> B [label="vi/2"]
C -> F [label="V/2"]
C -> H [label="vii/1"]
D -> E [label="IV/2"]
E -> D [label="iii/2"]
E -> G [label="iv/1"]
E -> F [label="V/3"]
F -> B [label="I/4"]
F -> B [label="vi/1"]
F -> B [label="*/0"]
G -> B [label="I/5"]
H -> B [label="vi/1"]
}
Выполнение следующей команды:
neato -Tpng Chord_NFA.dot > Chord_NFA.png
дает мне этот вывод:
![]()
Я хотел бы, чтобы он поместился на A4 и ни один из ребер не перекрывал или не пересекал узел. Это возможно (математически), потому что я сделал это сам с биро.
Ответы
Ответ 1
Я играл с ним несколько и получил это:
digraph n {
node [nodesep=2.0, fontsize=11];
graph [overlap = false];
subgraph cluster_a {
style=invisible;
A; B; H;
}
subgraph cluster_b {
style=invisible;
D; E; G;
}
subgraph cluster_c {
style=invisible;
C; F;
}
A -> B [label="I/5"];
A -> A [label="*/0"];
A -> C [label="ii/2"];
A -> H [label="vii/1"];
B:w -> D [label="iii/1"];
B:nw -> E [minlen=3 label="IV/2"];
B -> F [minlen=2 label="V/2"];
B -> B [label="vi/2"];
C -> F [minlen=2 label="V/2"];
C -> H [label="vii/1"];
D -> E [label="IV/2"];
D -> E [minlen=2 dir=back label="iii/2"];
G -> E [minlen=2 dir=back label="iv/1"];
F -> E [dir=back label="V/3"];
B -> F [minlen=2 dir=back label="I/4"];
B -> F [minlen=2 dir=back label="vi/1"];
B -> F [minlen=2 dir=back label="*/0"];
B -> G [dir=back label="I/5"];
H -> B [label="vi/1"];
}
Скомпилировать с помощью:
dot -Tpng -o Chord_NFA.png Chord_NFA.gv
Выход это, без каких-либо пересечений линий:
![graph]()
Трюк:
-
Чтобы добавить атрибут minlen для принудительного разделения, добавьте больше интервалов для рендеринга без перекрытий и пересечений.
-
Чтобы инвертировать логику некоторых ребер (рендеринг их без инверсии с помощью dir = back). Таким образом, точка всегда видит ациклический граф и может упорядочить края, не путаясь.
-
Сначала сосредоточитесь на некоторых подграфах и сгруппируйте их узлы в кластерах, чтобы дать им некоторую "защиту" от помех при рендеринге остальной части графика.
Ответ 2
Вот несколько шагов в лучшем направлении:
-
nodesep
не является атрибутом node - и, вероятно, он не делает то, что вы ожидается. Но это все еще полезно в вашем случае:
... это влияет на интервал между циклами на одном node или multiedges между парой узлов.
- Я не думаю, что край вес меняет что-то, если вы меняете его для всех ребер.
- Включение сплайнов часто является хорошей идеей.
- Добавление дополнительного пространства вокруг узлов может быть выполнено с помощью
sep
-
overlap
имеет больше значений, чем true/false - я часто нахожу scalexy
полезным.
- Как только дистрибутив node будет в порядке, вы можете точно настроить позиции ярлыков, используя комбинацию
headlabel
/taillabel
, labeldistance
и labelangle
(красный в пример ниже, чтобы выделиться).
Здесь измененный образец:
digraph n {
splines=true;
sep="+25,25";
overlap=scalexy;
nodesep=0.6;
node [fontsize=11];
//edge[weight=0.2];
A -> B [label="I/5"]
A -> A [label="*/0"]
A -> C [label="ii/2"]
A -> H [label="vii/1"]
B -> D [label="iii/1"]
B -> E [label="IV/2"]
B -> F [headlabel="V/2", labeldistance=4, labelangle=-10, labelfontcolor=red]
B -> B [label="vi/2"]
C -> F [label="V/2"]
C -> H [label="vii/1"]
D -> E [label="IV/2"]
E -> D [label="iii/2"]
E -> G [label="iv/1"]
E -> F [headlabel="V/3", labeldistance=8, labelangle=-7, labelfontcolor=red]
F -> B [label="I/4"]
F -> B [label="vi/1"]
F -> B [label="*/0"]
G -> B [taillabel="I/5", labeldistance=4, labelangle=15, labelfontcolor=red]
H -> B [label="vi/1"]
}
![graphviz output]()
Ответ 3
Используя точечный движок, я получил следующий результат, не меняя файл точки, который должен соответствовать A4. Марапетское исполнение лучше использует пространство.
![dot engine output]()