使用 \foreach 绘制的箭头指向 \node 的错误一侧

使用 \foreach 绘制的箭头指向 \node 的错误一侧

我注意到,如果我使用语句绘制节点,下面的 MWE 中的箭头会指向节点的错误一侧foreach,但如果我手动编写相同的绘制命令,则不会指向节点的错误一侧。哪里出了问题?

\documentclass{beamer}
\usepackage{tikz}

\begin{document}
\begin{frame}
\begin{tikzpicture}[scale=1.4]
\node[draw, thick, circle, minimum size=7mm] (xA0) at (0, 0) {};
\foreach \i in {1, ..., 3}{
  \node[draw, thick, circle, minimum size=7mm] (xA\i) at (\i, 0) {};
  \node[draw, thick, circle, minimum size=7mm] (xB\i) at (\i, -1) {};
}
\node[draw, thick, circle, minimum size=7mm] (xB4) at (4, -1) {};
\foreach \i in {0, ..., 3}{
  \pgfmathsetmacro\iplusone{\i+1};
  \draw[thick, -latex] (xA\i) -- (xB\iplusone);
  \ifnum\i<3
    \draw[thick, -latex] (xA\i) -- (xA\iplusone);
  \fi
  \ifnum\i>0
    \draw[thick, -latex] (xB\i) -- (xB\iplusone);
  \fi
}
\draw[thick, -latex, red] (xA0) -- (xB1);
\end{tikzpicture}
\end{frame}
\end{document}

目标是让箭头指向节点的最近端,而无需手动计算该点的位置;就像红色箭头一样。

在此处输入图片描述

答案1

通过在循环中定义额外的计数器:[count=\j from 2]你可以省略节点位置的计算\pgfmathsetmacro

\documentclass{beamer}
\usepackage{tikz}

\begin{document}
\begin{frame}
    \begin{tikzpicture}[scale=1.4,
  C/.style = {draw, thick, circle, minimum size=7mm},
arr/.style = {thick, -latex}
                        ]
]
\foreach \i [count=\j from 2] in {1,...,4}
{
  \node[C] (xA\i) at (\i, 0) {};
  \node[C] (xB\i) at (\j, -1) {};
\draw[arr] (xA\i) -- (xB\i);
}
\foreach  \i [count=\j from 2] in {1,2,3}
{
\draw[arr] (xA\i) -- (xA\j);
\draw[arr] (xB\i) -- (xB\j);
}
\end{tikzpicture}
\end{frame}
\end{document}

在此处输入图片描述

答案2

欢迎!原因是\pgfmathsetmacro\iplusone{\i+1},它会产生类似 的宏2.0,其中.0被解释为节点锚点(本例中为东锚点)。有很多方法可以解决这个问题,要么添加到int\pgfmathsetmacro要么使用 ,要么使用 \pgfmathtruncatemacro\the\numexpr例如

 \draw[thick, -latex] (xA\i) -- (xB\the\numexpr\i+1);

或使用 的评估键int。此循环可避免过度绘制一个箭头。以下是说明这一点的代码,下面可以找到更短且更符合人体工程学的代码:

\documentclass{beamer}
\usepackage{tikz}

\begin{document}
\begin{frame}
\frametitle{Some foreach loop}
\begin{tikzpicture}[scale=1.4]
\node[draw, thick, circle, minimum size=7mm] (xA0) at (0, 0) {};
\foreach \i in {1, ..., 3}{
  \node[draw, thick, circle, minimum size=7mm] (xA\i) at (\i, 0) {};
  \node[draw, thick, circle, minimum size=7mm] (xB\i) at (\i, -1) {};
}
\node[draw, thick, circle, minimum size=7mm] (xB4) at (4, -1) {};
\foreach \i [evaluate=\i as \j using {int(\i+1)}]in {0,...,3}{
  \ifnum\i<3
    \draw[thick, -latex] (xA\i) -- (xA\j);
  \fi
  \ifnum\i>0
    \draw[thick, -latex] (xB\i) -- (xB\j);
    \draw[thick, -latex] (xA\i) -- (xB\j);
  \else 
    \draw[thick, -latex, red] (xA0) -- (xB1);
  \fi
}

\end{tikzpicture}
\end{frame}
\end{document}

在此处输入图片描述

以上内容是为了解释为什么会发生这种情况。您不需要任何这些内容来绘制图表,一个循环就足够了。

\documentclass{beamer}
\usepackage{tikz}
\begin{document}
\begin{frame}
\begin{tikzpicture}[scale=1.4]
\path[nodes={draw, thick, circle, minimum size=7mm},
    every edge/.append style={thick, -latex}] 
 foreach \i in {0, ..., 3}{
  (\i, 0) node[] (xA\i)  {}
  (\i+1, -1) node[] (xB\i)   {}
  \ifnum\i>0
   (xA\i) edge (xB\i)
  \else
   (xA\i) edge[red] (xB\i)
  \fi
  \ifnum\i>0
   (xA\the\numexpr\i-1) edge (xA\i)
   (xB\the\numexpr\i-1) edge (xB\i)
  \fi};
\end{tikzpicture}
\end{frame}
\end{document}

在此处输入图片描述

相关内容