# How can I prevent ColorFunction from disabling antialiasing in graphics?

When I use ColorFunction, the appearance of my plots is ruined, changing from this

which has the normal smooth lines and antialiased fonts, to this

in which the line for the plot has become jagged and thin, and the fonts have lost their clear appearance, and the points have become jagged and have even shifted position a bit. The latter figure is useless to me.

How do I prevent this behavior? Is there a setting somewhere that I missed?

Setting the "Antialiasing Quality" to "Highest Quality" in Preferences, partly remedies the problem with the line, but points, fonts, and axes still shift, as if the scale of the figure has been changed:

Manipulate[Show[
{If[showcf,
ParametricPlot[{u, Sin[u]}, {u, 0, 2 Pi},
ColorFunction -> (White &), PlotStyle -> {Thickness[.02]}], {}],
ParametricPlot[{u, Sin[u]}, {u, 0, 2 Pi}],
Graphics[{Black, PointSize[Large], Point[{Pi, 0.5}], White,
PointSize[Medium], Point[{Pi, 0.5}]}]}],
{{showcf, False, "Show ColorFunction"}, {True, False}}]

-
I don't see any such thing. –  rm -rf Nov 3 '12 at 17:23
@rm-rf: Interesting. Any chance there are system settings (OS X) that could be causing this to which Mathematica would be sensitive, or perhaps some global Mathematica settings? –  raxacoricofallapatorius Nov 3 '12 at 17:28
@rm-rf: I've tried the only system setting I know of that could possibly affect this, font smoothing, to no effect. –  raxacoricofallapatorius Nov 3 '12 at 17:32
I get the same thing (on Windows 7, Mathematica 8.04). The text in e.g. Plot[x,{x,0,1}] is smoothed with ClearType (subpixel rendering), whereas the text in Plot[x,{x,0,1},ColorFunction->(Blue&)] is not. If I turn off ClearType the text in both plots is the same. –  Simon Woods Nov 3 '12 at 20:06
@SimonWoods: What happens to the point? Does it get scrambled? And the axes: do the shift a bit , and get blurry? –  raxacoricofallapatorius Nov 3 '12 at 20:12

The problem is caused by the appearance of VertexColors in the plot. Increasing the antialiasing quality doesn't really fix this, as you can see by exporting one of those plots to PDF. The color gradients are all wrong.

In principle, one can work around this by getting rid of the VertexColors and replacing them by rasterized images. Here is an attempt to do this for 2d line plots. It works in the context of this question, but should also work for other plots (maybe with additional adjustments):

Options[removeVertexCol] = {ImageResolution -> 300};

removeVertexCol[pp_, opts : OptionsPattern[]] :=
Module[
{pa, img, rangeCoords, plotRangeRule, x, noVertexPl},
pa = Show[
pp,
Axes -> None, Frame -> None, PlotRangePadding -> 0,
];
img = Rasterize[
pa,
"Image", ImageResolution -> OptionValue[ImageResolution]
];
plotRangeRule = AbsoluteOptions[pp, PlotRange];
rangeCoords = Transpose[PlotRange /. plotRangeRule];
noVertexPl =
Normal[(pp /. HoldPattern[VertexColors -> x__] :> Sequence[])];
Show[
Graphics[
First[
noVertexPl
] /. _?(MemberQ[{RGBColor, Hue, CMYKColor, GrayLevel},
Head[#]] &) -> RGBColor[1, 1, 1, 0],
Rest[List @@ noVertexPl]
],
Prolog -> Inset[
Show[img, AspectRatio -> Full], rangeCoords[[1]], {0, 0},
Subtract @@ rangeCoords
]
]
]


The function takes an option ImageResolution.

The idea is to make a rasterized version of the plot pp without axes and frames, and then underlay it with the original plot after removing all VertexColors from the latter. To make sure the two graphics are aligned, I remove any PlotRangePadding before rasterizing the plot. This means that you should avoid using PlotRangePadding in the original plot, and instead create any desired spacing by using an explicit PlotRange.

Below is how I would apply the above function to your example:

Manipulate[
Show[{
If[showcf,
removeVertexCol@
ParametricPlot[{u, Sin[u]}, {u, 0, 2 Pi}, ColorFunction -> Hue,
PlotStyle -> {Thickness[.02]},
PlotRange -> {Automatic, {-1.1, 1.1}}], {}
],
ParametricPlot[{u, Sin[u]}, {u, 0, 2 Pi},
PlotRange -> {Automatic, {-1.1, 1.1}}],
Graphics[{Black, PointSize[Large], Point[{Pi, 0.5}], White,
PointSize[Medium], Point[{Pi, 0.5}]}
]}
], {{showcf, False, "Show ColorFunction"}, {True, False}}]


The antialiasing is now preserved.

Edit

You may also look into replacing Show by Overlay in your example. But I don't have time to work out the details of the alignment - may get back later.

Edit 2

I made just a few modifications to your original code to get it to work with Overlay:

Manipulate[Overlay[
{If[showcf, removeVertexCol@ParametricPlot[{u, Sin[u]}, {u, 0, 2 Pi},
ColorFunction -> Hue, PlotStyle -> {Thickness[.02]},
PlotRange -> {Automatic, {-1.1, 1.1}},
AxesStyle -> Opacity[0]],
""
], ParametricPlot[{u, Sin[u]}, {u, 0, 2 Pi},
PlotRange -> {Automatic, {-1.1, 1.1}},
Epilog -> {
Black, PointSize[Large], Point[{Pi, 0.5}], White,
PointSize[Medium], Point[{Pi, 0.5}]
}
]
}
], {{showcf, False, "Show ColorFunction"}, {True, False}}]


The circle/dot is now an Epilog in the second plot so that it is placed relative to the coordinates of that plot.

-
That works wonderfully — but (a) it not only seems like an extraordinary amount of fiddling to go through in order to get what should clearly be the default behavior, (b) it's also a bit slow. As for (a), I'd call this a serious bug. As far as (b) is concerned, is there a way to speed things up? I use this inside of a manipulate that needs to be very responsive. –  raxacoricofallapatorius Nov 3 '12 at 23:07
See my edit - Overlay doesn't look jagged on the screen... –  Jens Nov 4 '12 at 0:05
Overlay is very promising, though I (in addition to having to make the axes to the first plot invisible, which is no problem) I get the point in what seems to be a separate region below the plots. –  raxacoricofallapatorius Nov 4 '12 at 2:14
I've added a quick fix using Overlay and placing the dot inside one of the plots. Seems to work fine in the Manipulate. Anyway, it's certainly a bug. –  Jens Nov 4 '12 at 4:24