Filling in rectangles drawn with the patch function - matlab

I am wanting to draw rectangles on a figure that I am creating. I also would like to be able to fill that rectangle with a transparent color. So I am using 'Patch' instead of 'Rectangle' which will allow me to do so.
I am able to get the rectangles in the location and the size that I want, but I cannot seem to get the filling in with transparency the way that I think it should work?
In the documentation, it is of the form:
p=patch(X,Y, 'c')
When I enter this in, it never takes into account that Color denoted by 'c'/cyan, and will just plot a standard black rectangle. However, I can set the color with the dot index notation of:
p.EdgeColor='c';
My actual script is different as the X's and Y's are variable, but I am attaching a very simple script here to simulate my issue of my vectorized plotting issue. It simply creates Xs vertices at every 10th location, with a width of 2, and a height of 10.
Am I misusing the patch function to get it to fill with a transparent color with FaceAlpha?
clear all;
% Generate some simple X value data, where each X is the X value starting from the
% lower left of the rectangle, in a clockwise fashion around the edges of
% rectangle.
X1(:,1) = 0:10:100;
X2(:,1) = 0:10:100;
X3(:,1) = X1+2;
X4(:,1) = X1+2;
% Rotate the X vectors into rows.
X1 = X1(:)';
X2 = X2(:)';
X3 = X3(:)';
X4 = X4(:)';
% Here I am stacking each X on top of each other, and padding the bottom
% row with NaNs. Adding a similar Y set of values, which will simply be a
% height of 0-10
X =[X1; X2; X3; X4;
nan(size(X1)) ];
Y =[zeros(size(X1)); 10+zeros(size(X2)); ...
10+zeros(size(X3)); zeros(size(X4));
nan(size(X1)) ];
% Rotate vectors so that the last value in the X/Y coordinates is a NaN,
% and Matlab will ignore and plot the next value
X=X(:);
Y=Y(:);
% This Plots the outline of the rectangles I am looking for, with a width
% of 2, height of 10, starting at each 10th value of X
p=patch( X ,Y,'c');
p.EdgeColor = 'b'; %Comment this out to see that the Patch function is not working?
p.FaceColor = 'blue';
p.FaceAlpha = 0.5;
% But for some reason it is not FILLING in the rectangles/patches I have
% drawn?

If you want to create multiple rectangles, you don't want to put the NaN values to separate them, you instead want to put each rectangle's coordinates in a separate column.
X = [X1; X2; X3; X4];
Y =[zeros(size(X1)); 10+zeros(size(X2)); ...
10+zeros(size(X3)); zeros(size(X4))];
patch(X, Y, 'c')
Also, the third input to patch specifies the color of the faces (FaceColor) but the default EdgeColor is going to be black.
You can specify the parameter/value pairs as additional inputs to patch to specify the desired value for any other parameters (such as EdgeColor).
patch(X, Y, 'c', 'EdgeColor', 'c', 'FaceAlpha', 0.5)

Your problem is not with the color but with X and Y, they should be a 4-by-n matrix. Here is a way to do this:
x = [0:10:100; (0:10:100)+2];
X = reshape(repelem(x(:),2),4,[]);
Y = repmat([0; 10; 10; 0],1,size(X,2));
p = patch(X,Y,'b','EdgeColor','c', 'FaceAlpha', 0.5);

Related

Draw error bars in Matlab

I have created an example scatter plot with five points in MATLAB as follows:
x = linspace(0,pi,5);
y = cos(x);
scatter(x,y);
In my case, the y-value of each point shall be in a predefined range defined as follows:
y_limits = {[0.9 1.1], [0.6 0.8], [-0.1 0.1], [-0.8 -0.6], [-1.1 -0.9]};
So for example, the y value of point 1 at x = 0 shall be in the range [0.9 1.1].
I would somehow like to draw five vertical boundaries nicely in the same plot perhaps by means of
five vertical lines with endpoints at the respective two limits
five filled vertical areas between the respective two limits
something else that may be more appropriate
I would like to get some suggestions or sample code of people who are more experienced than me in such kind of graphical representations.
You can do this in one line by using the errorbar function
% Your example variables
x = linspace(0,pi,5)';
y = cos(x);
y_limits = [0.9, 1.1; 0.6, 0.8; -0.1, 0.1; -0.8, -0.6; -1.1, -0.9];
% Plot
errorbar(x, y, y - y_limits(:,1), y_limits(:,2) - y, 'x');
% Format: (x, y, negative error, positive error, point style)
Result:
Edit, you can set the line properties of the plot as you call errorbar. For example, you could use larger, blue circle markers with thicker, red error bars
using:
errorbar(x, y, y - y_limits(:,1), y_limits(:,2) - y, 'o', 'MarkerSize', 2, 'MarkerFaceColor', 'b', 'MarkerEdgeColor', 'b', 'Color', 'r', 'LineWidth', 1);
Note for these images I'm using grid on to add the grid. Second result:
Creating a lines is done with the line command.
for i = 1:length(x)
line([x(i) x(i)], [y_limits{i}]);
end
Filled areas can be done with patch or fill. Some reordering of the limits is necessary so that the order given follows a path around the area to be filled. One nice trick is to use the alpha command on those filled areas to create transparency.
hold on
y_corners = reshape([y_limits{:}], 2, length(x)).'; %make an array
y_corners = [y_corners(:,1); flipud(y_corners(:,2))]; %corners follow a path around the shape
fill([x fliplr(x)], y_corners, 'blue');
alpha(0.5);

Shade a vertical strip Area in a MATLAB Plot

I need to shade a vertical strip area in a MATLAB plot between to vertical lines.
I need to shade the part covered enclosed by the BLACK Curve, RED, BLUE & GREEN Lines.
I have tried the example from Here
If the data for the plot is required, please let me know i will upload.
I think this is what you are looking for:
% some arbitrary data
x = -10:0.1:10;
y = abs(x).^0.5;
xleft = 0.5;
xright = 4;
fillStart = find(x>=0.5,1);
fillEnd = find(x>=4,1);
top = 2.5;
% plotting the lines
plot(x,y,'k',...
x,ones(1,length(x))*top,'r',...
ones(1,length(y)).*xleft,y,'g',...
ones(1,length(y)).*xright,y,'b')
hold on
% filling the area
area(x(fillStart:fillEnd),y(fillStart:fillEnd),top, ...
'EdgeColor', 'none', 'FaceColor', [0.5 0.5 0.5],'ShowBaseLine','off')
hold off
Which create this:
While not exactly what you are after, (you need the equations for your respective lines) something like this should work
x = -5:0.1:5;
y = sqrt(abs(x));
figure
hold on
fill([2, 4, 4, 2], [0, 0, 2, 2], 'g')
plot(x,y)
From the fill documentation
fill(X,Y,C) fills the 2-D polygon defined by vectors X and Y
with the color specified by C. The vertices of the polygon
are specified by pairs of components of X and Y. If necessary,
the polygon is closed by connecting the last vertex to the first.

Rotating a Plot About the Y Axis

I have a vector of values that I want to plot as brightness on a circle through the radius of it (I.e. If it was 0 3 1 5 I'd want a circle that was dark at the centre, then a bright ring around it, then a slightly darker ring, then a brighter ring).
To do this I've attempted to rotate my radial vector (E) around the y axis, as such
[X,Y,Z] = cylinder(E);
h = surf(X,Y,Z),
However I'm clearly not doing it right, as this appears to be rotating my curve around the x axis. I've tried just swapping X and Y, but it still rotates it around the x axis. Any help would be greatly appreciated.
One way would be to rotate your vector and create a surface. The Z data of the surface (your rotated vector) will be color coded according to the colormap you choose, if you display the surface from the top you get your circles at the different brightness.
If you are really only interested from the "top view" of this surface, then no need to create a full surface, a simple pcolor will do the job.
example:
%% // input data (and assumptions)
E=[0 3 1 5 2 7];
nBrightness = 10 ; %// number of brightness levels
r = (0:numel(E)) ; %// radius step=1 by default for consecutive circles
%// otherwise define different thickness for each circle
So if I use stairs([E 0]) you get your different brightness levels:
I had to add a last 0 to the vector to "close" the last level, we'll have to do that again in the solution below.
Now to rotate/replicate that around Y, color code the height, and look at it from the top:
%% // replicate profile around axis
ntt = 50 ; %// define how many angular division for the plot
theta = linspace(0,2*pi,ntt) ; %// create all the angular divisions
[rr,tt]=meshgrid(r,theta) ; %// generate a grid
z = repmat( [E 0] , ntt , 1 ) ; %// replicate our "E" vector to match the grid
[xx,yy,zz] = pol2cart(tt,rr,z) ; %// convert everything to cartesian coordinates
pcolor(xx,yy,zz) %// plot everything
colormap(gray(nBrightness)) %// make sure we use only "nBrightness" colors (Shades of gray)
caxis([0 nBrightness])
shading flat ; axis equal %// refine the view (axis ratio and "spokes" not visible) etc...
colorbar
axis off
will yield the following :
Note that your problem was not fully defined, I had to take assumptions on:
What radius each brightness circle should have ? (I made them all the same but you can modify that)
How many brightness levels you want ? (You can also modify that easily though).
Have you tried the rotate function?
direction = [0 1 0];
rotate(h,direction,90);
In this example a 90 degree rotation is performed around the y axis.
Using this library http://www.mathworks.com/matlabcentral/fileexchange/45952-circle-plotter
%http://www.mathworks.com/matlabcentral/fileexchange/45952-circle-plotter
x0 = 0;
y0 = 0;
colors = [0 3 1 5];
maxC = max(colors);
sz = numel(colors);
for i=fliplr(1:sz)
c = colors(i);
circles(x0,y0,i,'facecolor',[c/maxC c/maxC 0]) % http://au.mathworks.com/help/matlab/ref/colorspec.html
end

3d plot with axes of same length

I have some 3D trajectories I want to plot.
Since they vary a lot in XY, but much less in Z, the default plot3 is misleading, because it automatically scales axes.
I've been told to use axes equal but it has no effect (see the commented line where I used it).
I came up with this code, which in my opinion is very long to achieve a so simple task:
[D,rate]=read_vicon_ascii('csvdata/a1-0.csv');
% or replace above line with D=csvread('stackoverflow-31289872.csv');
% get stackoverflow-31289872.csv at https://drive.google.com/file/d/0B5GjKiDZk3F5UHlVQUxKeFo4SG8/view?pli=1
% indices of X,Y,Z columns
X = 1+(2:3:14);
Y = 2+(2:3:14);
Z = 3+(2:3:14);
Bounds = [ min(min(D(:,X))) max(max(D(:,X)))
min(min(D(:,Y))) max(max(D(:,Y)))
min(min(D(:,Z))) max(max(D(:,Z))) ];
MaxDelta = max(Bounds(:,2)-Bounds(:,1));
SquareBounds = Bounds;
for xyz=1:3
Delta = SquareBounds(xyz,2) - SquareBounds(xyz,1);
SquareBounds(xyz,:) = SquareBounds(xyz,:) + (MaxDelta - Delta) * [-0.5 0.5];
end
figure
hold on
for i=1:5
plot3(D(:,X(i)),D(:,Y(i)),D(:,Z(i)),'r-')
end
xlim(SquareBounds(1,:))
ylim(SquareBounds(2,:))
zlim(SquareBounds(3,:))
%axes equal
hold off
Is there any way to make it better. (or a correct usage of axes equal if that does what is supoosed to do?)

Absolute scale for color map?

I am trying to make a plot with an intensity that varies over time:
[X,Y] = meshgrid(-30:.1:30);
figure;
colormap(bone);
for t = 0:0.1:2*pi
R = sqrt(X.^2 + Y.^2);
Z = cos(t)*abs(besselj(2,R));
surf(Z,'EdgeColor','None');
view(90,90);
axis([0 600 0 600 -0.5 0.5])
pause(0.1);
end
I want to look at this from the top, such that as the Z value changes, the color changes. The problem is that rather than having an absolute scale (black = -0.5, white = 0.5), the color scale is relative to the maximum and minimum values, such that the colors only change when the sign flips change. How can I set an absolute scale for the color map?
Thank you.
You have to use scaled colour mapping mode and set the limits of the scaling by using the caxis command.
Now the problem with your current code is that you call surf at each iteration of the loop, essentially destroying the current plot and generating a new plot each time. This will reset a lot of properties, including the caxis limits to auto. To overcome that, simply create your plot only once before the loop, then in the loop you only change the properties which are modified (the Z values in this case). This way everything else stays the same in the figure.
So you code becomes:
%% // Prepare and initialize the surface plot
[X,Y] = meshgrid(-30:.1:30);
R = sqrt(X.^2 + Y.^2) ; %// this doesn't need to be in the loop
Z = cos(0)*abs(besselj(2,R)) ; %// calculate initial value to create the surface
surfHandle = surf( Z , 'EdgeColor','None' ) ; %// create a first surface, and save the handle to the surface object
colormap(bone);
colorbar %// this is optional, just to make sure the colorbar does not vary
caxis([-5 5 ] ) ; %// this is what sets the color scaling to what you want
view(90,90);
axis([0 600 0 600 -0.5 0.5]) ; %// this doesn't need to be in the loop anymore
%% // Modify and update the surface plot
for t = 0:pi/100:2*pi
Z = cos(t)*abs(besselj(2,R));
set( surfHandle , 'ZData' , Z )
drawnow
pause(0.01);
end
Read coloring-mesh-and-surface-plots for more info on how surfaces can be colored.
If you just want white for values less than 0 and black for values greater than 0, you ca simply do:
surf(Z,sign(Z),'EdgeColor','None');
which uses the optional C argument to surf, telling Matlab to colour the plot depending on the values of C, not Z. sign(Z) is a matrix that has 1's where Z>0, 0's where Z=0, and -1's where Z<0.