2
$\begingroup$

I have created a function which takes two arguments and outputs an RGBColor, and I was hoping that I could use this to create the equivalent of a ContourPlot or DensityPlot where I supply for each point $(x,y)$ a color instead of a number (intensity).

For example, consider plotting something like

f[x_,y_]:=With[{g=x^2+y^2},If[g<1, Red, Blue]]

I know I could do this with ContourPlot or DensityPlot, but in my case there are multiple (5) possible output values of the function, each of which results in a different color, and I would like to label the legend of the resulting plot with a different label for each color, rather than with numbers.

$\endgroup$

1 Answer 1

2
$\begingroup$

If speed is not a concern then you might just do it the brute-force way:

yellow = RGBColor[{0.9647058823529412, 0.8823529411764706, 0.7411764705882353}];
blue = RGBColor[{0.807843137254902, 0.8509803921568627, 0.9098039215686274}];

f[x_, y_] := With[{g = x^2 + y^2}, If[g < 1, blue, yellow]]

ArrayPlot[
 Table[
  f[x, y],
  {x, -1.5, 1.5, 0.01},
  {y, -1.5, 1.5, 0.01}
  ],
 PlotLegends -> SwatchLegend[{blue, yellow}, {"Blue", "Yellow"}]
 ]

Output

The disadvantage of this compared to hacking together a solution with e.g. DensityPlot is that you don't get adapative sampling, so to get really good resolution at the boundary between the colored regions you need to sample a larger number of values than with intelligent, adaptive sampling.

(If your function looks like the example that you posted, defined by inequalities, I would look into using RegionPlot. In this answer I assumed a black box function.)

EDIT: In response to your comment, I might add this method for coloring areas according to which function, out of a set, has the largest value:

pl = Plot3D[{
    0,
    1 - x^2 - y^2
    },
   {x, -1.5, 1.5},
   {y, -1.5, 1.5},
   Mesh -> None,
   PlotStyle -> {
     {Black, Glow[yellow]},
     {Black, Glow[blue]}
     },
   ViewPoint -> Above,
   Boxed -> False,
   Axes -> False,
   ImageSize -> 400
   ];
Row[{
  pl,
  SwatchLegend[{blue, yellow}, {"Blue", "Yellow"}]
  }]

Output

EDIT 2: As noted by OP in the comments, the f function can be modified to return an integer instead of a color. This should probably be the first thing to try, since one gets adaptive sampling in this way.

f[x_, y_] := With[{g = x^2 + y^2}, If[g < 1, 1, 2]]

DensityPlot[
 f[x, y],
 {x, -1.5, 1.5},
 {y, -1.5, 1.5}
 ]

Output

$\endgroup$
6
  • $\begingroup$ Thanks, yeah this method I suppose would always work as a last resort. The function I have is not really defined as such, rather the color is dependent on which of a set of functions gives the minimum value at that point. $\endgroup$
    – Kai
    Jul 14, 2020 at 3:04
  • $\begingroup$ @Kai I added a method aimed at specifically the problem that you describe here in the comment but as it is a hack one has to be prepared to experiment a lot with options and perhaps even image processing functions (e.g. to remove margins) to get it exactly the way one wants it. It has the advantage of being very fast. $\endgroup$
    – C. E.
    Jul 14, 2020 at 12:18
  • $\begingroup$ thanks! that should work. my current method is to make the function output an integer and then define a custom color function. It seems to work pretty well that way $\endgroup$
    – Kai
    Jul 14, 2020 at 14:38
  • $\begingroup$ @Kai Yes, that would be the first thing to try. I saw this question as being about finding alternatives to that since it mentions that ’DensityPlot’ is not desirable. But with that constraint removed, that is a very good option because then you get the adaptive sampling. As long as you found something that works for you, all is well. $\endgroup$
    – C. E.
    Jul 14, 2020 at 15:25
  • $\begingroup$ I added that type of solution to the answer for completeness and for future readers' benefit. $\endgroup$
    – C. E.
    Jul 14, 2020 at 15:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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