I want to add the following figure in the presentation of a paper I read. I read a small introduction to tikz but still the figure is very complicated for me to do. Can anybody help or point any guides to help me?
Ok, let’s work it through.
I used the through
library because we can simply use the anchors of the node as a reference and don’t have to worry where the circle exactly is in our picture.
Styles
I defined three styles:
- the
dot node
style is for the simple nodes on the circle, I have usedfill=white
so that the circle is not seen in the circle. This works best with a simple background. - the
dotdot node
inherits thedot node
style but also places a filled dot inside it (disguised as a label). - the
arc style
is for the arc arrows in the circle, the shorten amount is needed so that the|
part of the arrow overlap for connecting arrows. For more discussion and other solutions on that matter, see TikZ arrow tip is displaced
The dotdot node
style expects two mandatory arguments. The one is used to name the node, the second is used for any options for the label. We use this later to place a pin at the label (the black dot in the node).
TikZ picture options
The options to the tikzpicture
are:
thick
,every ping edge/.style={<-}
which sets the arrow style for the pins. If you use other pins in your code, you will need to change this and declare a separate style that is used for the pin edge.>=latex
sets the default arrow for the>
arrow tip. I don’t like theto
style much so I setlatex
here.
The following declare function
is used to declare some constants (the outer radius and the inner radius for the circle and the arrow arcs) and a function angleofNode
that takes on argument, the number of the node. As we place 23 nodes, this function easily calculates the angle on a circle.
We could have used also LaTeX macros, i.e.
\newcommand*{\outerR}{4}
\newcommand*{\innerR}{3.3}
\newcommand*{\angleofNode}[1]{(#1)/23*360}
and could have used these macro instead of the PGF math functions.
Drawing
The outer circle is easy. The circle through
key from the through
library is used to easily draw the circle. We name the node c
for the next steps.
The points on the circle are now accessible by c.east
, c.30
, c.170
, etc. We use this to place our simple dot node
s there. The \foreach
loop can be used to draw a bunch of nodes.
Another \foreach
loop is used to draw the dotdot node
s. In this same step we also draw the labels A_{<something>}
, name the dotdot node
s dd-<number>
and also the black dots inside the dotdot node
s. These are named ddd-<number>
, this is done by the first argument to the dotdot node
style. The second argument is used to for the pin
with the text T_{<something>}
.
In bot cases <something>
is the macro \tLabel
which we have declared for every step in the loop with the second value. The directions for the label and the pins are also defined in the loop. The \foreach
loop from TikZ is very powerful and has its own tag foreach. A short introduction can be found in Structure, Tuple or Dict for the foreach-loop in Tikz.
The third and final \foreach
loop is used to draw the arcs. Now, this is not that easy as we don’t have a circle to reference. Even if we had, we would have to draw the arc ourself.
The arc
path operator does not draw an arc from one point to another with a specified radius. It draws an arc from the last point on the path with a radius, a certain start and a certain end angle. (There is also delta angle
for when you only have one of the other angles.)
So, we need to move to one of the points on the arc: ({angleofNode(\sAngle)}:innerR)
. Then we draw an arc
with the radius of innerR
from the node \sAngle
to \eAngle
. Again, the angleofNode(<node number>)
function helps us to find the correct angle. Unfortunately, the placement of nodes along of arc
s is non-function (in the current release version of TikZ anyway), so I also place the node manually halfway along the path but .3cm
to the center. This has been discussed before in How to place a node in the middle of an arc?.
Code
\documentclass[tikz,convert=false]{standalone}
\usetikzlibrary{through,arrows}
\tikzset{
dot node/.style={
shape=circle,
fill=white,
draw,
inner sep=+0pt,
minimum size=+5mm
},
dotdot node/.style 2 args={
dot node,
label={[shape=circle,fill=black,outer sep=+0pt,inner sep=+0pt,minimum size=+3mm,name=ddd-#1,#2]center:}
},
arc style/.style={
|<->|,
shorten >=+-.5\pgflinewidth,
shorten <=+-.5\pgflinewidth,
}
}
\begin{document}
\begin{tikzpicture}[
thick,
every pin edge/.style={<-},
>=latex,
declare function/.list={
outerR=4;,
innerR=3.3;,
angleofNode(\a)=\a/23*360;}
]
\node [draw,circle through=(0:outerR)] (c) {};
\foreach \iAngle in {1,2,4,5,7,8,10,11,...,14,16,17,19,20,...,22}
\node[dot node] at (c.{angleofNode(\iAngle)}) {};
\foreach \iAngle/\tLabel/\lDir/\pDir in {0/3/above right/-10,%
3/2/above right/right,%
6/1/above/30,%
9/k/above left/above,%
15/l+1/below/left,%
18/l/below right/below}
\node[
dotdot node=\iAngle{pin={\pDir:{$T_{\tLabel}$}}},
label=\lDir:$A_{\tLabel}$
] (dd-\iAngle) at (c.{angleofNode(\iAngle)}) {};
\foreach \sAngle/\eAngle/\tLabel in {0/3/2,%
3/6/1,%
6/9/k,%
15/18/l}
\draw[arc style] ({angleofNode(\sAngle)}:innerR) arc[radius=innerR, start angle=angleofNode(\sAngle), end angle=angleofNode(\eAngle)]
node at ({angleofNode(\sAngle+\eAngle)/2}:innerR-.3) {$S_{\tLabel}$} ;
\end{tikzpicture}
\end{document}
Output
With PSTricks.
\documentclass[pstricks]{standalone}
\usepackage{pst-node,pst-plot}
\psset{saveNodeCoors}
\newcommand\MAL[4][1.5]{% Middle Arc Label
\rput(!#1 N-#3.y N-#3.x atan N-#2.y N-#2.x atan add 2 div PtoC){$#4$}}
\newcommand\NL[6][]{% Node Label
\qdisk(#2){3pt}
\uput{12pt}[#4](#2){$#3$}
\ifx\\#1\\%
\def\name{#5}
\else
\def\name{#1}
\fi
\uput{17pt}[#6](#2){\rnode{\name}{$#5$}}
\pcline[nodesepB=3pt,nodesepA=7pt]{->}(\name)(#2)}
\everypsbox{\scriptsize}
\begin{document}
\begin{pspicture}(-4,-4)(6,4)
% Big circle
\pscircle{2.5}
% Node declaration
\curvepnodes[plotpoints=24]{0}{360}{2.5 t PtoC}{P}
% Small circles
\multido{\i=0+1}{\Pnodecount}{\pscircle[fillstyle=solid](P\i){5pt}}
% Arcs
\begingroup
\psset{arrows=|<*->|*}
\psarc(0,0){2}{(P0)}{(P3)}
\psarc(0,0){2}{(P3)}{(P6)}
\psarc(0,0){2}{(P6)}{(P9)}
\psarc(0,0){2}{(P15)}{(P18)}
\endgroup
% Middle Arc Labels
\MAL{P0}{P3}{S_2}
\MAL{P3}{P6}{S_1}
\MAL{P6}{P9}{S_k}
\MAL{P15}{P18}{S_l}
% Node Labels
\NL{P0}{A_3}{15}{T_3}{-15}
\NL{P3}{A_2}{45}{T_2}{0}
\NL{P6}{A_1}{90}{T_1}{45}
\NL{P9}{A_k}{135}{T_k}{90}
\NL[TL1]{P15}{A_{l+1}}{-90}{T_{l+1}}{180}
\NL{P18}{A_l}{-45}{T_l}{-90}
% Others
\psarcn{->}{3.75}{35}{-20}
\uput{4}[7.5](0,0){\parbox{2cm}{\scriptsize Traverse\\Direction}}
\end{pspicture}
\end{document}
\foreach
command? That should make it much easier to place the circles automatically, compared to hard-coding them individually. Give that a try, and if you get stuck, edit your question to include the code you have so far, explaining what you've tried and what you're struggling with (at the moment, the question looks a little bit like a "draw-this-for-me" question). – Jake Jun 25 '13 at 15:33\foreach
(this should be quite easy to do). As for the black dot inside the white circle, that's possible with a simplefill
, no trickery needed, like so:\draw [fill=black] (36:5cm) circle (1mm);
(here the circle with the nodes has a radius of 5 cm and the first small circle at 36 deg, if we have 10 along the whole circle, so I center the dot in the small circle; the 1mm radius of the dot can be adjusted at will - maybe not the most elegant, but a simple, straightforward solution). – Count Zero Jun 25 '13 at 15:50