Piecewise ColorFunction fails

I have Mathematica 10.3, and when I run

MyColorFunc[z_] := Piecewise[{{Blue, z > 0}, {Green, z == 0}, {Red, z < 0}}];
f[x_, y_] := x^2 + y^2 - 3;
Plot3D[f[x, y], {x, -2, 2}, {y, -2, 2}, ColorFunction -> MyColorFunc,
PlotRange -> All]


the entirety of the plot is blue, apart from a spot where it's green (at 0,0 where it should really be blue).

Is this a bug in my version, or I am doing something wrong? I have similar issues with ContourPlot.

• Related, perhaps a duplicate: (55278) – Mr.Wizard Jun 8 '18 at 9:52

You probably want

Plot3D[f[x, y], {x, -2, 2}, {y, -2, 2}, MeshFunctions -> {#3 &},
Mesh -> {{0}}, MeshStyle -> {Directive[Thick, Green]},
MeshShading -> {Red, Blue}, PlotRange -> All] Alternatively,

Plot3D[Evaluate[ConditionalExpression[f[x, y], #] & /@ {f[x, y] <= 0,
f[x, y] > 0}], {x, -2, 2}, {y, -2, 2}, PlotStyle -> {Red, Blue},
Mesh -> None, BoundaryStyle -> {1 -> Directive[Thick, Green], 2 -> None}] Compare with what you get with ColorFunction (note the absence of Green line and the blending of Red and Blue at the boundary):

Plot3D[f[x, y], {x, -2, 2}, {y, -2, 2}, ColorFunction -> MyColorFunc,
PlotRange -> All, ColorFunctionScaling -> False] Update: We can eliminate the blending using Exclusions -> {f[x,y] == 0} and use the option ExclusionsStyle to color the boundary between the two pieces:

Plot3D[f[x, y], {x, -2, 2}, {y, -2, 2},
Exclusions -> {f[x, y] == 0},
ExclusionsStyle -> Directive[Thick, Green],
ColorFunction -> MyColorFunc, PlotRange -> All,
ColorFunctionScaling -> False] • Beautiful, thanks, – Three Diag Feb 14 '18 at 8:49
• @ThreeDiag, my pleasure. – kglr Feb 14 '18 at 9:14

With ColorFunctionScaling -> True (the default), 1D color functions are scaled to the domain [0,1]. cf[z_] := Piecewise[{{Blue, z > 1/2}, {Green, z == 1/2}, {Red, z < 1/2}}] colors the lower half red and the upper half blue.

With ColorFunctionScaling -> False, the actual z value is used instead, allowing the original function to work (likely as you intended).

• Thanks, you are right. I've stumbled upon a similar post a Second before you answered, so my q is likely a duplicate, but thanks =) – Three Diag Feb 14 '18 at 8:45
• @ThreeDiag If it is a duplicate or another question helped you out, it'd be good to link the other question so that other people can find it more easily. Even if this question ends up getting closed, there's no harm in having the additional information available. – eyorble Feb 14 '18 at 9:33

Define the function with MyColorFunc[args__].

Try using ColorFunction -> (MyColorFunc[##]&).

According to the documentation, the arguments are scaled versions of the $x$, $y$ and $z$ coordinates.

Since you've already gotten some great answers that touch upon the importance of ColorFunctionScaling -> False, let me just demonstrate another method for the kind of coloring you want to do:

myColorFunction = Blend[{ColorData[{"ThermometerColors", "Reverse"},
LogisticSigmoid[80 #]],
Green}, Exp[-80 #^2]] &;


where we use a sigmoid to map $(-\infty,\infty)$ to $(0,1)$ for ColorData[], and use a sharply peaked Gaussian along with Blend[] to insert the green color at $0$. With this,

Plot3D[x^2 + y^2 - 3, {x, -2, 2}, {y, -2, 2},
ColorFunction -> (myColorFunction[#3] &), ColorFunctionScaling -> False,
Mesh -> False, PlotPoints -> 105, PlotRange -> All] 