16

I'd like to draw an angle transmitter:

enter image description here

The following code shows what I have come up with so far, which is basically nothing. I can't figure out how to fill up for cells per quadrant... in a radial fashion. I've succeeded with rectangles and circles of some sort, but not this one.

Starting at 12 o'clock and going counter-clockwise, the pattern is 8f(ull)-8e(mpty) cells on the outer ring, then the same on the 2nd outer ring with an offset of 4 cells, then 4f-4e with an offset of 2 cells and the inner ring has a 2f-2e pattern with an offset of one.

\documentclass[
a4paper
]{scrartcl}

\usepackage{
    newtxtext,
    amsmath,
}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}

\usepackage{tikz}
\usetikzlibrary{
    external,
}

\listfiles

\begin{document}
\begin{center}
    \begin{tikzpicture}[font=\small]
    \draw[thick] (0,0) circle [radius=2cm];
    \draw[thick] (0,0) circle [radius=4cm];
%   \foreach \a in {2,2.5,...,4}
%       \foreach \w in {0,22.5,45,...,337.5} {
%   \fill ($(\w:\a;
%   }
    \end{tikzpicture}
\end{center}
\end{document}
1
  • 1
    A lovely visual example of Gray code...
    – Leeser
    Apr 26, 2014 at 17:46

7 Answers 7

9

Here is a layman's solution. No filling but draw the arc with line width=0.5cm.

\documentclass[
a4paper
]{scrartcl}

\usepackage[T1]{fontenc}
\usepackage{tikz}

\begin{document}
\begin{center}
    \begin{tikzpicture}[font=\small]
    \foreach \x in {0,22.5,...,337.5}{
        \draw (0,0) -- (\x:4cm);
    }
    \foreach \x in {2,2.5,...,4}{
    \draw[thick] (0,0) circle [radius=\x cm];
    }
    \draw[thick,fill=white] (0,0) circle [radius=2cm];
     \foreach \w/\t in {22.5/67.5,112.5/157.5,202.5/247.5,292.5/337.5} {
       \draw[line width=0.5cm] (\w:2.25) arc(\w:\t:2.25);
   }
   \foreach \w/\t in {135/225,315/405} {
       \draw[line width=0.5cm] (\w:2.75) arc(\w:\t:2.75);
   }
   \foreach \w/\t in {180/360} {
       \draw[line width=0.5cm] (\w:3.25) arc(\w:\t:3.25);
   }
   \foreach \w/\t in {90/270} {
       \draw[line width=0.5cm] (\w:3.75) arc(\w:\t:3.75);
   }
    \end{tikzpicture}
\end{center}
\end{document}

enter image description here

5
  • Inner circle is not correct.
    – Tarass
    Apr 25, 2014 at 8:41
  • One could use \draw (\x,2cm) -- (\x:4cm); for the first foreach loop instead of making a filled white circle but this works as well of course.
    – henry
    Apr 25, 2014 at 14:53
  • @henry Did you install pgf 3.0.0 by now ?
    – Tarass
    Apr 25, 2014 at 15:49
  • @Tarass Yes I have it installed ever since it came out: screenshot from my TeX Live Manager.
    – henry
    Apr 25, 2014 at 15:58
  • @henry And you still have errors with Mark Wibrow's answers ?
    – Tarass
    Apr 25, 2014 at 16:07
14

Here you have a starting point. It's based in Jake's wheelchart

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

% The main macro
% #1 - List of value/color pairs
% #2 - inner radius
% #3 - outer radius
\newcommand{\wheelchart}[3]{
    % Calculate total
    \pgfmathsetmacro{\totalnum}{0}
    \foreach \value/\colour in {#1} {
        \pgfmathparse{\value+\totalnum}
        \global\let\totalnum=\pgfmathresult
    }

    % Calculate the thickness and the middle line of the wheel
    \pgfmathsetmacro{\wheelwidth}{(#3)-(#2)}
    \pgfmathsetmacro{\midradius}{(#3+#2)/2}

    % Rotate so we start from the top
    \begin{scope}[rotate=90]
    % Loop through each value set. \cumnum keeps track of where we are in the wheel
        \pgfmathsetmacro{\cumnum}{0}
        \foreach \value/\colour in {#1} {
            \pgfmathsetmacro{\newcumnum}{\cumnum + \value/\totalnum*360}

      % Draw the color segments.
            \draw[draw, fill=\colour] (-\cumnum:#2) arc (-\cumnum:-\newcumnum:#2)--(-\newcumnum:#3) arc (-\newcumnum:-\cumnum:#3)--cycle;

       % Set the old cumulated angle to the new value
            \global\let\cumnum=\newcumnum
      }
      \end{scope}
}

\begin{tikzpicture}


\wheelchart{1/white,1/black,1/black,1/white,1/white,1/black,1/black,1/white,1/white,1/black,1/black,1/white,1/white,1/black,1/black,1/white}{3cm}{3.5cm}

\wheelchart{1/white,1/white,1/black,1/black,1/black,1/black,1/white,1/white,1/white,1/white,1/black,1/black,1/black,1/black,1/white,1/white}{3.5cm}{4cm}

\wheelchart{1/white,1/white,1/white,1/white,1/black,1/black,1/black,1/black,1/black,1/black,1/black,1/black,1/white,1/white,1/white,1/white}{4cm}{4.5cm}

\wheelchart{1/white,1/white,1/white,1/white,1/white,1/white,1/white,1/white,1/black,1/black,1/black,1/black,1/black,1/black,1/black,1/black}{4.5cm}{5cm}
\end{tikzpicture}

\end{document}

enter image description here

4
  • If \value it's just to rotate, you can add something licke \foreach \color [count = \value]… And, moreover, it would be great if instead of black/white you could write 1/0.
    – Manuel
    Apr 25, 2014 at 8:32
  • Inner circle is not correct.
    – Tarass
    Apr 25, 2014 at 8:41
  • @Tarass: Code and figure corrected.
    – Ignasi
    Apr 25, 2014 at 8:52
  • @Manuel: This code was just an example of how to use the general wheelchart function. Of course it can be improved or simplified for this particular case, but it will loose its flexibility.
    – Ignasi
    Apr 25, 2014 at 8:55
10

Not ideal, but a marginally cleaner way to specify the full/empty sectors. Also it exploits the default rules for filling so creates "holes" in the rectangular overlay, so having to fill the circles with the right color is unnecessary.

Requires the latest PGF release for the math library (which is arguably not essential here, but provides a simpler way to define/calculate values).

\documentclass[tikz,border=5]{standalone}
\usetikzlibrary{math}
\begin{document}
\begin{tikzpicture}[every sector/.style={draw}, sector-1/.style={fill=black}, sector-0/.style={fill=white}]
\tikzmath{%
  \n = 16; \N = 4;
  \R1 = 1; \R2 = 2;
  \th = (\R2-\R1) / \N;
  \st = 360 / \n;
  \S = 1;
}
\foreach \s [count=\i from 0,
  evaluate={\a=90+\i*\st; \r=\R2-floor(\i/\n)*\th;}] in 
 {%
    1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,
    0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,
    0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,
    0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0%
 }
   \path [every sector/.try, sector-\s] 
     (\a:\r) arc (\a:\a+\st:\r) -- 
     (\a+\st:\r-\th) arc (\a+\st:\a:\r-\th) -- cycle;

\filldraw [fill=white, rotate=\S*\st-\st/2] 
  (\R1-\th/2,-\th/2) rectangle (\R2+\th/2,\th/2)
  \foreach \i in {1,...,\N}{ (\R1+\th*\i-\th/2,0) circle [radius=\th/3] };
\end{tikzpicture}
\end{document}

enter image description here

7
  • IMHO the best answer here. Bravo for the "filled rectangle but circles not" trick ! I'll notice that. What does 'every sector/.try' mean ?
    – Tarass
    Apr 25, 2014 at 12:18
  • Hm, it doesn't work, it says ! Package tikz Error: tikz math library: Unknown function or keyword '\N ='. But my TikZ version on TeX Live 2013 is up-to-date.
    – henry
    Apr 25, 2014 at 13:12
  • @Tarass using the .try handler means an error won't occur if the every sector key doesn't exist. It is a bit unnecessary in this case as clearly that key is defined. Apr 25, 2014 at 13:41
  • @henry although I am using the CVS version, the math library hasn't been changed for just over 6 months and not since the last release. If that is the version in TeX Live 2013 then I'm not sure why it isn't working in your case. Apr 25, 2014 at 13:50
  • I use texlive 2013 but I install over the last version of pfg tokz : 3.0.0 and it works fine.
    – Tarass
    Apr 25, 2014 at 14:27
8

enter image description here

Edit More compact code :

\documentclass[tikz]{standalone}
\usetikzlibrary{calc}


\xdef\IntRad{2}
\xdef\Rad{.5}

\newcommand{\Sector}[2][]{%
    \draw[#1] (22.5:#2) arc (22.5:0:#2)
            --(#2+\Rad,0) arc (0:22.5:#2+\Rad)
            -- cycle ;
    }

\begin{document}
\begin{tikzpicture}

\foreach \Loop [count=\j from 0] in {%
    {white,,,white,white,,,white,white,,,white,white,,,white},
    {,,white,white,white,white,,,,,white,white,white,white,,},
    {white,white,white,white,white,white,white,white,,,,,,,,},
    {white,white,white,white,,,,,,,,,white,white,white,white}}
    {\foreach \col [count=\i from 0] in \Loop {%
        \begin{scope}[rotate={22.5*\i}]
        \Sector[fill=\col]{\IntRad+\j*\Rad} ;   
        \end{scope}
        }
    }
\begin{scope}[rotate=11.75]
    \draw[fill=white] (\IntRad-.2,-.5*\Rad) rectangle (\IntRad+.2+4*\Rad,.5*\Rad) ;

    \foreach \col [count=\i from 0, evaluate=\i as \j using 0.5+\i]
        in {white,black,white,white} {%
        \draw[fill=\col] (\IntRad+\j*\Rad,0) circle (.25*\Rad) ;
    }
\end{scope}
\end{tikzpicture}
\end{document}
6

Here is my solution made with LuaLaTeX and TikZ without any white filling and using some inverse clipping so any background color will be shown thorugh the holes (see second picture):

\documentclass[a4paper]{article}

\usepackage{luacode}
\usepackage{tikz}

\usetikzlibrary{calc}

% inverse clipping from: http://tex.stackexchange.com/a/59168/8844
\tikzset{
    invclip/.style={clip,%
        insert path={{[reset cm] %
            (-16383.99999pt,-16383.99999pt) rectangle (16383.99999pt,16383.99999pt)%
        }}
    }
}

\begin{luacode*}
    function draw_figure()

        tex.sprint([[\begin{tikzpicture}]])

        tex.sprint([[\begin{scope}[rotate=11.25] ]])
        tex.sprint([[\draw (2.25cm, 0.25cm) rectangle (4.75cm, -0.25cm)]])
        tex.sprint([[(2.75cm, 0) circle [radius=0.15cm] ]])
        tex.sprint([[(3.25cm, 0) circle [radius=0.15cm] ]])
        tex.sprint([[(3.75cm, 0) circle [radius=0.15cm] ]])
        tex.sprint([[(4.25cm, 0) circle [radius=0.15cm];]])
        tex.sprint([[\end{scope}]])

        -- inverse clipping from: http://tex.stackexchange.com/a/59168/8844
        tex.sprint([[\begin{pgfinterruptboundingbox}]])
        tex.sprint([[\path[invclip, rotate=11.25] (2.25cm, 0.25cm) rectangle (4.75cm, -0.25cm)]])
        tex.sprint([[(2.75cm, 0) circle [radius=0.15cm] ]])
        tex.sprint([[(3.25cm, 0) circle [radius=0.15cm] ]])
        tex.sprint([[(3.75cm, 0) circle [radius=0.15cm] ]])
        tex.sprint([[(4.25cm, 0) circle [radius=0.15cm];]])
        tex.sprint([[\end{pgfinterruptboundingbox}]])

        for radius = 2.5, 4.5, 0.5 do
            tex.sprint([[\draw (0,0) circle [radius=]])
            tex.sprint(radius)
            tex.sprint([[cm];]])
        end

        for angle = 0, 359, 22.5 do
            tex.sprint([[\draw[rotate=]])
            tex.sprint(angle)
            tex.sprint([[] (2.5cm, 0) -- (4.5cm, 0);]])
        end

        fillmatrix = {{0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0},
            {1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1},
            {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1},
            {0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0}}

        cols = #fillmatrix[1]
        rows = #fillmatrix

        offset = 2.5

        for i = 1, rows do

            angle = 0

            for j = 1, cols do
                if fillmatrix[i][j] == 1 then
                    tex.sprint([[\fill ($(0, 0) + (]])
                    tex.sprint(angle)
                    tex.sprint([[:]])
                    tex.sprint(offset)
                    tex.sprint([[cm)$) arc (]])
                    tex.sprint(angle)
                    tex.sprint([[:]])
                    tex.sprint(22.5 + angle)
                    tex.sprint([[:]])
                    tex.sprint(offset)
                    tex.sprint([[cm) -- ($(0, 0) + (]])
                    tex.sprint(22.5 + angle)
                    tex.sprint([[:]])
                    tex.sprint(offset + 0.5)
                    tex.sprint([[cm)$) arc (]])
                    tex.sprint(22.5 + angle)
                    tex.sprint([[:]])
                    tex.sprint(angle)
                    tex.sprint([[:]])
                    tex.sprint(offset + 0.5)
                    tex.sprint([[cm) -- cycle;]])
                end

                angle = angle + 22.5
            end

            offset = offset + 0.5
        end

        -- naive filling solution:
        -- for angle = 0, 359, 90 do
        --  tex.sprint([[\fill[rotate=]])
        --  tex.sprint(angle)
        --  tex.sprint([[] ($(0, 0) + (22.5:2.5cm)$) arc (22.5:67.5:2.5cm) -- ($(0, 0) + (67.5:3.0cm)$) arc (67.5:22.5:3.0cm) -- cycle;]])
        -- end
        -- for angle = 0, 359, 180 do
        --  tex.sprint([[\fill[rotate=]])
        --  tex.sprint(angle)
        --  tex.sprint([[] ($(0, 0) + (135:3.0cm)$) arc (135:225:3.0cm) -- ($(0, 0) + (225:3.5cm)$) arc (225:135:3.5cm) -- cycle;]])
        -- end
        -- tex.sprint([[\fill ($(0, 0) + (180:3.5cm)$) arc (180:360:3.5cm) -- ($(0, 0) + (360:4.0cm)$) arc (360:180:4.0cm) -- cycle;]])
        -- tex.sprint([[\fill ($(0, 0) + (90:4.0cm)$) arc (90:270:4.0cm) -- ($(0, 0) + (270:4.5cm)$) arc (270:90:4.5cm) -- cycle;]])

        tex.sprint([[\end{tikzpicture}]])
    end
\end{luacode*}

\begin{document}

\luadirect{draw_figure()}

\end{document}

I've made this into a parametrized function where you can set the values of the chart's inner radius, outer radius (measured in centimeters), and set the position of the ruler. The following code has some examples included, however I show some of them here also.

\documentclass[a4paper]{article}

\usepackage{luacode}
\usepackage{tikz}

\usetikzlibrary{calc}

% inverse clipping from: http://tex.stackexchange.com/a/59168/8844
\tikzset{
    invclip/.style={clip,%
        insert path={{[reset cm] %
            (-16383.99999pt,-16383.99999pt) rectangle (16383.99999pt,16383.99999pt)%
        }}
    }
}

\begin{luacode*}
    function draw_chart(fillmatrix, inner_radius, outer_radius, ruler_step)

        cols = #fillmatrix[1]
        rows = #fillmatrix

        angle_offset = 360 / cols

        radius_offset = (outer_radius - inner_radius) / rows

        tex.sprint([[\begin{tikzpicture}]])

        if ruler_step >= 1 and ruler_step <= cols then
            tex.sprint([[\begin{scope}[rotate=]])
            tex.sprint(angle_offset * ruler_step - angle_offset / 2)
            tex.sprint([[] ]])
            tex.sprint([[\draw (]])
            tex.sprint(inner_radius - radius_offset * 0.5)
            tex.sprint([[cm, ]])
            tex.sprint(radius_offset * 0.5)
            tex.sprint([[cm) rectangle (]])
            tex.sprint(outer_radius + radius_offset * 0.5)
            tex.sprint([[cm, ]])
            tex.sprint(radius_offset * -0.5)
            tex.sprint([[cm)]])
            for i = inner_radius, (outer_radius - radius_offset), radius_offset do
                tex.sprint([[(]])
                tex.sprint(i + radius_offset * 0.5)
                tex.sprint([[cm, 0) circle [radius=]])
                tex.sprint(radius_offset * 0.5 * 0.6)
                tex.sprint([[cm] ]])
            end
            tex.sprint([[;]])
            tex.sprint([[\end{scope}]])

            -- inverse clipping from: http://tex.stackexchange.com/a/59168/8844
            tex.sprint([[\begin{pgfinterruptboundingbox}]])
            tex.sprint([[\path[invclip, rotate=]])
            tex.sprint(angle_offset * ruler_step - angle_offset / 2)
            tex.sprint([[] (]])
            tex.sprint(inner_radius - radius_offset * 0.5)
            tex.sprint([[cm, ]])
            tex.sprint(radius_offset * 0.5)
            tex.sprint([[cm) rectangle (]])
            tex.sprint(outer_radius + radius_offset * 0.5)
            tex.sprint([[cm, ]])
            tex.sprint(radius_offset * -0.5)
            tex.sprint([[cm)]])
            for i = inner_radius, (outer_radius - radius_offset), radius_offset do
                tex.sprint([[(]])
                tex.sprint(i + radius_offset * 0.5)
                tex.sprint([[cm, 0) circle [radius=]])
                tex.sprint(radius_offset * 0.5 * 0.6)
                tex.sprint([[cm] ]])
            end
            tex.sprint([[;]])
            tex.sprint([[\end{pgfinterruptboundingbox}]])
        end

        for radius = inner_radius, outer_radius, radius_offset do
            tex.sprint([[\draw (0,0) circle [radius=]])
            tex.sprint(radius)
            tex.sprint([[cm];]])
        end

        for angle = 0, 359, angle_offset do
            tex.sprint([[\draw[rotate=]])
            tex.sprint(angle)
            tex.sprint([[] (]])
            tex.sprint(inner_radius)
            tex.sprint([[cm, 0) -- (]])
            tex.sprint(outer_radius)
            tex.sprint([[cm, 0);]])
        end

        radius = inner_radius

        for i = 1, rows do

            angle = 0

            for j = 1, cols do
                if fillmatrix[i][j] == 1 then
                    tex.sprint([[\fill ($(0, 0) + (]])
                    tex.sprint(angle)
                    tex.sprint([[:]])
                    tex.sprint(radius)
                    tex.sprint([[cm)$) arc (]])
                    tex.sprint(angle)
                    tex.sprint([[:]])
                    tex.sprint(angle + angle_offset)
                    tex.sprint([[:]])
                    tex.sprint(radius)
                    tex.sprint([[cm) -- ($(0, 0) + (]])
                    tex.sprint(angle + angle_offset)
                    tex.sprint([[:]])
                    tex.sprint(radius + radius_offset)
                    tex.sprint([[cm)$) arc (]])
                    tex.sprint(angle + angle_offset)
                    tex.sprint([[:]])
                    tex.sprint(angle)
                    tex.sprint([[:]])
                    tex.sprint(radius + radius_offset)
                    tex.sprint([[cm) -- cycle;]])
                end

                angle = angle + angle_offset
            end

            radius = radius + radius_offset
        end

        tex.sprint([[\end{tikzpicture}]])
    end
\end{luacode*}

\begin{document}

\setlength{\parindent}{0pt}

With this code you can set the inner and outer radius of the chart, and also set the position of the ruler.

inner radius = 2.5cm\\
outer radius = 4.5cm\\
ruler position = 1

\luadirect{
    fillmatrix = {{0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0},
        {1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1},
        {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1},
        {0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0}}

    draw_chart(fillmatrix, 2.5, 4.5, 1)
}

inner radius = 1cm\\
outer radius = 3cm\\
ruler position = 10

\luadirect{draw_chart(fillmatrix, 1, 3, 10)}

You can disable the ruler, by setting its position to zero.

inner radius = 0cm\\
outer radius = 2cm\\
ruler position = 0

\luadirect{
    fillmatrix = {{0, 0, 0, 0, 1, 1, 1, 1},
    {0, 0, 1, 1, 0, 0, 1, 1},
    {0, 1, 0, 1, 0, 1, 0, 1}}

    draw_chart(fillmatrix, 0, 2, 0)
}

You can also use this chart to visualize binary numbers. The third 3 bit binary number (binary 010 = octal 2 = decimal 2 = hexadecimal 2):

\luadirect{draw_chart(fillmatrix, 1, 2, 3)}

The sixteenth 4 bit binary number (binary 1111 = octal 17 = decimal 15 = hexadecimal F):

\luadirect{
    fillmatrix = {{0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1},
        {0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1},
        {0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1},
        {0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1}}

    draw_chart(fillmatrix, 2, 3, 16)
}

The sixth 5 bit binary number (00101):

\luadirect{
    fillmatrix = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
        {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1},
        {0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1},
        {0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1},
        {0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1}}

    draw_chart(fillmatrix, 3, 6, 6)
}

\end{document}

left

  • inner radius = 1cm, outer radius = 3cm, ruler position= 10

right

  • inner radius = 2.5cm, outer radius = 4.5cm, ruler position = 1

You can also use this chart to visualize binary numbers.

left:

  • the third 3 bit binary number (binary 010 = octal 2 = decimal 2 = hexadecimal 2)
  • inner radius = 1cm, outer radius = 2cm, ruler position = 3

right:

  • the sixteenth 4 bit binary number (binary 1111 = octal 17 = decimal 15 = hexadecimal F)
  • inner radius = 2cm, outer radius = 3cm , ruler position = 16
6

We can draw this in polar coordinates using nonlinear polar transform. To "fill", we draw thick lines.

\documentclass[tikz]{standalone}
\usepgfmodule{nonlineartransformations}

% from the manual 103.4.2 Installing Nonlinear Transformation
\makeatletter
\def\polartransformation{\pgfmathsincos@{\pgf@x}\pgf@x=\pgfmathresultx\pgf@y\pgf@y=\pgfmathresulty\pgf@y}
\makeatother

\begin{document}
  \begin{tikzpicture}
    \begin{scope}[x=90/4pt,y=2mm,yshift=1.5cm]
      % set the polar transform
      \pgftransformnonlinear{\polartransformation}
      % draw the polar grid
      \draw[yshift=-1mm] (0,0) grid[xstep=1,ystep=1] (16,4);
      % draw thick "straight" lines to fill
      \draw[line width=2mm,red,opacity=.7]
        (-1,0) foreach~in{1,...,4}{++(2,0) -- ++(2,0)}
        (6,1) -- ++(12,0)
        (8,2) -- ++(8,0)
        (4,3) -- ++(8,0);
    \end{scope}
    % draw the 4 holes in the rectangle
    \draw[fill=white,rotate=13,xshift=13mm]
      foreach~in{1,...,4}{++(2mm,0) circle(.7mm)} (0,-1.2mm) rectangle (1,1.2mm);
  \end{tikzpicture}
\end{document}

enter image description here

Note: If we remove the polar transform, we can see that we draw the following grid.

enter image description here

1
  • +1, very clever. I would though draw the filled rectangles before the grid, so you can use opaque filling colors
    – quinmars
    Oct 24, 2015 at 22:17
0

To observe how arcs and filling work you can add inside your tikzpicture :

%How arc works
    \draw[blue,->] (0,3.5) arc [radius=3.5, start angle=90, delta angle=90];
%Now filling
    \filldraw[fill=gray] (3.5,0) arc [radius=3.5, start angle=0, delta angle=90]
        -- (0,4) arc [radius=4, start angle=90, delta angle=-90]
        -- cycle;
    \filldraw[fill=red] (0,-3.5) arc [radius=3.5, start angle=270, delta angle=90]
        -- (4,0) arc [radius=4, start angle=0, delta angle=-90]
        -- cycle;

And here is an example within a loop, where a bit of trigonometry gives you the formula:

\foreach \a in {0,1} {
% filling in the loop
    \filldraw[fill=green!50!black] ({3.5*cos((-\a*(pi/8)+(pi/2)) r)},{3.5*sin((-\a*(pi/8)+(pi/2)) r)}) 
        arc [radius=3.5, start angle={((pi/2)+(-pi/8)*\a) r}, delta angle={(-pi/8) r}]
        -- ({4*cos((-(\a+1)*(pi/8)+(pi/2)) r)},{4*sin((-(\a+1)*(pi/8)+(pi/2)) r)}) 
        arc [radius=4, start angle={((pi/2)+(-pi/8)*(\a+1)) r}, delta angle={pi/8 r}]
        -- cycle;
% corresponding arcs
    \draw[thick,blue,->] ({3.5*cos((-\a*(pi/8)+(pi/2)) r)},{3.5*sin((-\a*(pi/8)+(pi/2)) r)}) 
        arc [radius=3.5, start angle={((pi/2)+(-pi/8)*\a) r}, delta angle={(-pi/8) r}];
    \draw[thick,red,->] ({4*cos((-(\a+1)*(pi/8)+(pi/2)) r)},{4*sin((-(\a+1)*(pi/8)+(pi/2)) r)}) 
        arc [radius=4, start angle={((pi/2)+(-pi/8)*(\a+1)) r}, delta angle={pi/8 r}];
}

You must log in to answer this question.

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