我有两个问题:
- 如果我正在阅读§30.4“交叉最小化”正确理解 PGF/TikZ 3.0 手册,分层图绘制算法应该默认启用交叉最小化。那么为什么算法不自动为该图选择平面嵌入呢?
- 告诉算法避免此图中的边交叉的最佳方法是什么?在这种情况下,我特别希望C位于左侧乙及其子项(全部为灰色),而不改变图的其他属性(如percusse 的回答)。
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{graphs, graphdrawing}
\usegdlibrary{layered}
\begin{document}
\tikz [gr/.style={gray!50}, font=\bfseries]
\graph [layered layout] {
% Swapping the next two lines removes the edge crossing, but
% it doesn’t make much sense, and also isn’t what I want.
A -- C -- F,
{ [nodes=gr, edges=gr] A -- B -- { E, D -- F } }
};
\end{document}
更新
我又看了看波尔曼的论点描述了他为 PGF/TikZ 实现分层图形绘制的过程。我现在确信这是不可能解决这个问题,除非你:
- 手动定义
minimum layers
或weight
全部或部分图表,或 - 重新实现该算法的交叉最小化步骤(在 Lua 中)。
在我看来,第一项并不可取,因为(a)这个问题只影响大量大图中的一小部分,并且(b)它也违背了使用自动图布局的意义。
第二种方法是可行的,但是对于不熟悉 Lua 的人来说很耗时。
以下是论文中的几段引文(重点是我添加的):
强制某些边缘增加最小跨度有时会使绘图因不必要的边缘交叉而解开。为此,模块化分层绘图算法提供了
/graph drawing/layered drawing/minimum layers
边缘选项。(75)
应用小图时,该算法似乎可以毫无问题地生成只有少量边缘交叉和弯曲的分层图,尽管并非在所有情况下都能产生最佳结果—例如,参见 BarthMJ-fig2 的绘图,其中可以轻松避免边缘交叉。总体而言,大多数边缘都尽可能短。(102)
物有所值,数学和点不会遭受此问题:
edges = {"a" -> "c", "c" -> "f", "a" -> "b", "b" -> "e", "b" -> "d", "d" -> "f"};
Row[{LayeredGraphPlot[edges, VertexLabeling -> True, ImageSize -> 100],
Graph[edges /. Rule -> DirectedEdge, VertexLabels -> Placed["Name", Before],
ImagePadding -> 10, ImageSize -> 110]}]
digraph g { a -> c -> f; a -> b; b -> e; b -> d -> f }
更新 2
我最终选择了设置minimum layers
和weight
一个边缘,正如esdd 的回答我对这个结果很满意:
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{graphs, graphdrawing}
\usegdlibrary{layered}
\begin{document}
\tikz [gr/.style={gray!50}, font=\bfseries]
\graph [layered layout] {
% A and F are horizontally aligned if you also set weight=0.5 for A -- C.
A -- [minimum layers=2] C -- F,
{ [nodes=gr, edges=gr] A -- B -- { E, D -- F } }
};
\end{document}
答案1
基于percusse 的回答您只能将边的数量minimum layers
(例如,边必须跨越的最小级别数)更改C
为F
:
\documentclass[tikz,margin=5mm]{standalone}
\usetikzlibrary{graphs, graphdrawing}
\usegdlibrary{layered}
\begin{document}
\tikz [gr/.style={gray!50}, font=\bfseries]
\graph [layered layout] {
A -- C -- F [>minimum layers=2],
{ [nodes=gr, edges=gr] A -- B -- { E, D -- F } },
};
\end{document}
此外,您还可以设置weight
边的参数从D
到F
到0
:
\documentclass[tikz,margin=5mm]{standalone}
\usetikzlibrary{graphs, graphdrawing}
\usegdlibrary{layered}
\begin{document}
\tikz [gr/.style={gray!50}, font=\bfseries]
\graph [layered layout] {
A -- C -- F [>minimum layers=2],
{ [nodes=gr, edges=gr] A -- B -- { E, D -- F [>weight=0] } },
};
\end{document}
答案2
我不是图论专家,但如果我理解这里的算法,你需要不止一层才能检测到交叉点。还要注意,最小化并不等于删除所有。所以添加更多层看起来是可行的。
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{graphs, graphdrawing}
\usegdlibrary{layered}
\begin{document}
\tikz [gr/.style={gray!50}, font=\bfseries]
\graph [layered layout,minimum layers=2] {
A -- C -- F,
{ [nodes=gr, edges=gr] A -- B -- { E, D -- F } }
};
\end{document}