\foreach 和名称

\foreach 和名称

我正在尝试编写一个命令来使用 Tikz 绘制一个循环图,基本上是一个多边形。该命令的参数是顶点数 #1 和图形半径 #2。

我最初的想法是先绘制 #1 节点,给它们命名,然后用边将它们连接起来。代码如下

\newcommand{\cyclegraph}[2]{\begin{tikzpicture}
\foreach \n in {1,...,#1}{
    \node[circle,fill=black] (n\n) at ({\n*360/#1}:#2cm) {};
}
\foreach \n in {1,...,#1-1}{
    \draw (n\n) -- (n{1+\n})
}   

\draw (n#1) -- (n1);
\end{tikzpicture}}

不幸的是,\foreach 循环中的代码不起作用。错误消息为“Package pgf Error: No shape named n{1+1} is known. \cyclegraph{7}{2}”、“Package pgf Error: No shape named n{1+2} is known. \cyclegraph{7}{2}”等。显然,这是节点命名的问题。有办法解决这个问题吗?

当然,我可以将代码重写为

\newcommand{\cyclegraph}[2]{\begin{tikzpicture}
\foreach \n in {1,...,#1}{
    \node[circle,fill=black] (n\n) at ({\n*360/#1}:#2cm) {};
}
\foreach \n in {1,...,#1-1}{
    \draw ({\n*360/#1}:#2cm) -- ({(1+\n)*360/#1}:#2cm);
}   

\draw ({0}:#2cm) -- ({360/#1}:#2cm);
\end{tikzpicture}}

但我认为使用节点名称会更简洁。此外,这对以后的图形也很有用。有什么想法吗?

答案1

这是一个解决方案:

\documentclass[tikz]{standalone}
\newcommand{\cyclegraph}[2]{%
  \begin{tikzpicture}
    \foreach \n in {1,...,#1}{
      \node[circle,fill=black] (n\n) at ({\n*360/#1}:#2cm) {};
    }
    \foreach \n[evaluate={\n as \nnext using int(mod(\n,#1)+1)}] in {1,...,#1}{
      \draw (n\n) -- (n\nnext);
    }   
  \end{tikzpicture}%
}

\begin{document}
\cyclegraph{7}{2}
\end{document}

在此处输入图片描述

答案2

我有与此非常相似的代码。您可以根据自己的用例进行修改,生成以下代码:

在此处输入图片描述

使用代码:

\documentclass{article}
\usepackage{tikz}

\newcommand\CycleGraph[2][1]{%
  \begin{tikzpicture}
    \foreach \pt [evaluate=\pt as \ang using {90+(\pt-1)*360/#2}] in {1,...,#2}
    {
        \node[circle,fill=black] (\pt) at (\ang:#1) {};
    }
    \foreach \pt [remember=\pt as \Pt (initially #2)] in {1,...,#2}
    {
        \draw (\pt)--(\Pt);
    }
  \end{tikzpicture}
}
\begin{document}

  \CycleGraph[0.5]{3}
  \CycleGraph{4}

\end{document}

请注意,我已经定义了\CycleGraph一个可选参数,给出循环的半径,以及一个强制参数,给出点的数量。

实际上,我发现这些想法的以下变体更有用:我定义一个命令\EdgeGraph,将顶点数以及以逗号分隔的边列表作为参数。例如,\EdgeGraph{4}{1/2,2/3,3/4,4/1}\EdgeGraph{4}{1/2,2/3,3/4,4/1,1/3}产生:

在此处输入图片描述

代码如下\EdgeGraph

\documentclass{article}
\usepackage{tikz}

\newcommand\EdgeGraph[3][1]{%
  \begin{tikzpicture}
      \foreach \pt [evaluate=\pt as \ang using {90+(\pt-1)*360/#2}] in {1,...,#2}
      {
          \node[circle,fill=black] (\pt) at (\ang:#1) {};
      }
      \foreach \x/\y in {#3} {
          \draw (\x)--(\y);
      }
  \end{tikzpicture}%
}
\begin{document}

  \EdgeGraph{4}{1/2, 2/3, 3/4, 4/1}
  \EdgeGraph{4}{1/2, 2/3, 3/4, 4/1, 1/3}

\end{document}

我通常也有标记顶点的选项,但也许我现在太忘乎所以了!

答案3

问题是由你的第二个\foreach

\foreach \n in {1,...,#1-1}{
    \draw (n\n) -- (n{1+\n})
}

首先,缺少一个分号。其次,节点名称不支持计算(n{1+\n})。这只会给出节点名称(n{1+1})、、(n{1+2})... 并引发错误。

除了更通用的选项evaluate用于@PaulGaborit 的回答,这里我使用另一个选项remember(记录在 pgfmanual 3.1.5b 末尾,第 89 节)将\n上一次迭代中的值存储在 中\xn。在第一次迭代中,没有“上一次”,因此我将其初始化\xn为 1。我还将迭代列表更改为2, ..., #2

\documentclass{article}
\usepackage{tikz}

\newcommand{\cyclegraph}[2]{%
  \begin{tikzpicture}
    \foreach \n in {1,...,#1}{
        \node[circle,fill=black] (n\n) at ({\n*360/#1}:#2cm) {};
    }
    \foreach \n[remember=\n as \xn(initially 1)] in {2,...,#1}{
        \draw (n\xn) -- (n\n);
    }
    \draw (n#1) -- (n1);
  \end{tikzpicture}%
}

\begin{document}
  \cyclegraph{3}{2}
\end{document}

另外,发布完整的示例(也称为平均能量损失) 而不是完整的宏定义总是更好的。

相关内容