How to plot a rectangular in MATLAB - matlab

It is necessary for me that plot a rectangular in MATLAB by contour. But when I plot this, the figure is like square and no rectangular.
In fact the length of X axis and Y axis are true, but figure is not rectangular.
How could I find a rectangular figure?
Once before I needed to plot a n eliptical by countour and it was like circle, by setting axes([xmin xmax ymin ymax]) this problem was solved but know this command do not work.
Here is my code u0,x,y are 3 vectors of length nx*ny. and nx and ny are the number of points in x axis and y axis.
figure
for i=1:ny
z(i,:)=u0((i-1)*nx+1:i*nx);
x1(i,:)=x((i-1)*nx+1:i*nx);
y1(i,:)=y((i-1)*nx+1:i*nx);
end;
cMap = [0.45 0.6 0.65;1 1 1]; % [green;yellow] on rgb-color
colormap(cMap);
axis equal
contourf(x1,y1,z,'LineColor','none')
colorbar
Let 's=0:0.1:0.2' and 'x=repmat(s,1,ny)' and 'd=0:0.1:1', 'y=repmat(d,1,nx)'
'u0=x+y'

I think the problem is the size of the vector you are using. Check out this example:
x = linspace(0,2,20);
y = linspace(0,1,10);
z = meshgrid(x,y);
contourf(x,y,z,20);
axis equal
it gives the following result:
Now if we check the sizes:
>> size(x)
ans =
1 20
>> size(y)
ans =
1 10
>> size(z)
ans =
10 20
if the size of x vector is equal to the size of the y vector it gives you a square obviously! in your case first check the size of x1, y1, z just before using the contourf an make sure that you are using axis equal after that.

Related

visually plotting a value going to infinity in matlab

I am trying to reproduce the Dirac Delta function:
my code:
x = -30:1:30;
y = zeros(1,numel(x)); %sets all values initially to zero
y(x==0)= inf; % the point corresponding to x=0 is set to inf
plot(x,y,'d')
axis([-40 40 0 inf])
My code produces:
You can do this with stem, specifying its 'Marker' as an up arrow...
% Open figure
figure;
% Blue stem plot at x=0, to y=75. Marker style is up arrow
stem(0, 75,'color','b','linewidth',2,'marker','^')
% Add infinity label at x=0, y = 82 = 75 + fontsize/2, where we plotted up to 75
text(0,82,'∞','FontSize',14)
% Set axes limits
xlim([-40,40])
ylim([0,90])
You can see the output plot here, but see the edit below for an improved version.
Note, of course you should choose a y value which is large relative to any other data on the plot. In this example I chose 75 to roughly match your desired example plot. MATLAB can't plot a value at inf because, well, where does infinity sit on the y axis?
Edit: You can indicate the y-axis is broken with additional '≈' characters as suggested by Marco in the comments. Combining xlim and ylim into one axis call, and changing the y-axis ticks to help indicate the axis break, we get this result:
stem(0, 80,'color','b','linewidth',2,'marker','^')
text([-42,0,38], [80,87,80], {'≈','∞','≈'}, 'Fontsize', 14)
axis([-40, 40, 0, 100])
yticks(0:20:60)
To show infinity, you should not set y to infinity. To do this, you can set y to a large value proportional to the axis values. For example if axis would be like [min_x max_x min_y max_y], you can set y(x==0) = max_y*10.
In your case you will have:
x = -30:1:30; min_x = min(x) - 10; max_x = max(x) + 10;
y = zeros(1,numel(x));
% compute values of y here
% ...
min_y = min(y) - 10; max_y = max(y) + 10;
y(x==0)= 10 * max_y;
plot(x,y,'d');
axis([min_x max_x min_y max_y]);
Use the tick property in Matlab plot as described below

Bar3 plot with seperate x,y,height and width values

Solution posted below function to plot bar 3 with separate x, y values and separate width and height values
bar3(x,y,z,xWidth,yWidth)
We are currently working on a project that allow one to visualize the area under a 3d function, f(x,y). The purpose of this is to demonstrate how the bars cut a 3d surface. Indirectly to visualize the desired integral.
We wish to have the bars match up with the intervals of the surface grid.
Below is a rough demonstration of the idea.
bar3 only has input for the x-values bar3(x,z), where as surf has a input for both the x and y surf(x,y,z)
Unfortunately this is what we are getting. - this is because bar3 cant be in terms of x and y
CODE:
clc;
cla;
d=eval(get(handles.edtOuterUpperB,'string'));
c=eval(get(handles.edtOuterLowerB,'string'));
b=eval(get(handles.edtInnerUpperB,'string'));
a=eval(get(handles.edtInnerLowerB,'string'));
n=eval(get(handles.edtInnerInterval,'string'));
m=eval(get(handles.edtOuterInterval,'string'));
h=(b-a)/n;
k=(d-c)/m;
[x,y] = meshgrid(a:h:b, c:k:d);
f=eval(get(handles.edtFunc,'string'));
surf(x,y,f);
hold on
bar3(f,1);
If you look closely, you will see that the XData and YData are different from the mesh to the 3D bar plot. This is because your mesh uses "real" x and y values while the bar plot uses indexes for the x and y values.
To fix this, you will want to change one or the other. For your case, the easiest one to change is going to be the surface. You can actually just omit the x and y inputs and the indexed x and y values will be used instead by default when generating the surface.
surf(f);
From the documentation for surf:
surf(Z) creates a three-dimensional shaded surface from the z components in matrix Z, using x = 1:n and y = 1:m, where [m,n] = size(Z). The height, Z, is a single-valued function defined over a geometrically rectangular grid. Z specifies the color data, as well as surface height, so color is proportional to surface height.
Update
If you want to keep the non-indexed values on the x and y axes, you will want to convert the bar3 plot instead. Unfortunately, MATLAB provides a way to specify the x axis bot not the y axis. You can take one of two approaches.
Change the XData
You can get the XData property of the resulting bar objects and change them to the data you want.
x = a:h:b;
y = c:k:d;
%// Anonymous function to scale things for us
scaler = #(vals)x(1) + ((vals-1) * (x(end) - x(1)) / (numel(x) - 1));
%// Create the bar plot
bars = bar3(y, f);
%// Change the XData
xdata = get(bars, 'XData');
xdata = cellfun(scaler, xdata, 'uni', 0);
set(bars, {'XData'}, xdata);
set(gca, 'xtick', x)
%// Now plot the surface
surf(x,y,f);
And just to demonstrate what this does:
x = linspace(0.5, 1.5, 5);
y = linspace(2.5, 4.5, 4);
f = rand(4,5);
scaler = #(vals)x(1) + ((vals-1) * (x(end) - x(1)) / (numel(x) - 1));
bars = bar3(y, f);
set(bars, {'XData'}, cellfun(scaler, get(bars, 'XData'), 'uni', 0))
set(gca, 'xtick', x)
axis tight
Change the XTickLabels
Instead of changing the actual data, you could simply change the values that are displayed to be what you want them to be rather than the indexed values.
x = a:h:b;
y = c:k:d;
labels = arrayfun(#(x)sprintf('%.2f', x), x, 'uni', 0);
bar3(y, f);
set(gca, 'xtick', 1:numel(x), 'xticklabels', labels);
hold on
%// Make sure to use the INDEX values for the x variable
surf(1:numel(x), y, f);
We found a user contributed function scatterbar3, which does what we want, in a different way than what bar3 uses:
http://www.mathworks.com/matlabcentral/fileexchange/1420-scatterbar3
There was however a slight hiccup that we had to correct:
hold on
scatterbar3(x,y,f,h);
scatterbar3 does not have separate inputs for the width and height of the bars, thus large gaps occur when the intervals do not equal one another. Demonstrated below.
We thus edited the scatterbar3 function in order to take both the width and height of the bars as inputs:
Edited scatterbar3 function:
function scatterbar3(X,Y,Z,widthx,widthy)
[r,c]=size(Z);
for j=1:r,
for k=1:c,
if ~isnan(Z(j,k))
drawbar(X(j,k),Y(j,k),Z(j,k),widthx/2,widthy/2)
end
end
end
zlim=[min(Z(:)) max(Z(:))];
if zlim(1)>0,zlim(1)=0;end
if zlim(2)<0,zlim(2)=0;end
axis([min(X(:))-widthx max(X(:))+widthx min(Y(:))-widthy max(Y(:))+widthy zlim])
caxis([min(Z(:)) max(Z(:))])
function drawbar(x,y,z,widthx,widthy)
h(1)=patch([-widthx -widthx widthx widthx]+x,[-widthy widthy widthy -widthy]+y,[0 0 0 0],'b');
h(2)=patch(widthx.*[-1 -1 1 1]+x,widthy.*[-1 -1 -1 -1]+y,z.*[0 1 1 0],'b');
h(3)=patch(widthx.*[-1 -1 -1 -1]+x,widthy.*[-1 -1 1 1]+y,z.*[0 1 1 0],'b');
h(4)=patch([-widthx -widthx widthx widthx]+x,[-widthy widthy widthy -widthy]+y,[z z z z],'b');
h(5)=patch(widthx.*[-1 -1 1 1]+x,widthy.*[1 1 1 1]+y,z.*[0 1 1 0],'b');
h(6)=patch(widthx.*[1 1 1 1]+x,widthy.*[-1 -1 1 1]+y,z.*[0 1 1 0],'b');
set(h,'facecolor','flat','FaceVertexCData',z)
Finally the working solution in action:
hold on
scatterbar3(x,y,f,h,k);

How to set x and y values for Bar3 plotting in Matlab?

I have a matrix for example A=rand(60,60). I want to set the x-axis and y-axis value with step size: 1:2:119 in 3d bar (matlab bar3). I already tried to make it but it doesn't work for large matrix. Note, y-axis is perfect but x-axis is not, it shows from 1 to 60. For example:
Z = rand(60,60);[r,c] = size(Z);
Y = 1:2:119; % y-axis value
X = 1:2:119; % x-axis value
bar3(Y,Z); set(gca,'XTick', X)
See: xlim and ylim
Z = rand(60,60);
[r,c] = size(Z);
Y = 1:2:119; % y-axis value
X = 1:2:119; % x-axis value
bar3(Y,Z);
xlim([X(1), X(end)]);
set(gca,'XTick', X)
ylim([Y(1), Y(end)]);
set(gca,'YTick', Y)
The ticks are super crowded but I'm just going with what you specified in your example.

Plotting a zplot using Matlab

I am trying to plot a zplot in Matlab that displays a unit circle, centered at 0 along with the poles and zeros of the plot. I am not allowed to use any other matlab function such as zplane or pzplot to do this. So far I am able to plot a unit circle just fine but I am having trouble getting my plot to display more of the axis without warping my circle. I also am having a heard time finding the poles and zeros of my function and also how to display the poles as little x's and the zeros as little o's on my plot. Any help would be greatly appreciated! My assignment looks like this and must correctly handle cases such as
zplot([0 1 1], [0 1]);
zplot([0 1 1], [0 0 1]);
function zplot(b, a)
% ZPLOT Plot a zero-pole plot.
-1 -nb
B(z) b(1) + b(2)z + .... + b(nb+1)z
H(z) = ---- = ---------------------------------
-1 -na
A(z) a(1) + a(2)z + .... + a(na+1)z
% zplot(b, a) plots the zeros and poles which determined by vectors b and a
% The plot includes the unit circle and axes for reference, plotted in black.
% Each zero is represented with a blue 'o' and each pole with a red 'x' on the
%plot.
xmin;
xmax;
ymin;
ymax;
% vector of angles at which points are drawn
angle = 0:2*pi/100:2*pi;
% Unit radius
R = 1;
% Coordinates of the circle
x = R*cos(angle);
y = R*sin(angle);
% Plot the circle
plot(x,y);
axis ([xmin, xmax, ymin, ymax]);
grid on;
end
If you can't use pzplot() it is not hard. Here is a hint:
num = [1 4 1];%numerator coefficients of transfer function
den = [1 2 1];%denominator coefficients
z = roots(num)%zeros
p = roots(den)%poles
angle = 0:2*pi/100:2*pi;
xp = cos(angle);
yp = sin(angle);
figure(1)
scatter(z,zeros(length(z),1),'o');
hold on
scatter(p,zeros(length(p),1),'x');
plot(xp,yp);
axis equal
The output
Note that I haven't dealt with imaginary poles/zeros in this example. You'll need to calculate the proper x,y coordinates for a given imaginary pole or zero. (all the poles/zeros in this example are real, not imaginary)
Given a transfer function G, you can use the pzplot() command and add a circle to it.
G = tf([1 4 1],[1 2 1]);
angle = [0:0.1:2*pi+0.1];
xp = cos(angle);
yp = sin(angle);
figure(1)
hold on
pzplot(G);
plot(xp,yp);
axis equal;
This should give you the pole-zero plot with x's for poles, o's for zeros, and the unit circle.
Here is the result.

Set surf minimum for matlab

I have a function which takes a voxel representation of a 3D landscape and can plot a X-Y section to show the middle of the landscape. The voxel representation is stored in a 3 dimensional matrix with a number that represents something important. Obviously the matrix is
1,1,1
2,2,2
in terms of accessing the elements but the actual 3D locations are found in the following method:
(index-1)*resolution+0.5*resolution+minPos;
where resolution is the grid size :
resolution
<-->
__ __ __
|__|__|__|
<- Min pos
and minPos is where the grid starts.
Now in terms of the actual question, i would like to extract a single X-Y section of this voxel representation and display it as a surf. This can be done by just doing this:
surf(voxel(:, :, section))
however then you get this:
The obvious problem is that the grid will start at 0 because that is how the matrix representation is. How can i set the minimum and cell size for surf, ie so that the grid will start at the minimum (shown above) and will have the grid spacing of resolution (shown above).
Read the documentation of surf, you can also provide x and y coordinates corresponding to your data points.
surf(X,Y,Z)
X and Y can be either vectors or matrices:
surf(X,Y,Z) uses Z for the color data and surface height. X and Y are vectors or matrices defining the x and y components of a surface. If X and Y are vectors, length(X) = n and length(Y) = m, where [m,n] = size(Z). In this case, the vertices of the surface faces are (X(j), Y(i), Z(i,j)) triples. To create X and Y matrices for arbitrary domains, use the meshgrid function
Example
Z=[ 0 1 2 3;
7 6 5 4;
8 9 10 11];
x=[-1 0 1 2];
y=[-2 0 2];
surf(x,y,Z);
Of course you have to match Z, x and y matrices/vectors as clearly described in the doc^^
Just remember that elements in columns of Z are surf'ed as values along the y-axis, elements in rows of Z are surf'ed as values along the x-axis. This is clearly to be seen in the example picture.
Solution
I think you switched the x and y-axis around, which you can fix by just transposing z:
s = size(voxel);
xi = (minPosX:resolution:(minPosX+resolution*s(1)-1));
yi = (minPosY:resolution:(minPosY+resolution*s(2)-1));
z = (voxel(:,:,section));
surf(xi, yi, z');
or that you're picking the wrong numbers for constructing xi and yi and it should be this instead:
xi = (minPosX:resolution:(minPosX+resolution*s(2)-1));
yi = (minPosY:resolution:(minPosY+resolution*s(1)-1));
z = (voxel(:,:,section));
surf(xi, yi, z);
So it was easy enough to do:
lets say we have a 3D matrix "voxel";
s = size(voxel);
xi = (minPosX:resolution:(minPosX+resolution*s(1)-1));
yi = (minPosY:resolution:(minPosY+resolution*s(2)-1));
z = (voxel(:,:,section));
[x y] = meshgrid(xi, yi);
x = x';
y = y';
surf(x, y, z);
Provides the following plot:
This is rotated which is annoying, I cant seem to get it to rotate back (I could just visualise around the other way but that's ok)