Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

In Asymptote I can create radial gradient shadings using the radialshade function which defines a gradient varying smoothly from color A on a circle with center cA and radius rA to color B on a circle with center cB and radius rB. But I find myself needing to specify intermediate color shades along the way to get the look I want, e.g. to get a circle that has a small white-red area in the center, a larger dark-red outer area, and a pure red area in between. I tried to achieve this by combining two radial shades in the following way:

size(0,100);

path g=scale(2)*unitcircle;
pair A=(0.35,0.35), B=(0.6,0.6), C=(0,0);

radialshade(scale(1.1)*unitcircle,white,C,0,red,C,0.8);
radialshade(scale(1.0)*unitcircle^^g,red+evenodd,C,1,black,C,2);

giving the following output:

This is not bad but I feel that this is not the most elegant way to do it. Furthermore I feel that the transition area, where one radial shading meets the other one, is not as smooth as I would hope. Another thing I would like to achieve is an "ellipse" equvialent to radialshade but I haven't found a solution for that.

I really like the behavior of TikZ for that sort of thing. Here I can declare a radial shading in such a way that I can give intermediate colors as well as their radial positions. Furthermore the radial shadings also kind of adapt to the shape they are used on so that an ellipse is shaded in an elliptical way. Also there is some nice way of distorting the shading by specifying a center different from {0, 0} which is quite handy in some situations (but, of course, this effect can be achieved with radialshade too). Example:

\documentclass{standalone}

\usepackage[svgnames]{xcolor}
\usepackage{tikz}

\pgfdeclareradialshading{normal}{\pgfqpoint{0bp}{0bp}}{%
  color(0bp)=(white);
  color(10bp)=(red!90!black);
  color(20bp)=(black!75!red);
  color(30bp)=(black);
  color(100bp)=(black)}

\pgfdeclareradialshading{distorted}{\pgfqpoint{10bp}{10bp}}{%
  color(0bp)=(white);
  color(10bp)=(red!90!black);
  color(20bp)=(black!75!red);
  color(30bp)=(black)}

\begin{document}

\begin{tikzpicture}
  \shade [shading=normal] (-1, 3.5) circle (1.5cm);
  \shade [shading=distorted] (3, 3.5) circle (1.5cm);
  \shade [shading=normal] (-3, 0) ellipse (2 and 1.5);
  \shade [shading=distorted] (2.00, 0.0) ellipse (2 and 1.5);
  \shade [shading=normal] (5.00, -1.5) rectangle (7, 1.5);
\end{tikzpicture}

\end{document}

enter image description here

What is the best way to achieve the look of the TikZ examples?

share|improve this question
    
Why exactly do you need these radial shadings? If you are trying to produce an illusion of three-dimensionality, you are probably better off actually drawing a three-dimensional surface and playing with the lighting and the surfacepen (which is, confusingly, of type material, not type pen). –  Charles Staats Oct 30 '13 at 0:10
    
@CharlesStaats Of course, you are right that in most cases using a 3D surface makes the best use of Asymptote's capabilities but there are pictures where you want to stay in 2D and just add some pseudo-3D-objects, like balls on a Christmas tree (see here: tex.stackexchange.com/a/39209/6870), as it keeps things simpler. –  Philipp Oct 30 '13 at 0:22
    
@CharlesStaats Another thing is that a shading between two colors is always kind of "linear", i.e. you start at color A and end at color B and when you're half-way through you have a 50:50 mixture between A and B. But there are cases where I want a 75:25 mixture when I'm half-way through for example. And the thing with the "elliptical" shadings is of general interest to me. –  Philipp Oct 30 '13 at 0:30

1 Answer 1

How's this?

enter image description here

settings.outformat="pdf";
size(5cm);
import graph;

pen[] pens = new pen[] {white, 0.9*red + 0.1*black, 0.75*black + 0.25*red, black};
path outerpath = ellipse((0,0), 2, 1.5);
path innerpath = (1,0.8);

path midpath(path p1, path p2, real t) {
  pair f(real s) {
    return (1-t)*relpoint(p1, s) + t*relpoint(p2, s);
  }
  path p = graph(f, 0, 1, operator ..) -- cycle;
  return p;
}

int lastpath = pens.length - 1;
path[] paths = new path[lastpath + 1];
for (int i = 0; i <= lastpath; ++i) {
  paths[i] = midpath(innerpath, outerpath, i/lastpath);
}

draw(paths, pens);
share|improve this answer
    
Nice idea and at a zooming level below 100% it looks very good. The only drawbacks are that zooming in a bit reveals a lot of stripes making it only usable for small objects and the output is rather big (63kb, 5 times as big as my Asymptote picture with the two radialshades and 20 times as big as the output of my TikZ code) which might become a problem when a lot of those objects are used within a picture. –  Philipp Oct 30 '13 at 1:08
    
@Philipp: I'm seeing at most very subtle stripes, even at very high zoom levels. But your point about the size is well-taken. That can be improved by reducing the number of points used to produce the path, but going below about n=50 (which is still half the current size) starts to produce a wierd artifact that shouldn't be there. –  Charles Staats Oct 30 '13 at 1:36
    
Do you know if there is a method that uses the normal radialshade function or something similar? This might be more size-efficient. –  Philipp Oct 31 '13 at 2:01

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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