Search code examples
matlabplotarea

MATLAB: How do I shade plot area with increasing and decreasing shades of a color


I want to plot an area of a graph (x = 1:24, y = -1:1) with one color (black), which I then want to decrease/increase in shading in terms of the time of day. So, that I have a plot which is 'dark' in the background at night and 'light' during the day with x being hours of day and y being a data value. My sunrise would be at 6.8 and my sunset would be at 22. I would then overlay scatter plots with data on top.

I have tried messing around with patch and area but with no luck. Here is some code I got from elsewhere on the internet but I'm not sure how to proceed:

% Define x, f(x), and M(x)
x = linspace(6.8, 22)';
f = sin(x)+cos(x);
M = x.^2;

% Define the vertices: the points at (x, f(x)) and (x, 0)
N = length(x);
verts = [x(:), f(:), x(:) zeros(N,1)];

% Define the faces to connect each adjacent f(x) and the corresponding points at y = 0.
q = (1:N-1)';
faces = [q, q+1, q+N+1, q+N];
p = patch('Faces', faces, 'Vertices', verts, 'FaceVertexCData', [M(:); M(:)], 'FaceColor', 'interp', 'EdgeColor', 'none')

So I want the end result to be similar to the image attached below (note faint shading - I would like the gradient stronger), but with x = 1:24 and y = -1:1.

shaded plot


Solution

  • Since you ignored my request to include the results of your MATLAB code in your question, I had to look into my crystal ball to determine that your "messing around" resulted in the following error message:

    Error using patch

    While setting the 'Vertices' property of Patch:

    Value must be a 1x2 or 1x3 vector of numeric type

    Error in X (line 13)

    p = patch('Faces', faces, 'Vertices', verts, 'FaceVertexCData', [M(:); M(:)], 'FaceColor', 'interp', 'EdgeColor', 'none')

    This can be resolved by concatenating the vertices vertically instead of horizontally in line 8:

    verts = [x(:), f(:); x(:), zeros(N,1)];
    

    This yields the following plot:

    resulting plot

    This is of course not what you want.

    Actual Solution

    You can build up your background from 5 rectangles:

    x = [0;
         6;    % 'First daylight'
         6.8;  % Full brightness
         22;   % Beginning of 'sunset'
         22.8; % Complete darkness
         24];
    
    vertices = [repmat(x,2,1), [ones(size(x)); -1.*ones(size(x))]];
    faces = [1:5; 2:6; 8:12; 7:11].';
    color = repmat([0 0 0; % 'Night' color
                    0 0 0;
                    1 1 1; % 'Day' color
                    1 1 1;
                    0 0 0;
                    0 0 0],2,1);
                  
    patch('Faces',faces, ...
          'Vertices',vertices, ...
          'FaceVertexCData',color, ...
          'FaceColor','interp', ...
          'EdgeColor','red');
    xlim([0 24]);
    

    bg rects

    You make the vertices of the 'night' rectangles black and the vertices of the 'day' rectangle white by assigning the appropriate RGB values to the FaceVertexCData property.

    The color of 'sunrise'/'sunset' rectangles is then interpolated between black and white by setting the FaceColor property to 'interp'.

    The EdgeColor has only been set to 'red' to illustrate how the background is constructed. Set the property to 'interp' to make the lines disappear.