请考虑下图:
我希望能够计算变量名中的数学表达式。例如,我希望能够写入(a$\i+1$\j)
以下代码来生成上述输出:
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{calc}
\begin{document}
\begin{tikzpicture}[>=to]
\node (a) at (0,0) {};
\foreach \i in {0,1,2,3}
\foreach \j in {0,1,2}
\node (a\i\j) at ($(a) + (\i, -\j)$) {};
\foreach \i in {0,1,2}
\foreach \j in {0,1,2}
\draw[->] (a\i\j) -- (a$\i+1$\j);
\foreach \i in {0,1,2,3}
\foreach \j in {0,1}
\draw[->,dotted] (a\i\j) -- (a\i$\j+1$);
\end{tikzpicture}
\end{document}
有没有办法在不使用 pgfmathsetmacro 和 pgfmathtruncatemacro 等 pgf 宏的情况下实现此功能,这些宏感觉有点不靠谱?另外,有没有更好的方法来生成图表?
答案1
您可以使用count
-loop 函数foreach
。与ifnum
此结合使用非常强大,而且非常神奇。这样,您还可以将所有代码放入一个循环中,并节省一些编译时间。
请参阅以下代码:
\documentclass[tikz, border=5mm]{standalone}
\begin{document}
\begin{tikzpicture}
\foreach \x [count=\xx from -1] in {0,...,3} {
\foreach \y [count=\yy from -1] in {0,...,3} {
\node (a\x\y) at (\x,-\y) {};
\ifnum\xx>-1
\draw [->] (a\xx\y) -- (a\x\y);
\fi
\ifnum\yy>-1
\draw [->, dotted] (a\x\yy) -- (a\x\y);
\fi
}
}
\end{tikzpicture}
\end{document}
答案2
您可以尝试使用evaluate
的选项\foreach
,但我更喜欢使用更简单的方法\pgfmathtruncatemacro
来执行算术计算:
代码:\pgfmathtruncatemacro
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{calc}
\begin{document}
\begin{tikzpicture}[>=to]
\node (a) at (0,0) {};
\foreach \i in {0,1,2,3}
\foreach \j in {0,1,2}
\node (a\i\j) at ($(a) + (\i, -\j)$) {};
\foreach \i in {0,1,2}
\pgfmathtruncatemacro{\IncrementI}{\i+1}%
\foreach \j in {0,1,2}
\draw[->] (a\i\j) -- (a\IncrementI\j);
\foreach \i in {0,1,2,3}
\foreach \j in {0,1}
\pgfmathtruncatemacro{\IncrementJ}{\j+1}%
\draw[->,dotted] (a\i\j) -- (a\i\IncrementJ);
\end{tikzpicture}
\end{document}
代码:evaluate
:
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{calc}
\begin{document}
\begin{tikzpicture}[>=to]
\node (a) at (0,0) {};
\foreach \i in {0,1,2,3}
\foreach \j in {0,1,2}
\node (a\i\j) at ($(a) + (\i, -\j)$) {};
\foreach [evaluate={\IncrementI=int(\i+1)}] \i in {0,1,2}
\foreach \j in {0,1,2}
\draw[->] (a\i\j) -- (a\IncrementI\j);
\foreach \i in {0,1,2,3}
\foreach [evaluate={\IncrementJ=int(\j+1)}] \j in {0,1}
\draw[->,dotted] (a\i\j) -- (a\i\IncrementJ);
\end{tikzpicture}
\end{document}
答案3
$
我们可以破解坐标解析器,这样 OP 所需的语法就成为可能。如果calc
库已加载,这仅适用于不以 开头的命名坐标,并且如果 的类别代码$
发生更改(例如,变为活动状态),则根本不可能起作用:
\documentclass[tikz,border=5]{standalone}
\makeatletter
\let\tikz@@parse@node=\tikz@parse@node
\def\tikz@parse@node#1(#2){%
\pgfutil@in@{$}{#2}%$
\ifpgfutil@in@%
\let\tikz@next=\tikz@parse@node@calc%
\else%
\let\tikz@next=\tikz@@parse@node%
\fi%
\tikz@next{#1}(#2)%
}
\def\tikz@parse@node@calc#1(#2$#3$#4){%
\pgfmathparse{\tikzcoordinatefunction{#3}}%
\edef\tikz@tmp{#2\pgfmathresult#4}%
\def\tikz@marshal{\tikz@parse@node{#1}}%
\expandafter\tikz@marshal\expandafter(\tikz@tmp)%
}
\def\tikzcoordinatefunction#1{int(#1)}
\begin{document}
\begin{tikzpicture}
\foreach \i in {1,...,4}
\foreach \j in {1,...,4}
\node (a\i\j) at (\j, -\i) {};
\foreach \i in {1,...,4}
\foreach \j in {1,...,3}
\draw [->] (a\i\j) -- (a\i$\j+1$);
\foreach \i in {1,...,3}
\foreach \j in {1,...,4}
\draw [->, dotted] (a\i\j) -- (a$\i+1$\j);
\end{tikzpicture}
\end{document}