13

I'm trying to draw a picture in tikz whose code is generated by another computer program. The program outputs hundreds of numbers in between 0 and 100, and I'd like to color objects in the picture on a spectrum according to the numbers.

For instance, suppose the spectrum I choose is red-orange-yellow-green-blue-violet. Then I would want to define a macro that has one input (a number between 0 and 100) and gives a color according to the following rules:

0=red

20=orange

40=yellow

60=green

80=blue

100=violet

Any number in between would be an appropriate mix. For example, 5 would be mostly red with a little bit of orange. 55 would be mostly green with a little bit of yellow.

Thank you in advance!

  • What are you coloring? Are you plotting or using shadings of random objects? How do you get the data? This still in do-it-for-me I'm afraid. – percusse Feb 26 '15 at 6:35
  • @percusse: I'm coloring nodes and paths between nodes. Suppose the computer gives me the number x. Then I can use something like blue!x!white to get a spectrum from blue to white depending on the color. However, there isn't enough variation in the picture if every color is just a mixture of white and blue. I'd like to be able to access a larger spectrum of color with just one number. Does that help? – Jared Feb 26 '15 at 6:44
  • This is more a question about xcolor. Look at its support for the HSB colour model. What you describe is essentially how the "hue" parameter works. – Thruston Feb 26 '15 at 9:06
21

Nested use of \ifnum to define a color via \colorlet does the job:

enter image description here

Code:

\documentclass{article}    
\usepackage{xcolor}
\usepackage{pgffor}

\colorlet{MyColor}{black}%
\newcommand{\MixValue}{0}
\newcommand*{\SetColor}[1]{%
    \ifnum#1<21
        \pgfmathtruncatemacro{\MixValue}{100*#1/20}%
        \colorlet{MyColor}{orange!\MixValue!red}%
    \else
        \ifnum#1<41
            \pgfmathtruncatemacro{\MixValue}{100*(#1-20)/20}%
            \colorlet{MyColor}{yellow!\MixValue!orange}%
        \else
            \ifnum#1<61
                \pgfmathtruncatemacro{\MixValue}{100*(#1-40)/20}%
                \colorlet{MyColor}{green!\MixValue!yellow}%
            \else
                \ifnum#1<81
                    \pgfmathtruncatemacro{\MixValue}{100*(#1-60)/20}%
                    \colorlet{MyColor}{blue!\MixValue!green}%
                \else
                    \ifnum#1<101
                        \pgfmathtruncatemacro{\MixValue}{100*(#1-80)/20}%
                        \colorlet{MyColor}{violet!\MixValue!blue}%
                    \else
                    \fi%
                \fi%
           \fi%
       \fi%
    \fi%
}%

\newcommand*{\ShowInAppropriateColor}[1]{%
    \SetColor{#1}%
    \textcolor{MyColor}{#1}%
}%

\begin{document}
\noindent
\foreach \x in {0,...,100} {%
    \ShowInAppropriateColor{\x}
}%
\end{document}
39

You can do this more simply using the wave colour model:

\documentclass{article}    
\usepackage{xcolor}
\usepackage{pgffor}
\begin{document}
\noindent
\foreach \x in {300,320,...,900} {\textcolor[wave]{\x}{\x}\ }
\end{document}

a spectrum of coloured letters

According to the xcolor manual, the argument, λ, is supposed to be a visible-light wavelength, given in nanometers (nm), so that λ ∈ [380, 780]. As my example shows, "invisible" wavelengths are shown as black.

  • 3
    Holy moly! That was simple and elegant. – Svend Tveskæg Feb 26 '15 at 14:01
  • 1
    What do the wave values represent in the model? – Werner Feb 26 '15 at 15:44
  • @Thruston: Thank you. This is wonderful and just what I'm looking for. However, I can't seem to implement the wave model to color a node of a tikz picture. I've tried \node[fill=\color[wave]{500}] at (0,0){}; along with about 10 other options along these lines. I've also tried defining a new color with \xdefinecolor{new}{wave}{500} and then filling with "new" but this too doesn't work (and many of its variations). How can I implement the wave color model to color a node of a tikz picture? – Jared Feb 26 '15 at 18:12
  • By the way, I'm able to use rgb and cmyk to color nodes either by defining a new color or using something like fill={rgb:red,.1;green,.8;blue,0} in the options for coloring the node. But for some reason the wave color model won't work in tikz like rgb or cmyk. – Jared Feb 26 '15 at 18:20
  • And even more confusing is the fact that I can define a color "new" using wave, and then use it in text (something like \textcolor{new}{hello}) and it works just fine. However, once I try to use the color "new" to fill a node, I get an "unsupported color model 'hsb'" error, and the node is colored black. – Jared Feb 26 '15 at 18:31
18

Here is an approach that, for a couple of reasons, is interesting.

\documentclass{article}

\usepackage{xcolor}
\usepackage{tikz}

\newcommand{\makemycolor}[2]{%
    \pgfmathsetmacro{\hue}{(#1/100)^1.715*0.8}%
    \definecolor{myhsbcolor}{hsb}{\hue,1,1}%
    \textcolor{myhsbcolor}{#2}%
}

\begin{document}

\noindent\begin{tikzpicture}
    \foreach \k in {0,1,...,100}{%
        \pgfmathsetmacro{\hue}{(\k/100)^1.715*0.79}
        \definecolor{mycolor}{rgb:hsb}{\hue,1,1}
        \node[color=mycolor] () at (\k/10,0) {$\bullet$};
    }%
    \foreach \f in {0,1,...,10}{%
        \pgfmathtruncatemacro{\num}{\f*10}
        \node () at (\f,-.5) {\num};
    }
    \foreach \g/\h in {0/Red,2/Orange,4/Yellow,6/Green,8/Blue,10/Purple}{%
        \pgfmathtruncatemacro{\num}{\g*10}
        \node at (\g,-1) {\makemycolor{\num}{\h}};
    }%
\end{tikzpicture}

\end{document}

Better sample

First, this uses the hsb (hue-saturation-brightness) model, as Thruston suggests.

Second: Normally, TikZ cannot use the hsb model. That problem is solved by specifying \usepackage[rgb]{xcolor} which causes xcolor.sty to convert all colors from whatever color space to the rgb color space which TikZ can use. You could also say \usepackage[cmyk]{xcolor} if you were having this printed -- TikZ also understands cmyk. Also note that you could say \usepackage{xcolor} but define the color with \definecolor{mycolor}{rgb:hsb}{\hue,1,1} or \definecolor{mycolor}{cmyk:hsb}{\hue,1,1} -- again this converts hsb to rgb or cmyk, but on an individual basis.

Note that xcolor.sty must be loaded BEFORE tikz.sty.

Third, the function that actually sets up what the hue is

\pgfmathsetmacro{\hue}{(\k/100)^1.715*0.8}

can be varied at will to get a better spread of colors. The 0.8 determines the ending color, so you can adjust it a little up or down to fine-tune the shade of purple at the end of the spectrum.

So, for a macro that could be called for a specific color, you could try something like this:

\documentclass{article}

\usepackage{xcolor}
\usepackage{tikz}

\newcommand{\makemycolor}[2]{%
    \pgfmathsetmacro{\hue}{(#1/100)^1.715*0.79}%
    \definecolor{myhsbcolor}{hsb}{\hue,1,1}%
    \textcolor{myhsbcolor}{#2}%
}

\begin{document}

\makemycolor{0}{Red}
\makemycolor{40}{Yellow}
\makemycolor{55}{Green with a touch of yellow}
\makemycolor{100}{Purple}

\end{document}

Sample colors

As an aside, you can also specify \usepackage[gray]{xcolor} in the preamble to get this:

enter image description here

Not sure of the practical use of this, but interesting nonetheless.

10

Here is a simple solution to make a HSB shading with xcolor:

enter image description here

\documentclass[tikz]{standalone}
\begin{document}
\begin{tikzpicture}[x=1mm,y=1mm]
  \colorlet{color min hsb}[hsb]{red}
  \colorlet{color max hsb}[hsb]{magenta}
  \foreach \pos in {0,...,100}{
    \colorlet{my color hsb}[rgb]{color max hsb!\pos!color min hsb}
    \fill[fill=my color hsb,draw=white] (\pos,1) rectangle +(1mm,5mm);
  }
\end{tikzpicture}
\end{document}
3

Mixing Paul Gaborit's answer with xcolor wave model and color conversions:

\documentclass[tikz, margin=2mm]{standalone}
\begin{document}
\begin{tikzpicture}[x=1mm,y=1mm]
  \foreach \wav in {380, 384,...,780}{
      \definecolor{tmpcolor}{wave}{\wav}
      \colorlet{mycolor}[rgb]{tmpcolor}
      \fill[fill=mycolor,draw=white] (\wav,1) rectangle +(4mm,15mm);
  }
\end{tikzpicture}
\end{document}

Rainbow

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.