3

I want to draw this figure in Tikz (apologies for poor image quality):

enter image description here

However, I can't quite figure out a good way to go about it. The only way I know how to draw this is as follows:

  1. Declare a scope which includes arrows halfway along each line segment, and \draw each of the 14 line segments on the outside inside this scope.

  2. Manually \draw the rest of the lines and label them accordingly.

  3. Manually \fill the 8 shaded regions.

  4. Add the two arcs on the sides and label one \gamma.

Surely this is not the most efficient method. Using the calc package might save me a little calculation, but not much time overall. The only other way I've thought to do this is define a command which draws each unshaded triangle, and another which draws each shaded one, but I'm not sure how to automate the label placement, or how to declare a scope within newcommand to use my method for getting arrows on the sides.

What is the best way to draw something like this?

2 Answers 2

8

This uses Caramdir's solution from How to draw an arrow in the middle of the line?

Code

\documentclass[parskip]{scrartcl}
\usepackage[margin=15mm]{geometry}
\usepackage{tikz}
\usetikzlibrary{decorations.markings}
\usepackage{xifthen}

\begin{document}

\pgfmathsetmacro{\octagonradius}{3}
\pgfmathsetmacro{\octagonbigradius}{\octagonradius/sin(67.5)}

\begin{tikzpicture}
[   midarrow/.style={thick,decoration={markings,mark=at position 0.5 with {\arrow{>}}},postaction={decorate}}
]
    \foreach \x in {1,...,8}
    {   \ifthenelse{\isodd{\x}}
        {\xdef\mysign{1}}
        {\xdef\mysign{-1}}
        \fill[red,opacity=0.4,shift={(0,\mysign*\octagonradius)}] (0,0) -- (45*\x+22.5:\octagonbigradius) -- (45*\x+67.5:\octagonbigradius) -- cycle;
        \fill[blue,opacity=0.4,shift={(0,\mysign*\octagonradius)}] (0,0) -- (45*\x+22.5:\octagonbigradius) -- (45*\x-22.5:\octagonbigradius) -- cycle;
        \draw[shift={(0,\mysign*\octagonradius)}] (0,0) -- node[label=45*\x+112.5:1] {} (45*\x+22.5:\octagonbigradius);
        \draw[shift={(0,\mysign*\octagonradius)}] (0,0) -- node[label=45*\x+157.5:0] {} (45*\x+67.5:\octagonbigradius);
    }
    \foreach \x in {0,...,6}
    {   \ifthenelse{\isodd{\x}}
        {\xdef\mysign{1}}
        {\xdef\mysign{-1}}
        \draw[midarrow,shift={(0,\mysign*\octagonradius)}] (45*\x-22.5:\octagonbigradius) -- (45*\x-67.5:\octagonbigradius);
        \draw[midarrow,shift={(0,-1*\mysign*\octagonradius)}] (45*\x+112.5:\octagonbigradius) -- (45*\x+157.5:\octagonbigradius);
    }
    \draw[shift={(0,\octagonradius)}] (247.5:\octagonbigradius) -- (292.5:\octagonbigradius);
    \draw[very thick,->] (-\octagonbigradius,\octagonbigradius) to[bend right=40] node[left] {Y} (-\octagonbigradius,-\octagonbigradius);
    \draw[very thick,->] (\octagonbigradius,-\octagonbigradius) to[bend right=40] node[right] {Y} (\octagonbigradius,\octagonbigradius);
\end{tikzpicture}

\end{document}

Result

enter image description here

3
  • I think I see the general strategy you're using, but I don't understand what \xdef\mysign{1} is doing. Commented Sep 6, 2012 at 7:37
  • @AlexBecker: mysign is set to 1 if x is odd and to -1 if it is even. This is used for the shift of the drawing commands, so shifted up or shifted down. It would have also been possible to do if x odd then draw[red,shift up] else draw[red, shift down], but I didn't like putting the draw commands twice. Commented Sep 6, 2012 at 7:42
  • Thanks very much. I actually just realized that after staring at the code some more. I'm going to try using this method to make a similar drawing and see how things work out. Commented Sep 6, 2012 at 7:45
4

When you have something that is very periodic a \foreach loop is very encouraging. I have here shown a simple picture given you enough for you to start, but still limited to not be complete.

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{decorations.markings}
\begin{document}
\begin{tikzpicture}[%
  ->-/.style={%
      postaction={decorate},decoration={%
          markings,mark=at position #1 with {\arrow{stealth}}%
      }%
  },->-/.default=.5,%
  -<-/.style={
      postaction={decorate},decoration={%
          markings,mark=at position #1 with {\arrowreversed{stealth}}%
      }%
  },-<-/.default=.5]
  \foreach \angle [count=\i] in {22.5,67.5,...,337.5} {
      \ifodd\i\relax
      \draw[-<-] (0,0) -- node{0} (\angle-45:2cm) -- (\angle:2cm) -- cycle;
      \else
      \fill[->-] (0,0) -- node{1} (\angle-45:2cm) -- (\angle:2cm) -- cycle;
      \fi
  }
\end{tikzpicture}  
\end{document} 

I have chosen to use decorations as arrows. In that way it is easier to maintain and reuse the code. The style ->- defaults to drawing an arrow halfway on the path. And -<- draws one reversed. In order to get the 1 and 0 on the curve you need to use the node path halfway on the path.

The crude result:

enter image description here

1
  • I hadn't seen loops in TeX before. Thanks for the answer, it should help me with some of the other stuff I have to TeX. Commented Sep 6, 2012 at 7:24

You must log in to answer this question.

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