39

I am trying to recreate the following image using tikz:

polar_plot

So far, this is my code

\documentclass{article}    
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}[>=latex]
\fill[fill=lightgray] plot[domain=-pi/2:pi/2] (xy polar cs:angle=\x r,radius= {2-2*sin(\x r)});
\draw[thick,color=red,domain=0:2*pi,samples=200,smooth] plot (xy polar cs:angle=\x r,radius= {2-2*sin(\x r)});
\node at (2,1) {\scriptsize $r=2-2\sin\theta$};
\draw[->] (-4,0) -- (4,0);
\draw[->] (0,-5) -- (0,2);
\end{tikzpicture} 
\end{document}

which produces:

enter image description here

To complete it, I need to polar grid with the particular labeling. I am aware of the polar axis environment available in the pgfplots package. However, I am not familiar with pgfplots and would prefer a tikz solution. Any ideas? I fear I can't put off learning pgfplots much longer.

3
  • pgfplots isn't that hard if you know tikz, not using it would be much harder than learning a new package I guess ;-)
    – hugovdberg
    Apr 4, 2014 at 21:17
  • It is even guven in the pgfplots manual.
    – percusse
    Apr 4, 2014 at 21:29
  • I know, pgfplots appears to simplify many things, and I will work on it. As with most problems, knowing multiple ways of solving is beneficial! :-)
    – DJJerome
    Apr 5, 2014 at 11:56

8 Answers 8

31

Okay, here’s what I came up with. It isn’t in the “spirit” of the question, since I haven’t used any of TikZ’s polar coordinate features: instead, I just drew the grid on by hand and with some basic loops.

This is the code I used, with some hopefully self-explanatory comments:

\documentclass{article}    
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}[>=latex]

% Draw the lines at multiples of pi/12
\foreach \ang in {0,...,31} {
  \draw [lightgray] (0,0) -- (\ang * 180 / 16:4);
}

% Concentric circles and radius labels
\foreach \s in {0, 1, 2, 3} {
  \draw [lightgray] (0,0) circle (\s + 0.5);
  \draw (0,0) circle (\s);
  \node [fill=white] at (\s, 0) [below] {\scriptsize $\s$};
}

% Add the labels at multiples of pi/4
\foreach \ang/\lab/\dir in {
  0/0/right,
  1/{\pi/4}/{above right},
  2/{\pi/2}/above,
  3/{3\pi/4}/{above left},
  4/{\pi}/left,
  5/{5\pi/4}/{below left},
  7/{7\pi/4}/{below right},
  6/{3\pi/2}/below} {
  \draw (0,0) -- (\ang * 180 / 4:4.1);
  \node [fill=white] at (\ang * 180 / 4:4.2) [\dir] {\scriptsize $\lab$};
}

% The double-lined circle around the whole diagram
\draw [style=double] (0,0) circle (4);

\fill [fill=red!50!black, opacity=0.5] plot [domain=-pi/2:pi/2] (xy polar cs:angle=\x r,radius= {2-2*sin(\x r)});
\draw [thick,color=red,domain=0:2*pi,samples=200,smooth] plot (xy polar cs:angle=\x r,radius= {2-2*sin(\x r)});
\node [fill=white] at (2,1) {$r=2-2\sin\theta$};

\end{tikzpicture} 
\end{document}

and this is what it produces:

enter image description here

I have made a few tweaks to the original code, as well as my additions:

  • I’ve reordered some of the commands, so that things get drawn in the right order (so that, for example, thin grey lines don’t appear atop black ones)

  • Added an opacity=0.5 key to the shaded area so we can actually see through it, and tried to get a shade of red vaguely close to the original.

  • Added a fill=white key to the nodes so their text isn’t obscured by the grid.

4
  • 3
    The "y-arrow" is a bit meaningless on a polar plot.
    – Thruston
    Apr 4, 2014 at 21:48
  • @Thruston: Point. Removed.
    – alexwlchan
    Apr 5, 2014 at 8:25
  • Very nice plot! I added it to the TeXample TikZ gallery, plus the Pythagorean triangle example with that great explanation. Is that ok for you? Your two examples are shown here: author page. I would be happy to add further ones.
    – Stefan Kottwitz
    May 19, 2014 at 12:52
  • @StefanKottwitz: That‘s fine by me; thanks. :)
    – alexwlchan
    May 22, 2014 at 22:46
29

A try in pgfplots in case you ever decide to learn/use it. :-) In this case, much of the code is setting up the styling to match your example. This could be stored as a style defined once in your document, as I have done, and used for consistent style for all plots.

There is surely a better way to draw the double line at the outer edge. I tried lots of stuff with before end axis, after end axis, and axis line style (and friends) to no avail. So I have shown a manual solution here.

Code

\documentclass{standalone}

\usepackage{pgfplots}
\usepgfplotslibrary{polar}
\pgfplotsset{compat=1.10}

\pgfplotsset{mypolarplot/.style={%
  clip=false, % needed for double line (last \addplot command)
  domain=0:360, % plot full cycle
  samples=180, % number of samples; can be locally adjusted
  grid=both, % display major and minor grids
  major grid style={black}, 
  minor x tick num=3, % 3 minor x ticks between majors
  minor y tick num=1, % 1 minor y tick between majors
  xtick={0,45,...,359},
  xticklabels={%
    $0$,
    $\frac{ \pi}{4}$,
    $\frac{ \pi}{2}$,
    $\frac{3\pi}{4}$,
    $\pi$,
    $\frac{5\pi}{4}$,
    $\frac{3\pi}{2}$,
    $\frac{7\pi}{4}$
  },
  yticklabel style={anchor=north}, % move label position
}}

\begin{document}
\begin{tikzpicture}
\begin{polaraxis}[%
  ymax=4,
  ytick={0,1,2,3},
  mypolarplot,
]
  \addplot[mark=none,fill=red!70!black,opacity=0.5,domain=-90:90] {2-2*sin(\x)};
  \addplot[mark=none,thick,red!70!black] {2-2*sin(\x)};
  \addplot[black] {4.05}; % there is likely a better way to do this
\end{polaraxis}
\end{tikzpicture}
\end{document}

Output

enter image description here

5
  • I appreciate the pgfplots approach. As expected, its much easier! It's certainly a question of "when" not "if" I learn pgfplots. In fact, the learning starts now. So there is no question. :-)
    – DJJerome
    Apr 5, 2014 at 12:00
  • 1
    Even a metapost diehard like me might have to learn pgfplots a bit better!
    – Thruston
    Apr 6, 2014 at 10:30
  • What would be the best way to move the yticklabels off the grid? yticklabel style={font=\footnotesize, anchor=north west} makes them a bit too far away...
    – Thruston
    Apr 6, 2014 at 11:19
  • @Thruston: You can use xshift and yshift keys to fine-tune the position if needed. E.g., yticklabel style={anchor=north west,xshift=-0.5ex,yshift=0.5ex}. Apr 6, 2014 at 12:24
  • Or adjust the value of inner sep: yticklabel style={anchor=north west,inner sep=2pt} Apr 6, 2014 at 12:37
15

Late to the party but another opportunity of nonlinear transformations and pretty printing radians for me. I stole the plotted function from alexwlchan's answer.

\documentclass[tikz]{standalone}
\usetikzlibrary{fpu}
\usepgfmodule{nonlineartransformations}
\makeatletter
\def\polartransformation{\pgfmathsincos@{\pgf@x}\pgf@x=\pgfmathresultx\pgf@y\pgf@y=\pgfmathresulty\pgf@y}
\def\PIrettify#1{\pgfmathparse{#1/180}%
\pgfmathifisint{\pgfmathresult}{\pgfmathparse{\pgfmathresult==0?0:"\pi"}$\pgfmathresult$}%
               {$\pgfmathprintnumber[frac,frac shift=1,frac whole=false]\pgfmathresult\pi$}}
\makeatother

\begin{document}
\begin{tikzpicture}
  \begin{scope}
    \pgftransformnonlinear{\polartransformation}
    \draw[double] (0pt,20mm) -- (360pt, 20mm);
    \foreach \x in {0,1,2,3}{
      \node[scale=0.5,above] at (0pt,5*\x mm){\x};
      \draw[gray,very thin] (0pt,5*\x mm) -- (360pt,5*\x mm);
    }
    \foreach \x in {0,30,...,359}{% <- Change the step size for frac trial
      \node at (\x pt,23 mm) {\PIrettify{\x}};
      \draw[gray,very thin](\x*1pt,0mm) -- (\x*1pt,21mm);
    }
  \end{scope}
\fill [fill=red!50!black, scale=0.5,opacity=0.5] plot [domain=-pi/2:pi/2] (xy polar cs:angle=\x r,radius= {2-2*sin(\x r)});
\draw [thick,color=red,domain=0:2*pi,scale=0.5,samples=200] plot (xy polar cs:angle=\x r,radius= {2-2*sin(\x r)});
\end{tikzpicture}
\end{document}

enter image description here

2
  • I “stole” the plotted function from the OP. :P
    – alexwlchan
    Apr 5, 2014 at 19:35
  • @alexwlchan \let\alexwlchan\stealit :P
    – percusse
    Apr 6, 2014 at 10:11
12

With PSTricks, the following is too short for typing exercise.

\documentclass[border=12pt,pstricks]{standalone}

\usepackage{pst-plot}
\def\r{2*(1-sin(x))}

\begin{document}
\begin{pspicture}[algebraic,plotpoints=100,polarplot](-5.5,-5.5)(5.5,5.5)
    \psaxes[axesstyle=polar,subticklinestyle=dashed](5,0)
    \pscustom*[linecolor=orange,opacity=.75]{\psplot{Pi 2 div neg}{Pi 2 div}{\r}}
    \psplot[linecolor=red,linewidth=3pt,strokeopacity=.75]{Pi neg}{Pi}{\r}
\end{pspicture}
\end{document}

enter image description here

5
  • 1
    If you omit half of the requirements :)
    – percusse
    Apr 5, 2014 at 15:56
  • Thank you for not avoiding my comment :-)
    – percusse
    Apr 5, 2014 at 16:25
  • @percusse: Thank you for smiling at me.:-) Apr 5, 2014 at 16:37
  • Thank you everybody for everything. :) Apr 7, 2014 at 8:34
  • 1
    Don't mention it :) Jul 26, 2014 at 12:54
12

Yes, it can be done in TikZ. I enclose my try.

%! *latex mal-polar.tex
\documentclass[a4paper]{article}
\pagestyle{empty}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}[>=latex]
\fill[fill=lightgray] plot[domain=-pi/2:pi/2] (xy polar cs:angle=\x r,radius= {2-2*sin(\x r)});
\draw[thick, color=red, domain=0:2*pi, samples=200,smooth] plot (xy polar cs:angle=\x r, radius= {2-2*sin(\x r)});
\node at (2,-4) {\scriptsize $r=2-2\sin\theta$};
\foreach \x in {0,...,4,4.05}{\draw (0,0) circle (\x);}
\foreach \x in {0.5,...,4}{\draw[green] (0,0) circle (\x);}
\pgfmathparse{360/32}\let\malr=\pgfmathresult
\foreach \x in {0,\malr,...,360}{\draw[blue,thin](0,0)--(\x:4);}
\foreach \x in {0,45,...,360}{\draw(0,0)--(\x:4.3);}
\foreach \x in {0,...,4}{\node at (\x+0.17,-0.2){\x};}
\foreach \x/\y in {0/0, 45/$\frac{\pi}{4}$, 90/$\frac{\pi}{2}$, 135/$\frac{3\pi}{4}$, 180/$\pi$, 225/$\frac{5\pi}{4}$, 270/$\frac{3\pi}{2}$, 315/$\frac{7\pi}{4}$}
  {\node at (\x:4.5) {\y};}
\end{tikzpicture} 
\end{document}

MWE, an example created in PGF+TikZ

11

Not hard to do in Metapost...

enter image description here

prologues := 3;
outputtemplate := "%j%c.eps";

beginfig(1);
s = 1cm;

path f; f = (for t = 0 upto 359: (cosd(t), sind(t)) scaled (2-2sind(t)) .. endfor cycle) scaled s;

fill subpath(0,90) of f -- subpath(270,360) of f .. cycle withcolor .1 red + .7 white;

for r = s/2 step s until 4s: draw fullcircle scaled 2r withcolor .8 white; endfor
for r = s   step s until 4s: draw fullcircle scaled 2r withcolor .5 white; endfor

  draw fullcircle scaled 8s withpen pencircle scaled 2 withcolor .5 white;
undraw fullcircle scaled 8s;

for t = 0 step 360/32 until 359: draw origin -- (4s,0)     rotated t withcolor .8 white; endfor
for t = 0 step 360/ 8 until 359: draw origin -- (4s+2mm,0) rotated t withcolor .5 white; endfor

for i = 0 upto 3: label.lrt(decimal i, (i*s,0)); endfor

label(btex $0$ etex,          (4s+5mm,0) rotated   0);
label(btex $ \pi\over4$ etex, (4s+5mm,0) rotated  45);
label(btex $ \pi\over2$ etex, (4s+5mm,0) rotated  90);
label(btex $3\pi\over4$ etex, (4s+5mm,0) rotated 135);
label(btex $\pi$        etex, (4s+5mm,0) rotated 180);
label(btex $5\pi\over4$ etex, (4s+5mm,0) rotated -135);
label(btex $3\pi\over2$ etex, (4s+5mm,0) rotated  -90);
label(btex $7\pi\over4$ etex, (4s+5mm,0) rotated  -45);

draw f withpen pencircle scaled 1 withcolor .58 red;

endfig;
end.

Admittedly I have done all the axes etc myself, but at least you can see what's going on, which makes it (in my hugely biassed opinion) a little easier to learn. But as ever, your mileage may vary, and you may prefer the baroque splendours of pgf.

You'll note that I've cheated by simply putting the shading under the grid rather than making it look transparent. To make it look transparent you'd have to redraw the grid lines in a shade of pink in the shaded area; not hard, but a bit fiddly.

1
  • Nice! A suggestion: Do you know the freelabel macro of Metafun? It makes the labelling much easier when labels are centered around a point, like here. For example, freelabel(btex $\pi over 4$ etex, (4s, 0), origin);. Apr 5, 2014 at 6:12
7

Another try with MetaPost. I chose a longer way than Thruston's before by implementing the possibility of drawing a more general polar grid, with arbitrary polar and radial boundaries, as shown in the first figure. The second figure being the desired image with standard polar grid.

Transparency is supported by the MetaFun format of MetaPost, at the condition that the output is in PDF format. I've felt like making use of it in this program, which is thus to be compiled by this instruction in Unix systems:

mptopdf -metafun -latex polargrid.mp

or the like (which I don't know) for Windows system.

input mpcolornames; input latexmp; 
setupLaTeXMP(mode = rerun, textextlabel = enable, packages = "amsmath");
u := 1cm; % unit length

% Circular arc
vardef arc(expr C, r, theta_min, theta_max) =
  save n, theta, mystep; 
  mystep = 1.37; n = floor((theta_max - theta_min)/mystep); theta = theta_min;
  (dir(theta) 
  for k=1 upto n:
    hide(theta := theta + mystep;) .. dir(theta)
  endfor .. dir(theta_max)) scaled r shifted C
enddef;

% General polar grid with arbitrary boundaries
% 0 <= rmin < rmax, nr integer >= 1
% 0 < theta_max - theta_min <= 360, ntheta integer >=1
% eps: radii's supplementary length 
def polar_grid(expr rmin, rmax, nr)(expr theta_min, theta_max, ntheta)(expr eps) =
  save r, rstep, theta, theta_step; 
  theta_step = (theta_max-theta_min)/ntheta; theta = theta_min;
  for i = 0 upto 
  if theta_max - theta_min < 360: ntheta else: ntheta-1 fi:
    draw ((rmin, 0) -- (rmax+eps, 0)) rotated theta;
    theta := theta + theta_step;
  endfor;
  rstep = (rmax-rmin)/nr; r = rmin;
  for j = 0 upto nr:
    draw arc(origin, r, theta_min, theta_max);
    r := r + rstep;
  endfor;
enddef;


% Shortcut for circular labelling
def circlabel(expr mylabel, theta) = freelabel(mylabel, Rmax*dir(theta), origin) enddef;

% The polar function
vardef f(expr t) = (2-2sind(t))*dir(t) enddef;

% Polar grid example    
beginfig(1);
  polar_grid(2u, 4u, 4)(30, 290, 13)(0);
endfig;

%Cardioid figure upon a standard polar grid
beginfig(2);
  % Complete polar grid    
  drawoptions(withcolor 0.8white);
  rmax := 4u; eps := 6bp; 
  polar_grid(0, rmax, 8)(0, 360, 32)(eps);
  drawoptions(withcolor 0.5white);
  polar_grid(0, rmax, 4)(0, 360, 8)(eps);
  % External circle
  draw fullcircle scaled 2(rmax+0.3eps);
  % Labels
  drawoptions(withcolor black);
  Rmax := rmax + eps;
  circlabel("$\dfrac{\pi}{4}$", 45);
  circlabel("$\dfrac{3\pi}{4}$", 135);
  circlabel("$\dfrac{5\pi}{4}$", -135);
  circlabel("$\dfrac{7\pi}{4}$", -45);
  circlabel("$0$", 0);
  circlabel("$\dfrac{\pi}{2}$", 90);
  circlabel("$\pi$", 180);
  circlabel("$\dfrac{3\pi}{2}$", -90);
  % Cardioid definition
  mystep := .5;
  n := round(360/mystep);
  path cardio; cardio = (for t = 0 upto n-1: f(t*mystep) .. endfor cycle) scaled u;
  % Filling with transparent color and drawing
  fill origin -- subpath ((90, -90)/mystep) of cardio -- cycle 
    withcolor transparent("normal", 0.3, DarkRed);
  draw cardio withcolor red;
endfig;
end.

enter image description here

enter image description here

6

Here's a partial try using TikZ's Data Visualization library (Part VI of the manual).

I still haven't worked out how to do the fill. It's not clear whether development in this area of TikZ will continue, but I wanted to try it out. :-)

\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{datavisualization,datavisualization.polar,datavisualization.formats.functions}
\begin{document}
\begin{tikzpicture}
\datavisualization [
  scientific polar axes={0 to 2pi, clean},
  visualize as smooth line={myline},
  myline={style=red!70!black},
  all axes={grid},
  angle axis={ticks={step=(pi/4),minor steps between steps=3}},
  radius axis={ticks={minor steps between steps=1}},
]
data [set=myline, format=function] {
  var angle : interval [-pi:pi] samples 128;
  func radius = 2 - 2*sin(\value{angle}r);
}
[visualize as smooth line=my data, my data={straight cycle,style={red!70!black,opacity=0.5}}] % need to add the fill somewhere here...
data [format=function] {
  var angle : interval [-pi/2:pi/2] samples 128;
  func radius = 2 - 2*sin(\value{angle}r);
};
\end{tikzpicture}
\end{document}

enter image description here

You must log in to answer this question.

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