12

For a document I am working on, I wanted to be able to draw polygon graphs. The graphs are to be labelled with the integers from 0 to n - 1, for some n. I wanted to write a macro that could be called inside a tikzpicture to draw such a graph, when supplied with the number of edges (n) and the "radius" of the graph (distance of each vertex from the centre). It turned out to be quite a frustrating experience because trying to use mathematical expressions involving macro arguments in TikZ's \foreach is not straightforward and results in many baffling error messages, but eventually I realised I just need to use \pgfmathparse to avoid the hassle. Yet I now have a perfectly good graph, except that the edges are "wonky" - each edge seems to connect from one node to a point slightly off the next node. Why is this happening? Here is a screengrab of what I am getting:

Here is a minimal working example.

\documentclass[a4paper]{amsart}

\usepackage{tikz}

\tikzset{graph/.style = {every node/.style = { draw,
                                               shape = circle,
                                               fill = black,
                                               minimum size = 0.8mm,
                                               inner sep = 0mm,
                                               label distance = 0.8mm
                                               }}}

\newcommand{\circumferencenode}[3]{\node (#1) at (#3: #2) [label = #3: $#1$] {};}
\newcommand{\polygon}[2]{
    \pgfmathparse{subtract(#1, 1)}
    \foreach \x in {0, ..., \pgfmathresult} {
        \pgfmathparse{90 - 360 * \x / #1}
        \circumferencenode{\x}{#2}{\pgfmathresult}
    }
    \pgfmathparse{subtract(#1, 1)}
    \foreach \x in {0, ..., \pgfmathresult} {
        \pgfmathparse{mod(\x + 1, #1)}
        \draw (\x) -- (\pgfmathresult);
    }
}

\begin{document}
    \begin{tikzpicture}[graph]
        \polygon{6}{10mm}
    \end{tikzpicture}
\end{document}

2 Answers 2

12

Your big problem is with \pgfmathparse{mod(\x + 1, #1)}, because the results are 1.0, 2.0... and not 1,2... With (nodename.x), you select a point on the border of node nodename in angle x.

Some advices:

  • Use \pgfmathsetmacro to store the result of a math expression (float) in a macro.
  • Use \pgfmathtruncatemacro to store the result of a math expression (integer) in a macro.
  • Use \typeout to show (and debug) your results.
  • With default math engine, you can't exceed 16383.99999 during calculation, so use {90-360/#1*\x} instead of {90-360*\x/#1}.

So, here is your MWE :

enter image description here

\documentclass{standalone}
\usepackage{tikz}
\tikzset{graph/.style = {every node/.style = { draw,
                                               circle,
                                               fill = black,
                                               minimum size = 0.8mm,
                                               inner sep = 0mm,
                                               }}}

\newcommand{\circumferencenode}[3]{
  \node[label = #3: $#1$] (p#1) at (#3: #2)  {};
}
\newcommand{\polygon}[2]{
    \pgfmathtruncatemacro{\nminusone}{#1 - 1}
    \foreach \x in {0, ..., \nminusone} {
        \pgfmathsetmacro{\angle}{90 - 360 / #1 * \x}
        \circumferencenode{\x}{#2}{\angle}
    }
    \foreach \x in {0,...,\nminusone} {
        \pgfmathtruncatemacro{\next}{mod(\x + 1, #1)}
        \typeout{\next}
        \draw (p\x) -- (p\next);
    }
}

\begin{document}
\begin{tikzpicture}[graph]
  \polygon{6}{10mm}
\end{tikzpicture}
\end{document}
11

There is also the possibility of using directly the library shapes.geometric and the shape regular polygon.

One might proceed as follows:

\documentclass[a4paper]{amsart}

\usepackage{tikz}
\usetikzlibrary{shapes.geometric}

\tikzset{
        new polygon/.code 2 args={
        \node[regular polygon, regular polygon sides=#1, draw,minimum size=1.7cm] (s) {};
        \foreach \corner in {1,...,#1}{
         \pgfmathparse{90-360 * (\corner-1) / #1}
         \node at (\pgfmathresult:#2)[label={[font=\small]\pgfmathresult:$\corner$}]{};
         \node[fill=black,circle, minimum size=0.8mm,inner sep=0mm] at (s.corner \corner){};
        }
    }
}

\begin{document}
\tikz[baseline]\node[new polygon={9}{9mm}] {}; \hspace*{0.5cm}
\tikz[baseline]\node[new polygon={5}{8mm}] {}; \hspace*{0.5cm}
\tikz[baseline]\node[new polygon={11}{7mm}] {};  
\end{document}

The result:

enter image description here

1
  • Thanks for your advice. I chose Paul's answer because he explained why the graph was incorrect as well as giving a fix, but I appreciate it.
    – Hammerite
    Commented Dec 2, 2012 at 11:11

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .