How to create a patch/shape with a color gradient in a simple 2d plot?

Hi, I am trying to add a rectangle with a color gradient to a plot to indicate a special region that should fade out, i.e. have a color gradient to white. So far I have tried hpatch() and vpatch(), which give me the rectangle, but only in a solid color. I’ve managed to engineer a color gradient using a heatmap, but this overlays the xticks and yticks and is therefore not a suitable solution. I’ve tried to use fill, and then set the fill_z accordingly, but this gives me slices that do not interpolate nicely no matter how fine I make the spacing… here is some code to demonstrate what I try to achieve.

myCG = cgrad([:gray, :white]);
gridSpacing = 50;
xPatch = (1, 10);
yPatch = (0, +1);
x = range(xPatch[1], stop = xPatch[2], length = gridSpacing);
y = yPatch[2] * ones(length(x));
z = range(0, stop = 1, length = gridSpacing);
myPlot = plot(x, y, linecolor = :transparent, fillrange = yPatch[1], fillcolor = myCG, fill_z = z, legend = false)

Is there any simple way to do this?

Have you checked this post with a beautiful solution by @klaff using Plots, Colors and PolygonOps?

NB: please post your code above inside triple backticks

1 Like

Thanks for the suggestion. I came across this post already, but I felt like there has to be a simpler solution. Anyway, I will take a closer look at it again.

You may not want to switch plotting libraries for this, but in Makie you can use poly or mesh with a color for each point:

using GLMakie

poly(
    Point2f0[(0, 0), (0, 1), (1, 1), (1, 0)], 
    color = [:gray, :gray, :white, :white])

# Or with transparency to fade out even more:w
poly(
    Point2f0[(0, 0), (0, 1), (1, 1), (1, 0)], 
    color = [:gray, :gray, (:white, 0.0), (:white, 0.0)])

2 Likes

Thanks., this is exactly what I am looking for. I still didn’t manage to do this with GR, but maybe I can combine your suggestion with the rest of the plot.

If I may follow up on this, is there a way to make a triangle patch plot with a bilinear gradient (or higher order) with Makie?
I’m trying to make a a patch plot (multiple triangles or quads) in which all vertices are assigned with a scalar value (not a RGB code) and which the interior value is interpolated from vertices values.
Using the above and other online examples, here’s an attempt of MWE which only feature one triangle.

using GLMakie
vertices = [
    0.0 -1.0;
    1.0 0.0;
    0.6 1.0;
    0.0 0.0; # why does the script fails if this vertex is removed? Ideally, one should not need a 4th vertex to draw a triangle
]
faces = [
    1 2 3;
]
f = Figure(backgroundcolor = RGBf(0.98, 0.98, 0.98),
    resolution = (1000, 700))
ga     = f[1,1]
ax2d   = Axis(ga[1, 1], title = "patch plot")
colors = [1, 2, 3]  # EDIT: 4th color is not needed - which makes sense for a triangle
m      = mesh!(ax2d,vertices, faces, color = colors, shading = false, colormap = Reverse(:roma))
Colorbar(ga[1, 2], m, label = "whatever")
display(f)

This MWE runs but only if the vertices list contains 4 vertices (while only 3 would be needed for a triangle) and when the the list of colors contains 4 values (while 3 values would be needed for a triangle).
Would anyone have an idea of what’s wrong with the above example?


Here’s the output corresponding to the above MWE.
Besides the issues stated above, one problem is that, along the upper edge, one would explain a gradient from -1.0 to 3.0, but there is no color corresponding to this range along that edge. Would anyone has a hint? Cheers!

Is this cairomakie or glmakie?

So far, I’ve only tried GLMakie. I will try with Cairo.
Is what I’m trying to do possible to do with Makie (i.e. plotting a triangular patch with a linear gradient based on vertices values) ?
Cheers and thanks!

EDIT: I’ve CairoMakie and got the same result. Not sure what I do wrong. One puzzling thing is: what is the role of the 4th vertice in the list?

Ah the good old interpolating between colors vs between values:
I just fixed it in GLMakie:
https://github.com/JuliaPlots/Makie.jl/pull/2097

The matrix of values approach is a bit flimsy because it’s ambiguous, so I’d just use points:

using GLMakie
vertices = Point2[
    (0.0, -1.0)
    (1.0, 0.0)
    (0.6, 1.0)
]
faces = [1, 2, 3]
colors = [1, 2, 3]
f, ax, p = mesh(vertices, faces, color = colors, shading = false, colormap = Reverse(:viridis))
Colorbar(f[1, 2], p)
f
1 Like

Thanks again for considering my question. I have now updated GLMakie and well as Julia (1.8). Unfortunately I still get the same result. Have the changes you made been pushed to the main branch?
Also, the MWE now takes a first execution time of 8 min 45 s on my lappy. It looks (and sounds) like it’s an unusually expensive computing task. Is there anything I could try besides making a system image?
Cheers

I have to admit, precompile times have been increasing.
But time to first plot should be a lot faster now, so after you compiled the new version, things should be much faster.
I get ~5 minute compile times for the very first time installing the package, and then I get 47s time to first plot…

I just tested Makie@0.6.13 and it does interpolate between values and not colors anymore, so I guess you’re still on the wrong version?!

Thanks, you’re right, it’s me being confused. I was working in a notebook and somehow Pkg.update() never brought me to GLMakie v0.6.13, I’m trying to understand why… In the same project, I’ve run ]up and just got the right versions. Results look great and time for 1st plot is comparable to what I had initially (2m45 on my lappy):


So, I apologise for my previous message. Now I go to study what’s going in with my package manager…

1 Like