我正在尝试使用 tikzpicture 绘制一棵树,如下所示:
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{math}
\begin{document}
\begin{tikzpicture}
\tikzstyle{node}=[circle, fill=blue!25, minimum size=0.1 cm];
\foreach \ilayer in {0,...,3} {
\tikzmath {\nnodes = 3 ^ \ilayer; }
\tikzmath {\leftnum = 1 - floor(\nnodes / 2) - 1; }
\tikzmath {\rightnum = \nnodes - floor(\nnodes / 2) - 1; }
\foreach \isibling in {\leftnum,...,\rightnum} {
\tikzmath {\d = 3 ^ (- \ilayer) * 15; }
\tikzmath {\x = \isibling * \d; }
\tikzmath {\y = - \ilayer * 2; }
\node[node] (node_\ilayer_\isibling) at (\x cm, \y cm) {\isibling};
}
}
\end{tikzpicture}
\end{document}
我得到了如下图所示的树。文本是\isibling
每一层内的节点。大多数节点都是整数,但所有最左边的节点都不是整数。
答案1
你可以告诉 Ti钾Z 明确表示你想要一个整数。
\documentclass[tikz,border=3.14mm]{standalone}
\usetikzlibrary{math}
\begin{document}
\begin{tikzpicture}
\tikzset{mynode/.style={circle, fill=blue!25, minimum size=0.1 cm}}
\foreach \ilayer in {0,...,3} {
\tikzmath {\nnodes = 3 ^ \ilayer; }
\tikzmath {\leftnum = int(1 - floor(\nnodes / 2) - 1); }
\tikzmath {\rightnum = \nnodes - floor(\nnodes / 2) - 1; }
\foreach \isibling in {\leftnum,...,\rightnum} {
\tikzmath {\d = 3 ^ (- \ilayer) * 15; }
\tikzmath {\x = \isibling * \d; }
\tikzmath {\y = - \ilayer * 2; }
\node[mynode] (node_\ilayer_\isibling) at (\x cm, \y cm) {\isibling};
}
}
\end{tikzpicture}
\end{document}
或者
\documentclass[tikz,border=3.14mm]{standalone}
\usetikzlibrary{math}
\begin{document}
\begin{tikzpicture}
\tikzset{mynode/.style={circle, fill=blue!25, minimum size=0.1 cm}}
\foreach \ilayer in {0,...,3} {
\tikzmath {int \nnodes,\leftnum,\rightnum;
\nnodes = 3 ^ \ilayer;
\leftnum = 1 - floor(\nnodes / 2) - 1;
\rightnum = \nnodes - floor(\nnodes / 2) - 1; }
\foreach \isibling in {\leftnum,...,\rightnum} {
\tikzmath {\d = 3 ^ (- \ilayer) * 15;
\x = \isibling * \d;
\y = - \ilayer * 2; }
\node[mynode] (node_\ilayer_\isibling) at (\x cm, \y cm) {\isibling};
}
}
\end{tikzpicture}
\end{document}
原则上,这里不需要数学库。
\documentclass[tikz,border=3.14mm]{standalone}
\begin{document}
\begin{tikzpicture}
\tikzset{mynode/.style={circle, fill=blue!25, minimum size=0.1 cm}}
\foreach \ilayer [evaluate=\ilayer as \nnodes using {int(3 ^ \ilayer)},
evaluate=\nnodes as \leftnum using {int(1 - floor(\nnodes / 2) - 1)},
evaluate=\nnodes as \rightnum using {int(\nnodes - floor(\nnodes / 2) - 1)}]
in {0,...,3} {
\foreach \isibling
[evaluate=\ilayer as \d using {3 ^ (- \ilayer) * 15},
evaluate=\isibling as \x using {\isibling * \d},
evaluate=\ilayer as \y using {- \ilayer * 2}]
in {\leftnum,...,\rightnum} {
\node[mynode] (node_\ilayer_\isibling) at (\x cm, \y cm)
{\isibling};
}
}
\end{tikzpicture}
\end{document}
答案2
正如 @marmot 所说,你在这里不需要tikzmath
,但如果你使用它,你可以用更有效的方式做到这一点:
- 您可以使用一个
\tikzmath
包含循环的命令。 - 您可以声明您的整数变量,这样
int
您之后就不需要再做任何事情了int()
。 - 奇怪的是,
\nnodes
您不需要\rightnum
分开;\leftnum
\rightnum = - \leftnum
- 为什么使用
1-floor(\nnodes/2)-1
代替-floor(\nnodes/2)
? - 该值
\d
可以在外循环中计算。 - 除了使用之外,
\x=\isibling*\d
您还可以说[x=\d cm]
,然后使用\isibling
as\x
。同样,也可以通过使用\y
来替换。\ilayer
[y=-2cm]
因此,这是我的建议:
\documentclass[tikz,border=7pt]{standalone}
\usetikzlibrary{math}
\begin{document}
\begin{tikzpicture}
\tikzstyle{node}=[circle, fill=blue!25, minimum size=0.1 cm];
\tikzmath{
int \ilayer,\nnodes,\rightnum,\isibling;
\nnodes = 1;
for \ilayer in {0,...,3}{
\rightnum = (\nnodes-1)/2;
\d = 15/\nnodes;
for \isibling in {-\rightnum,...,\rightnum}{
{
\path[x=\d cm,y=-2cm]
node[node] (node_\ilayer_\isibling) at (\isibling, \ilayer) {\isibling};
};
};
\nnodes = 3*\nnodes;
};
}
\end{tikzpicture}
\end{document}