3

My goal is to create a half color wheel in tikz looking something like that:

enter image description here

The code I used to produce the above picture is based on:

\shade[shading=color wheel white center,opacity=.3] [even odd rule]
    (1,0) arc (0:360:1);

However there are multiple problems:

  • first, it is not a half wheel but a full wheel that I "cut" while taking the screenshot. If I replace (0:360) with (0:180), the center of the shading (see the white part) is not at the right position: enter image description here
  • secondly, even if I find how to "recenter" the shading (if you know how to do that I'm still interested), the colors are still not going from the whole spectre: for instance cyan is not visible since only half of the spectre will be visible.
  • lastly, it is not easily customizable if I want other shapes/functions/colors.

Do you know a way to do this half color wheel? I'd love to be able to provide directly a "function" taking the coordinates (absolute and relative, in cartesian and polar form for instance) as input and outputting the final color (in that case the hue would be the polar angle divided by 2, the luminosity would be a function of the radius), but can't find a nice way to do that. Note also that I'll later want to find a way to rotate the final shape, in my case to fill the lower part of the circle with the rotated color wheel.

-- EDIT --

Using clipping as proposed in comment, together with shading angle=180 (rotating the scope directly does not work with shading...) I was able to achieve a first nice version (it works mostly because the center of the shading has the good position before clipping):

enter image description here

However, it does not contain all the colors I want since the spectrum is cut in two. Any idea how I could solve that with a more customizable function? Maybe by inserting pgfplots inside tikzpicture? (No idea if it is possible)

Also, shading seems to fail to render into Firefox (which is quite bad for my application...) so I'd love a more universal solution:

In firefox:

enter image description here

MWE

\documentclass{article}
\usepackage{amsmath}
\usepackage{amssymb}
\usepackage{amsfonts}
\usepackage{tikz}
\usetikzlibrary{positioning,arrows,calc,math,angles,quotes,shadings}
\usepackage{blochsphere}
\usepackage{braket}

\begin{document}

\begin{tikzpicture}[
  scale=1.5
  ]
  \def\maxim{1.5}
  \draw[help lines,opacity=.5] (-1.5,-1.5) grid[step=0.25] (1.5,1.5);
  \begin{scope}
    \clip (-1,0) rectangle (1,1);
    \shade[shading=color wheel white center,opacity=.3] [even odd rule]
    (1,0) arc (0:360:1);
  \end{scope}
  \begin{scope}
    \clip (-1,-1) rectangle (1,0);
    \shade[shading=color wheel white center,opacity=.3,shading angle=180] [even odd rule]
    (1,0) arc (0:360:1);
  \end{scope}
  \draw[-] (-\maxim,0) -- (\maxim,0);
  \draw[-] (0,-\maxim) -- (0,\maxim);
  \draw (0,0) circle (1);
  \draw[-latex] (0,0) -- (0:1) coordinate (ket0) node[above right] {$\ket{0}$};
  \draw[-latex] (0,0) -- (90:1) coordinate (ket1) node[above right]  {$\ket{1}$};
  \draw[-latex] (0,0) -- (45:1) node[above right] (ketp) {$\ket{+}$};
  \draw[-latex] (0,0) -- (90+45:1) node[above left] (ketm) {$\ket{-}$};
  \coordinate (orig) at (0,0);
  \pic[draw,red,thick,angle radius=10.7]{right angle=ket0--orig--ket1};
  \draw[-latex] (0,0) -- (180+0:1) coordinate (ket0) node[below left] {$\ket{0}$};
  \draw[-latex] (0,0) -- (180+90:1) coordinate (ket1) node[below left]  {$\ket{1}$};
  \draw[-latex] (0,0) -- (180+45:1) node[below left] (ketp) {$\ket{+}$};
  \draw[-latex] (0,0) -- (180+90+45:1) node[below right] (ketm) {$\ket{-}$};
\end{tikzpicture}
\end{document}
2
  • 1
    An idea could be to draw the complete wheel and clip it with the code \clip (-1.1,0) rectangle (1.1,1.1); before the wheel. You probably will need a scope too. Jul 22, 2021 at 17:31
  • @JuanCastaño Thanks, clipping does indeed help. However, of course, it does not help to get all the colors, the spectrum is still cut in two. Any idea how to display a full spectrum?
    – tobiasBora
    Jul 22, 2021 at 17:51

2 Answers 2

6

This may not be exactly what you want, but in order to show every colour of the spectrum, I tried to create a colour wheel by filling arcs from 0° to 180°:

half colour wheel

\documentclass[tikz,border=3.14mm]{standalone}    

\begin{document}
    \begin{tikzpicture}
        
        \def\R{5}
        \draw[very thin,gray!50] (-1.5*\R,-1.5*\R) grid [step=0.25*\R] (1.5*\R,1.5*\R);
        
        \def\startwave{440} \def\endwave{650}
        \def\t{75} \def\inter{0.3}
        \pgfmathsetmacro\m{180/\t}
        
        \begin{scope}[transparency group,opacity=0.5]
            \clip (180:\R) -- (0:\R) arc (0:180:\R);
            \foreach \i in {0,\inter,...,\t}
                {
                \pgfmathsetmacro\wavelen{\startwave-(\startwave-\endwave)*\i/\t}
                \definecolor{clr}{wave}{\wavelen}
                \pgfmathsetmacro\j{\i+\inter}
                \filldraw[thin,clr] (0:0) -- (\m*\i:\R) arc (\m*\i:\m*\j:\R) -- (0:0) -- cycle;
                }
        \end{scope}
    
        
        \draw (-1.5*\R,0) -- (1.5*\R,0) (0,-1.5*\R) -- (0,1.5*\R);
    \end{tikzpicture}
\end{document}
4
  • Thanks a lot. It works to some extend (so +1, I also made it work for a different version with hue color instead of wave), but there is still an issue with the fact that the center is not white. I guess I could do a quite dirty code that separate my space into squares instead of arcs... But isn't there any simpler method where I could simply provide a function that gives the color given the coordinates? I think that pgfplot has some things like that related to surface plots.
    – tobiasBora
    Jul 22, 2021 at 19:06
  • Maybe by adding a white radial shading from the centre?
    – SebGlav
    Jul 22, 2021 at 19:55
  • That's true, it should fake the effect well enough if transparency is well handled. That said, it does not really generalize to more complex drawings in which I want a precise function to be drawn. In case there is a nice way to do that without many loops it could be cool. For instance pgfplots does things like that page 145,151,166,299 (the trick is to do a 3d plot with view={0}{90}, and then they have multiple ways to draw stuff, like using mesh/color input=explicit, shader=interp,the color being configured via point meta like (which defaults to `point meta=f(x).
    – tobiasBora
    Jul 23, 2021 at 8:42
  • The problem with pgfplot is that it seems less easy to include it in an existing tikz picture at a precise position.
    – tobiasBora
    Jul 23, 2021 at 8:44
4

The color wheel is defined by a \pgfdeclarefunctionalshading. (See pgflibraryshadings.code.tex line 104--188.

Copy and paste the definition and multiply the frequency by two, and you are don

\documentclass[border=9,tikz]{standalone}
\usetikzlibrary{shadings}
\begin{document}

\pgfdeclarefunctionalshading{Bora wheel}
{\pgfpoint{-25bp}{-25bp}}{\pgfpoint{25bp}{25bp}}{}
{% x y
    2 copy % x y x y
    atan % x y theta (range [0, 360])
    90 add % x y theta (rotating by 90)
    180 div % x y theta (out of 2)
    dup 2 gt {2 sub}{} ifelse % fancy way to mod 1
    dup 1 gt {1 sub}{} ifelse % fancy way to mod 1
    3 1 roll % theta x y
    dup mul % theta x y*y
    exch % theta y*y x
    dup mul % theta y*y x*x
    add sqrt % theta radian (in PS points)
    25 div % theta radian (in custom unit, center = 0, boundary = 1)
    1 % H S V (with 'Value' set to literal constant of 1)
    %%%
    % C version to use as model:
    % H' = H * 6
    % i = floor(H')
    % f = H' - i
    % P = V * (1 - S)
    % Q = V * (1 - (S * f))
    % T = V * (1 - (S * (1 - f)))
    3 2 roll % S V H
    6 mul dup % S V H' H'
    4 1 roll % H' S V H'
    floor dup % H' S V i i
    5 1 roll % i H' S V i
    3 index %  i H' S V i H'
    sub neg % i H' S V f
    1 3 index %  i H' S V f 1 S
    sub % i H' S V f (1 - S)
    2 index % i H' S V f (1 - S) V
    mul % i H' S V f P
    6 1 roll % P i H' S V f
    dup % P i H' S V f f
    3 index % P i H' S V f f S
    mul % P i H' S V f (f * S)
    1 sub neg % P i H' S V f (1 - (f * S))
    2 index  % P i H' S V f (1 - (f * S)) V
    mul % P i H' S V f Q
    7 1 roll % Q P i H' S V f
    1 sub neg % Q P i H' S V (1 - f)
    2 index % Q P i H' S V (1 - f) S
    mul % Q P i H' S V (S * (1 - f))
    1 sub neg % Q P i H' S V (1 - S * (1 - f))
    1 index mul % Q P i H' S V T
    7 2 roll % V T Q P i H' S
    pop pop % V T Q P i
    %%%
    % end of BLOCK B. The rest is just stack manipulation
    dup 0.5 le % TEST II [ i == 0 ]
    { % BLOCK C [ take stack to V T P ]
        pop exch pop
    }
    { dup 1.5 le % TEST III [ i == 1 ]
        { % BLOCK D [ take stack to Q V P ]
            pop exch 4 1 roll exch pop
        }
        { dup 2.5 le % TEST IV [ i == 2 ]
            { % BLOCK E [ take stack to P V T ]
                pop 4 1 roll pop
            }
            { dup 3.5 le % TEST V [ i == 3 ]
                { % BLOCK F [ take stack to P Q V ]
                    pop exch 4 2 roll pop
                }
                { dup 4.5 le % TEST VI [ i == 4 ]
                    { % BLOCK G [ take stack to T P V ]
                        pop exch pop 3 -1 roll
                    }
                    { % BLOCK H [ take stack to V P Q ]
                        pop 3 1 roll exch pop
                    }
                    ifelse
                }
                ifelse % for V
            }
            ifelse % for IV
        }
        ifelse % for III
    }
    ifelse % for II
}%

\tikz{
    \shade[shading=Bora wheel] (0,0) circle (5);
}

\end{document}
2
  • Thanks a lot for that! That said it's quite hard to read ^^' I guess it's because the pdf reader is in charge of evaluating that... The second problem with shaders is that firefox fails to read some of them apparently (notably the color wheel one).
    – tobiasBora
    Jul 23, 2021 at 8:47
  • You are right. FWICT Chrome also dislike this type of GPU-intense figures. (Which is ironic.)
    – Symbol 1
    Jul 23, 2021 at 19:47

You must log in to answer this question.

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