我正在尝试使用 ipe 绘图程序创建这个图表,但想用它来TikZ
比较最终的质量。
但是只想使用相对定位来实现,而不必使用at
坐标或使用硬编码xshift
等等。也就是说,我想告诉 tikz 将一个节点放在另一个节点的左下方,并让它从右侧出来。
问题是,当我添加更多节点时,它们会相互重叠。这是我的尝试。图中的前两行看起来不错:
\documentclass[12pt]{article}
\usepackage{tikz}
\usetikzlibrary{shapes,arrows}
\usetikzlibrary{positioning,fit}
\usepackage[margin=1in]{geometry}
\tikzset{block/.style={draw, text width=5em , inner sep=2pt, text centered} }
\begin{document}
\begin{tikzpicture}[auto]
\node[block] (ode) {Differential equation};
\node[block] (firstOrder) [below left=of ode] {First order ode};
\node[block] (secondOrder) [below=of ode] {Second order ode};
\node[block](higherOrder) [below right=of ode] {Higher order ode};
\end{tikzpicture}
\end{document}
这并不难。现在的问题在于添加下一行时。我只使用相对定位。现在变成了这样
\documentclass[12pt]{article}
\usepackage{tikz}
\usetikzlibrary{shapes,arrows}
\usetikzlibrary{positioning,fit}
\usepackage[margin=1in]{geometry}
\tikzset{block/.style={draw, text width=5em , inner sep=2pt, text centered} }
\begin{document}
\begin{tikzpicture}[auto]
\node[block] (ode) {Differential equation};
\node[block] (firstOrder) [below left=of ode] {First order ode};
\node[block] (secondOrder) [below=of ode] {Second order ode};
\node[block](higherOrder) [below right=of ode] {Higher order ode};
\node[block] (firstOrderLinear) [below left=of firstOrder] {First order linear in $y'$};
\node[block] (firstOrderNonLinear) [below right=of firstOrder] {First order none linear in $y'$};
\node[block] (secondOrderLinear) [below left=of secondOrder] {Linear second order ode};
\node[block] (secondOrderNonLinear) [below right=of secondOrder] {None linear second order ode};
\node[block] (higherOrderLinear) [below left=of higherOrder] {Linear higher order ode};
\node[block] (higherOrderNonLinear) [below right=of higherOrder] {None linear higher order ode (not implemented)};
\end{tikzpicture}
\end{document}
您会看到某些节点彼此重叠并且位置不正确。
我认为它会自动排列第三行的节点,使它们不重叠且均匀分布,我只需要告诉它相对位置。
我知道我可以通过xshift
根据需要添加显式的负值和正值来解决这个问题。但重点不在于这样做。我希望这能自动完成。否则,手动将每个节点定位到应在的位置将变得非常困难。
也许我做得不对。
在 tikz 中执行此操作的正确方法是什么没有在代码中使用硬编码坐标和任何硬编码数字?最终的流程图将比这复杂得多,我试图避免在其中使用硬编码坐标和数字,并且只在可能的情况下使用相对定位,因为这将使以后的修改更容易。
更新
作为解决方法,我找到了这个解决方案。我对它不太不满意,因为它实现了我想要的效果:避免对每个节点使用硬编码的坐标和移位。解决方案是对图表的每一层使用一个行矩阵。这是新代码。
\documentclass[12pt]{article}
\usepackage{tikz}
\usetikzlibrary{shapes,arrows}
\usetikzlibrary{positioning,fit}
\usepackage[margin=1in]{geometry}
\tikzset{block/.style={draw, text width=5em , inner sep=2pt, text centered} }
\begin{document}
\begin{tikzpicture}[auto]
\node[block] (ode) {Differential equation};
\matrix[column sep=4pt] at(0,-2) {
\node[block] (firstOrder) {First order ode}; &
\node[block] (secondOrder) {Second order ode}; &
\node[block](higherOrder) {Higher order ode};\\
};
\matrix[column sep=4pt] at(0,-4) {
\node[block] (firstOrderLinear) {First order linear in $y'$}; &
\node[block] (firstOrderNonLinear) {First order none linear in $y'$}; &
\node[block] (secondOrderLinear) {Linear second order ode}; &
\node[block] (secondOrderNonLinear) {None linear second order ode}; &
\node[block] (higherOrderLinear) {Linear higher order ode}; &
\node[block] (higherOrderNonLinear) {None linear higher order ode (not implemented)};\\
};
\draw[->] (ode)--(firstOrder);
\draw[->] (ode)--(secondOrder);
\draw[->] (ode)--(higherOrder);
\draw[->] (firstOrder)--(firstOrderLinear.north);
\draw[->] (firstOrder)--(firstOrderNonLinear.north);
\draw[->] (secondOrder)--(secondOrderLinear.north);
\draw[->] (secondOrder)--(secondOrderNonLinear.north);
\draw[->] (higherOrder)--(higherOrderLinear.north);
\draw[->] (higherOrder)--(higherOrderNonLinear.north);
\end{tikzpicture}
\end{document}
给予
我只需要告诉 tikz 每个矩阵的位置。就这些。我需要做更多的工作来使箭头看起来像 IPE 绘图中的那样,但这只是小问题。
但我还是想知道是否有仅使用相对定位的解决方案。
更新 2
为了完成,这里是使用 forest 包的解决方案。我认为这个是最简单的一个
\documentclass[12pt]{article}
\usepackage[edges]{forest}
\usepackage[margin=1in]{geometry}
\tikzset{block/.style={draw, text width=5em , inner sep=2pt, text centered} }
\newcommand\set[1]{\fbox{\begin{minipage}{0.8in}\raggedright%
#1
\end{minipage}}
}
\begin{document}
\begin{forest}
for tree={edge+={->}} %to have arrow instead of just line
%
[\set{Differential equation}
[\set{First order ode}
[\set{First order linear in $y'$}]
[\set{First order none linear in $y'$}]
]
[\set{Second order ode}
[\set{Linear second order ode}]
[\set{None linear second order ode}]
]
[\set{Higher order ode}
[\set{Linear higher order ode}]
[\set{None linear higher order ode (not implemented)}]
]
]
\end{forest}
\end{document}
另一个选择是使用for tree={forked edge,edge+={->}}
上面的替代,这将提供此版本
另一个选择是将上面的命令更改\set
为
\usepackage{fancybox}
\newcommand\set[1]{\shadowbox{\noindent\begin{minipage}{0.8in}\raggedright%
#1
\end{minipage}}
}
这给出了
答案1
相对定位并不像您想象的那样。它不会自动布局以避免重叠。它只是一种指定放置节点位置的方法。您无需绝对指定位置(这实际上仍然是相对的,但它是相对于坐标系或页面的),而是指定相对于一个或多个其他坐标或节点的位置。
如果您说“将此放在 上方 5 厘米a
和 左侧 1 厘米处b
”,则该项目将放置在 上方 5 厘米a
和 左侧 1 厘米处b
。Ti钾Z 不会检查是否适合或避免重叠。
如果你说“把这个放在右边a
”,这意味着“把这个放在默认距离右边a
,上面 0pt a
”。所以这就是 Ti钾Z 会放它。
如果你想要一种避免重叠等的方法,你需要使用可以做到这一点的东西forest
,例如 Ti 的绘图工具钾Z、amatrix of nodes
或其他。
简而言之,您询问的是一种用木槌削土豆皮的方法,并且在有人提供蔬菜削皮刀时坚称您不想使用它。
我会使用蔬菜削皮器,并找到木槌的另一种用途:
\documentclass[12pt]{article}
\usepackage[edges]{forest}
\usetikzlibrary{arrows}
\usepackage[margin=1in]{geometry}
\usepackage{array}
\newcolumntype{C}[1]{>{\centering\arraybackslash}m{#1}}
\begin{document}
\noindent
\begin{forest}
for tree={
edge+={->},
draw,
anchor=child anchor,
inner sep=0pt,
align=C{5em},
},
forked edges,
[Differential equation
[First order ode
[{First order linear in $y'$. $F(x,y,y')=0$}
]
[{First order nonlinear in $y'$. ODE has form $f(x,y,y')$}
]
]
[Second order ode
[Linear second order ode
]
[Nonlinear second order ode
]
]
[Higher order ode
[Linear higher order ode
]
[Nonlinear higher order ode (not implemented)
]
]
]
\end{forest}
\end{document}