PGF supports several types of shadings. The most advanced type of shading is “functional shadings”. For such shadings the color of each point is calculated by calling a user specified function for each point in the shaded area. The shading function is specified using a simplified form of a subset of the PostScript language.
In this impressive example a functional shading is used to draw a slice of the cone shaped HSV color space. Note the smooth color transitions. The most interesting part of the code is the conversion from HSV to RGB.
Source: | PGF-users mailing list |
---|
Do you have a question regarding this example, TikZ or LaTeX in general? Just ask in the
LaTeX Forum.
Oder frag auf Deutsch auf TeXwelt.de.
En français: TeXnique.fr.
% HSV shading
% Author: Ken Stars
\documentclass{article}
\usepackage{tikz}
\begin{document}
\pgfdeclarefunctionalshading{HSVsweep}
{\pgfpoint{-2cm}{-2cm}}
{\pgfpoint{2cm}{2cm}}
{}
{ % x y
2 copy % ... x y x y
2 copy 0 eq exch 0 eq and
{ pop pop 0.0 } % silently deal with error: return
% arbitrary heading of zero for origin
{atan 360.0 div} % ... x y heading; heading being in
%the interval [0, 1.0]
ifelse % because we will use it for 'Hue'
dup 360 eq { pop 0.0 }{} ifelse % if heading is 360
%degrees, make it zero instead
3 1 roll % ... heading x y
dup mul % ... heading x y*y
exch dup mul % ... heading y*y x*x
add sqrt % ... heading ra_pt (distance from origin in points)
56 div % scale it means a ra of just under 2 cm
dup 1.0 ge % BOOLEAN. ready to clamp to interval [0, 1.0]
{ pop 1.0 }{} ifelse % We shall use the scaled ra as 'Saturation'
2.5 mul 0.25 sub % now, Ra in [0.1, 0.5] --> Saturation
% in [0.0, 1.0]. Saturation varies between the two radii
1 % ... H S V ( with 'Value' set to literal constant of 1.0 )
1 index 1.0 eq % TEST I [ S == 1.0 ]
{ % BLOCK A [ take stack to V V V ] achromatic case
3 1 roll pop pop dup dup
}
{ % BLOCK B take stack to V T Q P i
% C version to use as model:
% H' = H * 6
% i = floor(H')
% f = H' - i
% P = V * (1.0 - S)
% Q = V * (1.0 - (S*f))
% T = V * (1.0 - (S * (1.0 - f)))
3 -1 roll 6.0 mul dup 4 1 roll % H' S V H'
floor % H' S V i
dup 5 1 roll % i H' S V i
3 index sub neg % i H' S V f
1.0 3 index sub % i H' S V f (1.0 - S )
2 index mul % i H' S V f P
6 1 roll % P i H' S V f
dup 3 index mul neg 1.0 add % P i H' S V f ( 1.0 - (f*S))
2 index mul % P i H' S V f Q
7 1 roll % Q P i H' S V f
neg 1.0 add % Q P i H' S V (1.0 - f)
2 index mul neg 1.0 add % Q P i H' S V (1.0 - S * (1.0 - 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 eq % TEST II [ i == 0 ]
{ % BLOCK C [ take stack to V T P ]
pop exch pop
}
{ dup 1 eq % TEST III [ i == 1 ]
{ % BLOCK D [ take stack to Q V P ]
pop exch 4 1 roll exch pop
}
{ dup 2 eq % TEST IV [ i == 2 ]
{ % BLOCK E [ take stack to P V T ]
pop 4 1 roll pop
}
{ dup 3 eq % TEST V [ i == 3 ]
{ % BLOCK F [ take stack to P Q V ]
pop exch 4 2 roll pop
}
{ dup 4 eq % 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
% BLOCK I
}
ifelse % for I
% BLOCK J
% .. RGB at last
% Fix for Apple's PDF viewer shading bug:
cvr 3 1 roll cvr 3 1 roll cvr 3 1 roll
}
\begin{tikzpicture}
\def\ra{3.8cm}
\def\raB{1cm}
\draw[shading=HSVsweep,even odd rule] (0,0) circle (\ra) circle (\raB);
\foreach \x in {0, 30, ..., 330}
\draw (-\x+90:3.8) -- (-\x+90:4.0) (-\x+90:4.4) node {$\x^\circ$};
\end{tikzpicture}
% The shading can also be used for other shapes
%\begin{tikzpicture}
% \draw[shading=HSVsweep,shading angle=90] (0,0) rectangle (4,8);
%\end{tikzpicture}
\end{document}
See:
James D FOLEY et al
"Computer Graphics, Principals and Practice"
2nd edition
ISBN 0-204-84840-6
Page 593. Figure 13.34
"Algorithm for converting from HSV to RGB color space"
(This is C. I had to convert it to Postscript. Mostly
lots of nasty stack manipulation)
Comments
Update: Added a workaround for Apple's PDF viewer shading bug. Thanks Berteun Damman for the patch.
can alpha channel (~transparency) be specified in "functional shadings"?
I checked the PGF documentation, but as far as I can see, you can't specify alpha channel when using functional shadings, only RGB-values. There are probably workarounds since PGF support fadings with varying alpha-values.
Adding comments is currently not enabled.