7

How can I draw a path of nodes forming a circle with tikz?

I have tried placing the nodes manually with

\documentclass[tikz]{standalone}

\usetikzlibrary{arrows,positioning}

\begin{document}
\begin{tikzpicture}[->,node distance=2cm, auto, thick,main node/.style={circle,fill=blue!20,draw}]

  \node[main node] (1) {A};
  \node[main node] (2) [above left=of 1] {B};
  \node[main node] (3) [above right=of 1] {C};
  \node[main node] (4) [above=of 2] {D};
  \node[main node] (5) [above=of 3] {E};

  \path[draw, every node/.style={font=\sffamily\small}] (1) -- (2) -- (4) -- (5) -- (3) -- cycle;
\end{tikzpicture}
\end{document}

but it's very difficult to organize them properly. I think it is easily to do with only 4 nodes but I need 5 nodes. I wonder if I can draw the nodes with a path.

Edit

Sorry, I forgot to tell that I need arrows between the nodes and I want different texts in each node.

Can I still use a foreach? I can perhaps make a list of the texts and let the foreach determine which element in the list to draw?

7

Nodes on a regular polygon

It is possible to put circular nodes with various sizes on a circle and corners of a regular polygon and draw arrows between them, which are also on the circle.

\documentclass{article}

\usepackage{tikz}
\usetikzlibrary{bending}

\begin{document}
\begin{tikzpicture}[
  ->,   
  thick,
  main node/.style={circle, fill=blue!20, draw},
]
  \newcommand*{\MainNum}{5}
  \newcommand*{\MainRadius}{1.5cm} 
  \newcommand*{\MainStartAngle}{90}

  % Print main nodes, node names: p1, p2, ...
  \path
    (0, 0) coordinate (M)
    \foreach \t [count=\i] in {A, Hello\\World, 3, foobar, $\cdot$} {
      +({\i-1)*360/\MainNum + \MainStartAngle}:\MainRadius)
      node[main node, align=center] (p\i) {\t}
    }
  ;  

  % Calculate the angle between the equal sides of the triangle
  % with side length \MainRadius, \MainRadius and radius of circle node
  % Result is stored in \p1-angle, \p2-angle, ...
  \foreach \i in {1, ..., \MainNum} {
    \pgfextracty{\dimen0 }{\pgfpointanchor{p\i}{north}} 
    \pgfextracty{\dimen2 }{\pgfpointanchor{p\i}{center}}
    \dimen0=\dimexpr\dimen2 - \dimen0\relax 
    \ifdim\dimen0<0pt \dimen0 = -\dimen0 \fi
    \pgfmathparse{2*asin(\the\dimen0/\MainRadius/2)}
    \global\expandafter\let\csname p\i-angle\endcsname\pgfmathresult
  }

  % Draw the arrow arcs
  \foreach \i [evaluate=\i as \nexti using {int(mod(\i, \MainNum)+1}]
  in {1, ..., \MainNum} {  
    \pgfmathsetmacro\StartAngle{   
      (\i-1)*360/\MainNum + \MainStartAngle
      + \csname p\i-angle\endcsname
    }
    \pgfmathsetmacro\EndAngle{
      (\nexti-1)*360/\MainNum + \MainStartAngle
      - \csname p\nexti-angle\endcsname
    }
    \ifdim\EndAngle pt < \StartAngle pt
      \pgfmathsetmacro\EndAngle{\EndAngle + 360}
    \fi
    \draw
      (M) ++(\StartAngle:\MainRadius)
      arc[start angle=\StartAngle, end angle=\EndAngle, radius=\MainRadius]
    ;
  }
\end{tikzpicture}
\end{document}

Result

Equidistant nodes

Instead of putting the nodes on the corners of a regular polygon, the nodes can be placed in such a way on the circle, that the arrows have equal lengths. The advantage is, that the main radius can be made smaller for a more compact presentation.

\documentclass{article}

\usepackage{tikz}
\usetikzlibrary{bending}

\begin{document}
\begin{tikzpicture}[
  ->,
  thick,
  main node/.style={circle, fill=blue!20, draw, align=center},
]
  \newcommand*{\MainRadius}{1.2cm}
  \newcommand*{\MainStartAngle}{90}

  \coordinate (M) at (0, 0);

  \newcommand*{\MainAngleSum}{0}
  \begin{scope}
    % First the nodes are only set, but clipped to get their size.
    % The final location is not yet known.
    \clip (M);
    \foreach \t [count=\i] in {A, Hello\\World, 3, foobar, $\cdot$} {
      \global\expandafter\let\csname p\i-text\endcsname\t
      \node[main node] (p\i) at (M) {\t};
      %
      \global\let\MainNum\i % the last assignment is number of nodes
      % Calculate the angle between the equal sides of the triangle
      % with side length \MainRadius, \MainRadius and radius of circle node
      % Result is stored in \p1-angle, \p2-angle, ...
      \pgfextracty{\dimen0 }{\pgfpointanchor{p\i}{north}}
      \pgfextracty{\dimen2 }{\pgfpointanchor{p\i}{center}}
      \dimen0=\dimexpr\dimen2 - \dimen0\relax
      \ifdim\dimen0<0pt \dimen0 = -\dimen0 \fi
      \pgfmathparse{2*asin(\the\dimen0/\MainRadius/2)}
      \global\expandafter\let\csname p\i-angle\endcsname\pgfmathresult
      \pgfmathparse{\MainAngleSum + 2*\csname p\i-angle\endcsname}
      \global\let\MainAngleSum\pgfmathresult
    }
  \end{scope}
  \pgfmathsetmacro\MainAngleStep{(360 - \MainAngleSum)/\MainNum}

  % Draw the nodes and arrow arcs
  \global\let\CurrentAngle\MainStartAngle
  \foreach \i in {1, ..., \MainNum} {
    \pgfmathsetmacro\AngleA{\CurrentAngle + \csname p\i-angle\endcsname}
    \pgfmathsetmacro\AngleB{\AngleA + \MainAngleStep}
    \draw
      (M) +(\CurrentAngle:\MainRadius)
      node[main node] {\csname p\i-text\endcsname}
      +(\AngleA:\MainRadius)
      arc[
        start angle=\AngleA,
        end angle=\AngleB,  
        radius=\MainRadius, 
      ]
      ;
    \ifnum\i<\MainNum
      \pgfmathparse{ 
        \AngleB
        + \csname p\the\numexpr\i+1\relax-angle\endcsname
      }
      \global\let\CurrentAngle\pgfmathresult
    \fi
  }
\end{tikzpicture}
\end{document}

Result equidistant

3

I would use polar coordinates:

\documentclass[border=5mm,tikz]{standalone}
\usepackage{tikz}
\begin{document}

  \begin{tikzpicture}
    \foreach \ang/\lab in {0/A,72/B,144/C,216/D,288/E} {
      \node[circle,fill=blue!20,draw] (\ang) at (\ang:2){\lab};
    }
    \draw(0)--(72)--(144)--(216)--(288)--(0);
  \end{tikzpicture}

\end{document}

enter image description here

  • I'm confused: why the -1? – Andrew Jun 15 '15 at 5:34
2

You can use polar coordinates and a \foreach loop:

\documentclass[tikz]{standalone}
\usetikzlibrary{arrows,positioning}

\begin{document}

\begin{tikzpicture}[
  ->,
  thick,
  main node/.style={circle,fill=blue!20,draw}
]
\foreach \Rotulo [count=\ci] in {C,E,D,B,A}
  \node[main node] (\ci) at (-90+\ci*360/5:2cm) {\Rotulo};
\path[draw, every node/.style={font=\sffamily\small}] 
  (1) -- (2) -- (3) -- (4) -- (5) -- (1);
\end{tikzpicture}

\end{document}

The result:

enter image description here

Another option is to use a regular polygon shape (requires the shapes.geometric library):

\documentclass[tikz]{standalone}
\usetikzlibrary{arrows,positioning,shapes.geometric}

\begin{document}

\begin{tikzpicture}[
  ->,
  thick,
  main node/.style={circle,fill=blue!20,draw}
]
\node[
  regular polygon, 
  regular polygon sides=5, 
  draw,
  inner sep=1cm
  ] 
  (pentagon) at (0,0) {};
\foreach \Rotulo [count=\ci] in {C,E,D,B,A}
  \node[main node] (\ci) at (pentagon.corner \ci) {\Rotulo};
\end{tikzpicture}

\end{document}

enter image description here

Update:

\documentclass[tikz]{standalone}
\usetikzlibrary{arrows,positioning}

\begin{document}

\begin{tikzpicture}[
  ->,
  thick,
  main node/.style={circle,fill=blue!20,draw}
]
\foreach \Rotulo [count=\ci] in {C,E,D,B,A}
  \node[main node] (\ci) at (-90+\ci*360/5:2cm) {\Rotulo};
\draw 
  (1) to[out=85,in=-40] (2);
\draw 
  (2) to[out=155,in=25] (3);
\draw 
  (3) to[out=225,in=95] (4);
\draw 
  (4) to[out=295,in=175] (5);
\draw 
  (5) to[out=5,in=245] (1);
\end{tikzpicture}

\end{document}

enter image description here

For other ways to get a circular array of arrows between the nodes, see the answers to connect nodes that it looks like circle.

  • Great! Can I also draw arrows between the nodes? And is it possible to draw a circle instead of a polygon? – Jamgreen Jun 14 '15 at 20:00
  • @Jamgreen Of course. Please see my updated answer. – Gonzalo Medina Jun 14 '15 at 20:03
1

You can also use smartdiagram

\documentclass{standalone}

\usepackage{smartdiagram}

\begin{document}

\smartdiagramset{module shape=circle}
\smartdiagram[circular diagram]{A, B, C, D, E}

\end{document}

enter image description here

  • \usetikzlibrary{bending} improves the arrow heads. – Heiko Oberdiek Jun 15 '15 at 14:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.