7

Here is my code:

\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage{tikz,tikz-3dplot}

\begin{document}

\begin{tikzpicture}[thick]
  \draw[lightgray, dotted, xstep=pi/6, ystep=1] (0,0) grid (2*pi,2);
  \draw[gray] (0,0)--(2*pi,0) node[above] {$x$};
  \draw[gray] (0,0)--(0,2) node[left] {$y$};
  \draw[domain=0:2*pi,samples=100] plot (\x,{1+sin(\x r)});
  \foreach \ang in {0,30,60,...,361} { \draw node at (\ang /180*pi ,{1+sin(\ang  )}) {\textcolor{red}{$\bullet$}};}
\end{tikzpicture}
\begin{tikzpicture}[thick]
\foreach \ang in {0,...,15} { \draw [lightgray] (0,0) -- (\ang * 180 / 8:2.1);}
\foreach \s in {1, 1.5, 2} {\draw [lightgray] (0,0) circle (\s );}
  \draw[domain=0:2*pi,samples=100] plot ({deg(\x)}:{1+sin(\x r)});
  \foreach \ang in {0,...,15} { \draw node at (\ang * 180 / 8:{1+sin(\ang * 180 / 8 )}) {\textcolor{red}{$\bullet$}};}
\end{tikzpicture}

\end{document}

And here is what it looks like enter image description here

And I'd like to make each of the bullets to be coloured in a rainbow-way so that the graph on the left is colour-coordinated with the one of the right.

1
  • 1
    Please, please, please don't assume colour and nothing else is an acceptable way of conveying information. It is not: en.wikipedia.org/wiki/Colour_blindness#Design_implications. Up to 8% of men have some form of colour vision deficiency, and using colour only will make your graph inaccessible for them.
    – mathrick
    Commented Apr 25, 2021 at 0:51

2 Answers 2

17

I interpreted the question a bit differently: cycle the colors of the dots and let the color in the left graph at a certain angle correspond to the color in the right plot at that angle.

For this I wrote a small color cycle command that goes through a predefined list of colors. It uses two counters, one global counter for the current color index and one local counter in a loop. It also uses a boolean to check if a color is assigned at the end of the loop, if not then the global counter is larger than the length of the list and should be reset to 0.

The next color is computed at the start of the \foreach body in the tikzpictures, and the global counter is increased at the end of the \foreach body.

MWE (note that I reduced the number of points in the polar plot to match the angles):

\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage{tikz,tikz-3dplot}

\newcounter{clridx}
\newcounter{cllistloop}
\newif\ifclrfound

\makeatletter
\newcommand{\getnextcolor}{%
\setcounter{cllistloop}{0}
\clrfoundfalse
% loop list from 0 until list index = current color index
% at this index define \currcolor and set found to true
\@for\next:=\plotcolors\do{\ifnum\value{cllistloop}=\value{clridx}\xdef\currcolor{\next}\clrfoundtrue\fi\stepcounter{cllistloop}}
% if nothing found: cycle current color to 0 and call lookup function again
\ifclrfound\relax\else\setcounter{clridx}{0}\getnextcolor\fi
}
\makeatother

\begin{document}
% cycle list for colors
\def\plotcolors{red,yellow,green,cyan,blue,violet}
% current color index
\setcounter{clridx}{0}
\begin{tikzpicture}[thick]
  \draw[lightgray, dotted, xstep=pi/6, ystep=1] (0,0) grid (2*pi,2);
  \draw[gray] (0,0)--(2*pi,0) node[above] {$x$};
  \draw[gray] (0,0)--(0,2) node[left] {$y$};
  \draw[domain=0:2*pi,samples=100] plot (\x,{1+sin(\x r)});
  \foreach \ang in {0,30,60,...,361} { \getnextcolor\filldraw[\currcolor] (\ang /180*pi ,{1+sin(\ang  )}) circle (2pt);\stepcounter{clridx}}
\end{tikzpicture}
\begin{tikzpicture}[thick]
% reset color index for new plot
\setcounter{clridx}{0}
\foreach \ang in {0,...,12} { \draw [lightgray] (0,0) -- (\ang * 180 / 6:2.1);}
\foreach \s in {1, 1.5, 2} {\draw [lightgray] (0,0) circle (\s );}
  \draw[domain=0:2*pi,samples=100] plot ({deg(\x)}:{1+sin(\x r)});
  \foreach \ang in {0,...,12} { \getnextcolor\filldraw[\currcolor] (\ang * 180 / 6:{1+sin(\ang * 180 / 6 )}) circle (2pt);\stepcounter{clridx}}
\end{tikzpicture}

\end{document}

Result:

enter image description here

6
  • 3
    +1 This is what I expected as an answer. On can clearly see the mapping relationship.
    – AlexG
    Commented Apr 24, 2021 at 12:37
  • 1
    That's really great. Probably should have waited for more answers. Thanks for this.
    – Sat
    Commented Apr 24, 2021 at 13:35
  • 4
    @sat In this case, it is best that you apologize to Black Mild and accept this response as stated here What should I do when someone answers my question?
    – AndréC
    Commented Apr 24, 2021 at 15:55
  • Is there any way to make the shapes different as well, or maybe add a varying internal feature such as a dot, cross, dash, etc. inside the points? As stated in my other comment, colour-only is inaccessible design, and especially the fine distinction between two shades of blue and a green in the centre has the potential to be completely unreadable: en.wikipedia.org/wiki/Colour_blindness#Design_implications
    – mathrick
    Commented Apr 25, 2021 at 0:56
  • @mathrick more accessibility is definitely possible, you can use the same approach to make the circle part of the \filldraw command a variable from a list.
    – Marijn
    Commented Apr 25, 2021 at 6:59
6

How about this? I clean your code a bit, and use \pgfdeclareverticalshading{rainbow} from the newest PGF manual (page 1202)

There are other kinds of shading: \pgfdeclarehorizontalshading, \pgfdeclareradialshading, \pgfdeclarefunctionalshading. For more details, see Section 114.2 Declaring Shadings in the above-mentioned PGF manual.

Note: \shade and \fill can be used with the same effect. I think this is intentional to increase TikZ's user-friendliness.

enter image description here

\documentclass{article}
\usepackage{tikz}
\begin{document}
% 2021 pgfmanual.pdf ver 3.1.8b (page 1202)
\pgfdeclareverticalshading{rainbow}{100bp}{
color(0bp)=(red);     color(35bp)=(red); 
color(45bp)=(yellow); color(55bp)=(green);  
color(65bp)=(cyan);   color(75bp)=(blue);
color(85bp)=(violet); color(100bp)=(violet)
}   

\begin{tikzpicture}[thick]
\draw[lightgray,dotted,xstep=pi/6] (0,0) grid (2*pi,2);
\draw[gray] 
(0,0)--(2*pi,0) node[right] {$x$} 
(0,0)--(0,2) node[left] {$y$};
\draw[smooth] plot[domain=0:2*pi] (\x,{1+sin(\x r)});
\foreach \ang in {0,30,...,361}
\shade[shading=rainbow] (\ang/180*pi,{1+sin(\ang)}) circle(1mm); 
\end{tikzpicture}

\begin{tikzpicture}[thick]
\foreach \ang in {0,...,15} 
\draw[lightgray] (0,0) -- (\ang * 180 / 8:2.1);
\foreach \s in {1, 1.5, 2} 
\draw [lightgray] (0,0) circle (\s);
\draw[smooth] plot[domain=0:2*pi] ({deg(\x)}:{1+sin(\x r)});
\foreach \ang in {0,...,15}
\shade[shading=rainbow] (\ang*180/8:{1+sin(\ang*180/8)}) circle(1mm);
\end{tikzpicture}
\end{document}
2
  • 1
    Thanks for the answer Black Mild and sorry for prematurely accepting the response
    – Sat
    Commented Apr 24, 2021 at 16:20
  • @Sat It's okay. I misunderstood your question. In free time, I am going to try this with Asymptote
    – Black Mild
    Commented Apr 25, 2021 at 5:23

You must log in to answer this question.

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