MatLab--How would I generate an n-sided shape wher n >= 4 - matlab

I'm new to Matlab but I know a bit about programming.
For class, we have been asked to generate a matrix that gives the vertices of a two dimensional n-sided shape where n>=4. Then, generate the vectors to connect the vertices. We were also given a hint: a vector for each segment can be found by adding the vectors drawn from the origin to each of two adjacent vertices.
I know how to create a matrix using A = [1 1; 1 2; 2 2; 2 1] but I'm not sure how to draw the vectors given this or any other matrix.
The plot() function looks promising, but I'm unsure how to use it with the matrix.
Thank you for any suggestions.
Btw, I'm using Matlab 2011a

I'm not exactly sure how your matrix represents your shape but you might for example let the x-coordinates of the shape be the first column of your array, then let the y-coordinates be the 2nd column, like:
A = [1 1; 1 2; 2 2; 2 1];
x = A(:,1);
y = A(:,2);
fill(x,y,'g');
axis([0 3 0 3]);
axis square;
Which in your case plots a square from the matrix A:
Or construct something a little more complicated like a pentagon:
theta = [0:pi/2.5:2*pi];
x = sin(theta);
y = cos(theta);
% your matrix is then:
B(:,1) = x;
B(:,2) = y;
B
figure;fill(x,y,'g');
axis square;
Which gives:

If you just want to plot the outline with plot (not fill the interior with fill), just remember you have to repeat the initial point at the end so that the polygonal line is closed:
A = [1 1; 1 2; 2 2; 2 1];
B = [A; A(1,:) ]; %// repeat first row at the end
plot(B(:,1),B(:,2))
axis equal %// same scale on both axes
axis([min(x)-.5 max(x)+.5 min(y)-.5 max(y)+.5]) %// larger axes for better display

Related

Creating graphs that show the distribution in space of a large number of 2D Random Walks at three different time points

So essentially I have this code here that I can use to generate a 2D Random Walk discretely along N number of steps with M number of walkers. I can plot them all on the same graph here.
clc;
clearvars;
N = 500; % Length of the x-axis, also known as the length of the random walks.
M = 3; % The amount of random walks.
x_t(1) = 0;
y_t(1) = 0;
for m=1:M
for n = 1:N % Looping all values of N into x_t(n).
A = sign(randn); % Generates either +1/-1 depending on the SIGN of RAND.
x_t(n+1) = x_t(n) + A;
A = sign(randn); % Generates either +1/-1 depending on the SIGN of RAND.
y_t(n+1) = y_t(n) + A;
end
plot(x_t, y_t);
hold on
end
grid on;
% Enlarge figure to full screen.
set(gcf, 'Units', 'Normalized', 'Outerposition', [0, 0.05, 1, 0.95]);
axis square;
Now, I want to be able to Create graphs that show the distribution in space of the positions of a large number
(e.g. n = 1000) random walkers, at three different time points (e.g. t = 100, 200 and 300 or any three time points really).
I'm not sure how to go about this, I need to turn this into a function and iterate it through itself three different times and store the coordinates? I have a rough idea but iffy on actually implementing. I'd assume the safest and least messy way would be to use subplot() to create all three plots together in the same figure.
Appreciate any assistance!
You can use cumsum to linearize the process. Basically you only want to cumsum a random matrix composed of [-1 and 1].
clc;
close all;
M = 50; % The amount of random walks.
steps = [10,200,1000]; % here we analyse the step 10,200 and 1000
cc = hsv(length(steps)); % manage the color of the plot
%generation of each random walk
x = sign(randn(max(steps),M));
y = sign(randn(max(steps),M));
xs = cumsum(x);
xval = xs(steps,:);
ys = cumsum(y);
yval = ys(steps,:);
hold on
for n=1:length(steps)
plot(xval(n,:),yval(n,:),'o','markersize',1,'color',cc(n,:),'MarkerFaceColor',cc(n,:));
end
legend('10','200','1000')
axis square
grid on;
Results:
EDIT:
Thanks to #LuisMendo that answered my question here, you can use a binomial distribution to get the same result:
steps = [10,200,10000];
cc = hsv(length(steps)); % manage the color of the plot
M = 50;
DV = [-1 1];
p = .5; % probability of DV(2)
% Using the #LuisMendo binomial solution:
for ii = 1:length(steps)
SDUDx(ii,:) = (DV(2)-DV(1))*binornd(steps(ii), p, M, 1)+DV(1)*steps(ii);
SDUDy(ii,:) = (DV(2)-DV(1))*binornd(steps(ii), p, M, 1)+DV(1)*steps(ii);
end
hold on
for n=1:length(steps)
plot(SDUDx(n,:),SDUDy(n,:),'o','markersize',1,'color',cc(n,:),'MarkerFaceColor',cc(n,:));
end
legend('10','200','1000')
axis square
grid on;
What is the advantage ? Even if you have a big number of steps, let's say 1000000, matlab can handle it. Because in the first solution you have a bruteforce solution, and in the second case a statistical solution.
If you want to show the distribution of a large number, say 1000, of these points, I would say the most suitable way of plotting is as a 'point cloud' using scatter. Then you create an array of N points for both the x and the y coordinate, and let it compute the coordinate in a loop for i = 1:Nt, where Nt will be 100, 200, or 300 as you describe. Something along the lines of the following:
N = 500;
x_t = zeros(N,1);
y_t = zeros(N,1);
Nt = 100;
for tidx = 1:Nt
x_t = x_t + sign(randn(N,1));
y_t = y_t + sign(randn(N,1));
end
scatter(x_t,y_t,'k*');
This will give you N x and y coordinates generated in the same way as in the sample you provided.
One thing to keep in mind is that sign(0)=0, so I suppose there is a chance (admittedly a small one) of not altering the coordinate. I am not sure if you intended this behaviour to be possible (a walker standing still)?
I will demonstrate the 1-dimensional case for clarity; you only need to implement this for each dimension you add.
Model N steps for M walkers using an NxM matrix.
>> N = 5;
>> M = 4;
>> steps = sign(randn(N,M));
steps =
1 1 1 1
-1 1 -1 1
1 -1 -1 -1
1 1 -1 1
1 -1 -1 -1
For plotting, it is useful to make a second NxM matrix s containing the updated positions after each step, where s(N,M) gives the position of walker M after N steps.
Use cumsum to vectorize instead of looping.
>> s = cumsum(steps)
s =
1 1 1 1
0 2 0 2
1 1 -1 1
2 2 -2 2
3 1 -3 1
To prevent plot redraw after each new line, use hold on.
>> figure; hold on
>> plot(1:N, s(1:N, 1:M), 'marker', '.', 'markersize', 20, 'linewidth', 3)
>> xlabel('Number of steps'); ylabel('Position')
The output plot looks like this: picture
This method scales very well to 2- and 3-dimensional random walks.

How to plot mesh (with intensity profile on z) Nx3 matrix in Octave/Matlab?

I have got a data that are in a matrix of size N rows by 3 columns, each column corresponds to particular point in x, y and z axis. The data in that matrix have already been pre generated so my task is to plot it in a mesh as this is faster than creating the same plot with scatter function requiring 1M data points just to look similar.
The z will determine the corresponding color intensity as well as the valley and hills of the mesh.
Consider the example below:
A = [1 2 3; 1 3 2; 1 5 8; 1 2 6; 6 1 2];
mesh(A(:,1),A(:,2),A(:,3));
The attempt was nice, as I have already supplied appropriate x, y, and z for mesh function. However, I just get empty plot when I tested it. So, I am looking for help on how to plot mesh (with intensity profile on z) Nx3 matrix in Octave/Matlab?
Read about delaunay triangulation. YOu can make an unstructured mesh from your (x,y,z) data and then plot the mesh.
A = [1 2 3; 1 3 2; 1 5 8; 1 2 6; 6 1 2];
% mesh(A(:,1),A(:,2),A(:,3));
x = A(:,1) ;
y = A(:,2) ;
z = A(:,3) ;
dt = delaunayTriangulation(x,y) ;
triplot(dt) ;

Changing the coordinates using a vector

Let's say I am at the point (0, 0) in MATLAB and I want to move in the coordinate plane, let's say by the vector [1, 1]. Clearly, I could just manually add 1 and 1 to the x and y coordinates, or I could set v = [1, 1] and increment x by v(1) and y by v(2) or something along those lines. However, let's say I didn't want to do this. For example, suppose my aim is to plot the graph generated by the following algorithm.
Start at the point (0, 0)
Alternate between the displacement vectors (1, 1) and (1, -1) until you reach (100, 0).
Graph it.
How would I do this using the vector directly? In other words, is there something in MATLAB which allows you to directly do something like position = current position + vector? Thanks!
Here is a way to do it from what I understood:
clc
clear
%// The 2 displacement vectors
d1 = [1 1];
d2 = [1 -1];
%// Create a matrix where each row alternates between d1 and d2.
%// In the following for-loop we will access each row one by one to create the displacement.
D = repmat([d2;d1],51,1);
%/ Initialize matrix of positions
CurrPos = zeros(101,2);
%// Calculate and plot
hold all
for k = 2:101
CurrPos(k,:) = CurrPos(k-1,:) + D(k,:); %// What you were asking, I think.
%// Use scatter to plot.
scatter(CurrPos(k,1),CurrPos(k,2),40,'r','filled')
end
box on
grid on
And the output:
Is this what you had in mind?

How to map a matrix to a coordinate and plot it

I have been struggling with this problem for a while and I would appreciate if anyone can help me out. I am able to generate a 10 by 10 matrix and have it randomly assign "1"s in the matrix. My goal is to plot a "star" at the location of each element in the vector that has a value of "1", but I can't seem to figure out how to map the vector to a x-y coordinate system. The code I wrote below generates a plot of 100 stars at each cell and also generates a vector "v", but I don't know how I can link the plot to the vector that instead of having 100 "star"s in my plot, I have however many that there is a value of "1" at the corresponding location of the element.
Thanks!!
David
davidtongg#gmail.com
close all
clear all
clc
a=10;b=10;
v = zeros(a,b);
xy = int32(randi(a, 100, 2));
z = randi(1, 100, 1); % 100 values.
indexes = sub2ind([a, b], xy(:,1), xy(:,2))
v(indexes) = z
m=length(v);
ctr=0;
for i=1:m^2
x_cor(i)=(i-(floor(i/m)*m))*200-100;
y_cor(i)=(floor(i/m)+1)*200-100;
for j=1:m
if i==j*m
x_cor(i)=((i-(floor(i/m)*m))*200-100)+(2*m*100);
y_cor(i)=(floor(i/m))*200-100;
end
end
end
figure(1)
plot(x_cor,y_cor,'*');
grid on
I may of course have misinterpreted this because that code is confusingly complicated, but this is what I think you're after.
For an axb matrix with a random number of ones:
v = randi([0 1], a, b);
Or for a specific number n of ones, in random locations:
v = zeros(a, b);
idx = randi([1 numel(v)], n, 1);
v(idx) = 1; % linear indexing into a matrix
Then to plot them in arbitrarily scaled coordinates:
[y x] = find(v);
x = x * xscale + xoffset;
y = y * yscale + yoffset;
plot(x, y, '*');
Or the really cheaty way:
spy(v);
You can do it easily taking into account that plot(A) , where A is a matrix, plots the columns of the matrix vs their index, and that NaNs are not plotted:
v =[ 1 0 0 0
1 1 0 0
0 0 0 1
1 1 1 1
0 1 1 0 ]; %// example data
v2 = double(v); %// create copy; will be overwritten
v2(~v2) = NaN; %// change zeros to NaNs
plot(bsxfun(#plus, fliplr(v2.'), 0:size(v,1)-1) ,'b*')
%'// transpose and flip from left to right.
%// Add 1 incrementally to each column to have all of them "stacked" in the plot
axis([0 size(v,2)+1 0 size(v,1)+1]) %// set axis limits
set(gca,'xtick',1:size(v,2),'ytick',1:size(v,1)) %// set ticks
grid

Ellipse around the data in MATLAB

I would like to reproduce the following figure in MATLAB:
There are two classes of points with X and Y coordinates. I'd like to surround each class with an ellipse with one parameter of standard deviation, which determine how far the ellipse will go along the axis.
The figure was created with another software and I don't exactly understand how it calculates the ellipse.
Here is the data I'm using for this figure. The 1st column is class, 2nd - X, 3rd - Y. I can use gscatter to draw the points itself.
A = [
0 0.89287 1.54987
0 0.69933 1.81970
0 0.84022 1.28598
0 0.79523 1.16012
0 0.61266 1.12835
0 0.39950 0.37942
0 0.54807 1.66173
0 0.50882 1.43175
0 0.68840 1.58589
0 0.59572 1.29311
1 1.00787 1.09905
1 1.23724 0.98834
1 1.02175 0.67245
1 0.88458 0.36003
1 0.66582 1.22097
1 1.24408 0.59735
1 1.03421 0.88595
1 1.66279 0.84183
];
gscatter(A(:,2),A(:,3),A(:,1))
FYI, here is the SO question on how to draw ellipse. So, we just need to know all the parameters to draw it.
Update:
I agree that the center can be calculated as the means of X and Y coordinates. Probably I have to use principal component analysis (PRINCOMP) for each class to determine the angle and shape. Still thinking...
Consider the code:
%# generate data
num = 50;
X = [ mvnrnd([0.5 1.5], [0.025 0.03 ; 0.03 0.16], num) ; ...
mvnrnd([1 1], [0.09 -0.01 ; -0.01 0.08], num) ];
G = [1*ones(num,1) ; 2*ones(num,1)];
gscatter(X(:,1), X(:,2), G)
axis equal, hold on
for k=1:2
%# indices of points in this group
idx = ( G == k );
%# substract mean
Mu = mean( X(idx,:) );
X0 = bsxfun(#minus, X(idx,:), Mu);
%# eigen decomposition [sorted by eigen values]
[V D] = eig( X0'*X0 ./ (sum(idx)-1) ); %#' cov(X0)
[D order] = sort(diag(D), 'descend');
D = diag(D);
V = V(:, order);
t = linspace(0,2*pi,100);
e = [cos(t) ; sin(t)]; %# unit circle
VV = V*sqrt(D); %# scale eigenvectors
e = bsxfun(#plus, VV*e, Mu'); %#' project circle back to orig space
%# plot cov and major/minor axes
plot(e(1,:), e(2,:), 'Color','k');
%#quiver(Mu(1),Mu(2), VV(1,1),VV(2,1), 'Color','k')
%#quiver(Mu(1),Mu(2), VV(1,2),VV(2,2), 'Color','k')
end
EDIT
If you want the ellipse to represent a specific level of standard deviation, the correct way of doing is by scaling the covariance matrix:
STD = 2; %# 2 standard deviations
conf = 2*normcdf(STD)-1; %# covers around 95% of population
scale = chi2inv(conf,2); %# inverse chi-squared with dof=#dimensions
Cov = cov(X0) * scale;
[V D] = eig(Cov);
I'd try the following approach:
Calculate the x-y centroid for the center of the ellipse (x,y in the linked question)
Calculate the linear regression fit line to get the orientation of the ellipse's major axis (angle)
Calculate the standard deviation in the x and y axes
Translate the x-y standard deviations so they're orthogonal to the fit line (a,b)
I'll assume there is only one set of points given in a single matrix, e.g.
B = A(1:10,2:3);
you can reproduce this procedure for each data set.
Compute the center of the ellipsoid, which is the mean of the points. Matlab function: mean
Center your data. Matlab function bsxfun
Compute the principal axis of the ellipsoid and their respective magnitude. Matlab function: eig
The successive steps are illustrated below:
Center = mean(B,1);
Centered_data = bsxfun(#minus,B,Center);
[AX,MAG] = eig(Centered_data' * Centered_data);
The columns of AX contain the vectors describing the principal axis of the ellipsoid while the diagonal of MAG contains information on their magnitude.
To plot the ellipsoid, scale each principal axis with the square root of its magnitude.