4

i need to draw this timing wheel image in tikz. Can anyone help me? I just tried to start drawing a normal circular array image, but this isn't the result that i want.

timing wheel

EDIT:

This is my attempt:

\documentclass[tikz]{standalone}
\begin{document}
\begin{tikzpicture}[>=latex,font=\sffamily,semithick,scale=2.5]
\draw [thick] (0,0) circle (1);
\foreach \angle in {90,67.5,...,-67.5}
\draw (\angle:1) -- (\angle-180:1);
\node [circle,thick,fill=white,draw=black,align=center,minimum size=3.5cm] at (0,0) {};
\draw [->] (0,0) -- (0.4,0.6);
\end{tikzpicture}
\end{document}
  • 2
    Welcome to TeX.SX. Questions about how to draw specific graphics that just post an image of the desired result are really not reasonable questions to ask on the site. Please post a minimal compilable document showing that you've tried to produce the image and then people will be happy to help you with any specific problems you may have. See minimal working example (MWE) for what needs to go into such a document. – Martin Schröder Dec 1 '15 at 21:53
  • Can you share what you tried, even if the output isn't what you want? – cfr Dec 1 '15 at 21:56
  • @cfr i have edited the post with my attempt – Simon Dec 1 '15 at 22:00
  • If you want to highlight (fill) sections, then each section needs to be a closed loop (two arsc and two radials). This would probably work better as a macro than a pic. – John Kormylo Dec 1 '15 at 22:27
  • @JohnKormylo Why? I'd written the code for a pic solution before reading your comment. It seems to work, but is there a pitfall in doing it this way? – cfr Dec 1 '15 at 23:44
4

You could use pics to define the shapes you need. Here, I use 2 pics - timer and tick. The first of these takes a single argument which specifies 'where on the clock' the shading should be done and the arrow drawn. The second draws an arrow for the Tick!.

I use a counter timer to name both kinds of pic because the current code for pics is buggy and naming them in the way suggested in the manual no longer works. (For example, the seagull example in the manual has not compiled for some time.)

\newcounter{timer}
\setcounter{timer}{0}

We next define the two pics:

\tikzset{
  timer/.pic={
    \stepcounter{timer}

Increment the counter so each instance gets a unique identifier, starting from 1.

    \begin{scope}[scale=2.5]

We start by just filling a circle and creating the shadow. We don't draw it yet because we want to shade the segment on the border before drawing the lines.

      \fill [fill=white, drop shadow] (0,0) circle (1);

Now for a loop which does most of the heavy lifting. It is just an expanded version of the original in the question:

      \foreach \i [count=\j from 0] in {90,67.5,...,-247.5}
      {
        \ifnum\j>#1

#1 is the shaded segment which the arrow points to. If we've already done that, the labels need to just be the number of the loop we are in. We also draw the lines, as in the original loop in the question.

          \draw (\i:1.2) node (timer\thetimer-\j) {\j} (\i:1) -- (\i:0.7) ;
        \else

Otherwise, the label is not just the number of the loop. We want the value of the loop number plus 16, so we save this:

          \pgfmathsetmacro\modon{int(16+\j)}

We have 2 cases: either we are in the highlighted segment or we aren't.

          \ifnum\j=#1

If we are, we start by filling the segment with grey:

            \fill [gray] (\i:1) arc (\i:\i-22.5:1) -- (\i-22.5:.7) arc (\i-22.5:\i:.7) -- cycle;

Now we draw the lines and add the double label which is the value we just calculated, a forward slash and the loop number:

            \draw (\i:1.2) node (timer\thetimer-\j) {\modon/\j} (\i:1) -- (\i:0.7) ;
          \else

If not, we are before the target segment, so we draw the lines and write the label with the value of 16 plus the loop number:

            \draw (\i:1.2) node (timer\thetimer-\j) {\modon} (\i:1) -- (\i:0.7) ;
          \fi
        \fi
      }

Now we draw the inner and outer circles:

      \draw [thick] (0,0) circle (1) circle (.7);

Finally, we add the arrow:

      \draw [-{Triangle[]}, draw=cyan!75!blue!75, line width=1mm] (0,0) -- (90-#1*22.5-11.25:.71);
    \end{scope}
  },

Nest for the tick pic, which is just a filled arrow shape with the text 'Tick!':

  tick/.pic={
    \node (tick\thetimer) [shape=single arrow, fill=yellow!50!orange!50, draw=yellow!50!orange, pic actions, transform shape, drop shadow] {Tick!};

For convenience, we create a named coordinate at the arrow's tip:

    \coordinate (tick\thetimer-tip) at (tick\thetimer.east);
  }
}

We've defined the pics above so that first timer is timer1, the second timer2 etc. and the first tick is tick1 etc.

In addition, we've named the tip of the tick with tick<number>-tip and we've named each label on the border of the timer with the value of the label modulo 16. For example,

  • timer1-4 is the node containing the label marking the fourth point on the first timer i.e. what would be the .east anchor of timer1 if timer1 were a node rather than a pic;
  • timer2-0 would be the northern-most label of the second timer (labelled 16/0 or 16).

Probably a picture would be easier than trying to explain this ;):

ticking timers

So the tick arrow can be placed relative to (timer1-4.east) which is the centre right anchor for the label 4 for the leftmost timer. Then timer2 is placed relative to (tick1.east) which is the centre right point of the arrow i.e. its tip. Or, equivalently, we could use (tick1-tip).

That is, having set up the code for the pics, we can draw the diagram above by just saying:

\begin{tikzpicture}[font=\sffamily,semithick]
  \pic  {timer=0};
  \path (timer1-4.east) ++(1,0) pic {tick} (tick1.east) ++(3.5,0) pic {timer=1};
\end{tikzpicture}

Or, for a more complex example,

\begin{tikzpicture}[font=\sffamily,semithick]
  \pic  {timer=0};
  \path (timer1-4.east) ++(1,0) pic {tick} (tick1-tip) ++(3.5,0) pic {timer=1} (timer2-8.south) ++(0,-1) pic [rotate=-90] {tick} (tick2-tip) ++(0,-3.5) pic {timer=11} (timer3-12.west) ++(-1,0) pic [rotate=-180] {tick} (tick3-tip) ++(-3.5,0) pic {timer=14};
\end{tikzpicture}

to produce

tick-tock-tick-tock

Complete code:

\documentclass[tikz,border=10pt,multi]{standalone}
\usetikzlibrary{shadows,arrows.meta,shapes.arrows}
\begin{document}
\newcounter{timer}
\setcounter{timer}{0}
\tikzset{
  timer/.pic={
    \stepcounter{timer}
    \begin{scope}[scale=2.5]
      \fill [fill=white, drop shadow] (0,0) circle (1);
      \foreach \i [count=\j from 0] in {90,67.5,...,-247.5}
      {
        \ifnum\j>#1
          \draw (\i:1.2) node (timer\thetimer-\j) {\j} (\i:1) -- (\i:0.7) ;
        \else
          \pgfmathsetmacro\modon{int(16+\j)}
          \ifnum\j=#1
            \fill [gray] (\i:1) arc (\i:\i-22.5:1) -- (\i-22.5:.7) arc (\i-22.5:\i:.7) -- cycle;
            \draw (\i:1.2) node (timer\thetimer-\j) {\modon/\j} (\i:1) -- (\i:0.7) ;
          \else
            \draw (\i:1.2) node (timer\thetimer-\j) {\modon} (\i:1) -- (\i:0.7) ;
          \fi
        \fi
      }
      \draw [thick] (0,0) circle (1) circle (.7);
      \draw [-{Triangle[]}, draw=cyan!75!blue!75, line width=1mm] (0,0) -- (90-#1*22.5-11.25:.71);
    \end{scope}
  },
  tick/.pic={
    \node (tick\thetimer) [shape=single arrow, fill=yellow!50!orange!50, draw=yellow!50!orange, pic actions, transform shape, drop shadow] {Tick!};
    \coordinate (tick\thetimer-tip) at (tick\thetimer.east);
  }
}
\begin{tikzpicture}[font=\sffamily,semithick]
  \pic  {timer=0};
  \path (timer1-4.east) ++(1,0) pic {tick} (tick1.east) ++(3.5,0) pic {timer=1};
\end{tikzpicture}
\setcounter{timer}{0}
\begin{tikzpicture}[font=\sffamily,semithick]
  \pic  {timer=0};
  \path (timer1-4.east) ++(1,0) pic {tick} (tick1-tip) ++(3.5,0) pic {timer=1} (timer2-8.south) ++(0,-1) pic [rotate=-90] {tick} (tick2-tip) ++(0,-3.5) pic {timer=11} (timer3-12.west) ++(-1,0) pic [rotate=-180] {tick} (tick3-tip) ++(-3.5,0) pic {timer=14};
\end{tikzpicture}
\end{document}
  • It will take me days to understand your answer not to draw it :) – Diaa Aug 27 '16 at 21:23
  • 1
    @DiaaAbidou Well, you can always ask. However, I did try to explain the modifications I made as clearly as I could ;). – cfr Aug 27 '16 at 22:01

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.