Multifaceted Patches with structs (matlab) - matlab

matlab newcomer here.
I have a problem understanding how to use patch() using a structure with given vertices and faces.
It is a simple problem and probably easily solved, but I guess I might need a little inspiration.
I wrote the following example lines after reading through the patch-related Documentations I found:
Z = struct('VoV',[0 0 0; 0 1 0; 0 1 1; 0 0 1],'VoF',[1 2 3 4]);
patch(Z);
Instead of the wanted quadrangle I recieved the error:
Error using patch
Unrecognized property VoV for class Patch.
Any help would be very much appreciated :)

Pulling an example from the MATLAB help page for patch:
clear S
S.Vertices = [2 4; 2 8; 8 4; 5 0; 5 2; 8 0];
S.Faces = [1 2 3; 4 5 6];
S.FaceVertexCData = [0; 1];
S.FaceColor = 'flat';
S.EdgeColor = 'red';
S.LineWidth = 2;
figure
patch(S)
It looks like the field names you want are Vertices and 'Faces' not VoV and FoV.

Related

resize matrix in matlab

i was using the function "resizem" to expand the size of my matrix, without erasing the data. recently, after using the function, it sends me an error that the function cannot use integers of type double. i have tried to use abs().^2 on my matrix but it didn't work.
is there any other function that can do the same?
note: i need the data to not change, so if i have an matrix
A = [-1 0 2; 4 1 2] i want it to become a 5x5 matrix like so:
A = [-1 -0.5 0 1 2; 4 2.5 1 1.5 2]
Also, I have tried the function 'imresize', and gives me the same problem as the resizem. (I own both the tool box, and my matrix is in type double)
If A = [-1 0 2; 4 1 2] you could do something like A = [A, [1, 2; 1.5 2]] to get A = [-1 -0.5 0 1 2; 4 2.5 1 1.5 2].
I would try to go for imresize (which is part of the Image Processing Toolbox). I never used those functions, but looking at the error you are receiving, which is related to variable types, the new option should provide more flexibility. In fact, while resizem returns double precision output, imresize returns an output of the same type as the input.
A = [-1 0 2; 4 1 2];
imresize(A,[2 5]);
The example shows how to use it. I also tested both outcomes:
A = [-1 0 2; 4 1 2];
A_imr = imresize(A,[2 5]);
A_rem = resizem(A,[2 5]);
This is the result for imresize:
A_imr:
-1,08000000000000 -0,720000000000000 -1,77635683940025e-15 1,29600000000000 2,16000000000000
4,24000000000000 2,82400000000000 1,00000000000000 1,48000000000000 2,08000000000000
This is the result for resizem:
A_rem :
-1 -1 0 2 2
4 4 1 2 2
For further tinkering, try to play with scale and method arguments. In imresize, for example, you need to specify the appropriate interpolation kernel to achive averaging.

Increasing samples of a signal in matlab

Hi everybody I have a simple matrix like this Ex = [ 1 5; 2 5; 4 15; 5 15; 7 25; 8 25]; and it is graph is like below. I want to keep the same shape of the signal with more samples. In other words I need to have more rows in my matrix with corresponding values in between, keeping the same behaviour. Thanks for help. ,
The term you want to look into is interpolation, in this case linear interpolation would do nicely. There's a good blog post on this topic here.
The gist is that you can do what you are after using the interp1 function, like so:
Ex = [ 1 5; 2 5; 4 15; 5 15; 7 25; 8 25];
x_points = [1:0.5:8];
y_points = interp1(Ex(:,1),Ex(:,2),x_points,'linear');
Ex2 = [x_points' y_points'];
This should generate y_points for each of the specified x_points and then combine them into a matrix similar to the input (but with more rows).

Having Matlab randomly choose a number from a select few that I designate

sorry if this is relatively simple, but I'm new to Matlab and trying to learn the ropes. What I'm asking is simply the following. I was a function that will randomly choose a number with the only options for it to choose from being -3,-1,1, and 1. What I was trying to do was something like this below.
clear;
N=10e5;
B=randint(1,N,[-3 || -1 || 1 || 3]);
Bmean=sum(B)/N
Bvar=sum((B-Bmean).^2)/(N-1)
but obviously I can't set up a range that way.
Thanks in advance for the help!
Why not only generate random index:
A = [-3 -1 1 3];
idx = randint(1, N, numel(A)) + 1;
B = A(idx);
Fortunately, this is builtin function and does not require extra toolbox.
What about this:
N = 10; I assume N is sample size you want.
B = datasample([-3,-1,1, 1], N);
B =
-3 1 1 1 1 1 -1 1 -3 1
datasample is from statistical toolbox. Not sure you have it or not.

Generate a vector in MATLAB

I am trying to solve a MATLAB problem to generate a vector like 1,2,2,3,3,3,4,4,4,4...
So if n = 3, then return
[1 2 2 3 3 3]
And if n = 5, then return
[1 2 2 3 3 3 4 4 4 4 5 5 5 5 5]
This is what I came up with:
ans=1
for n=2:n
ans=[ans n*ones(1,n)]
end
But I'm trying to minimize the code length. Anyone have any ideas?
still a few lines:
n = 5; %number of elements
A(cumsum(0:n)+1) = 1;
B = cumsum(A(1:end-1))
returns
1 2 2 3 3 3 4 4 4 4 5 5 5 5 5
In the same spirit, here's my one liner:
nonzeros(triu(meshgrid(1:n)))'
n = 5;
A = triu(ones(n,1)*(1:n));
A(A==0) = [];
This is similar to jkshah's answer, but I would approach it slightly differently,
n=5;
M = ones(n,1)*(1:n)
B = M(triu(ones(n))>0)';
Here's another one-liner. Unlike solutions based on triu, this one doesn't generate extra elements as intermediate results (that doesn't mean it's faster, though):
fliplr(cumsum([n full(sparse(ones(1,n-1),cumsum(n:-1:2),-1))]))
A little 'magic' solution:
ceil(sqrt(2*(1:(n^2+n)/2))-0.5)
See visualisation:
This is the plot of function sqrt(2*(1:(n^2+n)/2))-0.5:
plot(1:(n^2+n)/2,sqrt(2*(1:(n^2+n)/2))-0.5,'.')
where xticklabels were changed according the following code:
set(gca,'xtick',cumsum(0:n),'xticklabel',0:n)
it is a litle bit longer
function y = your_fcn_name(n)
N = sum(1:n);w = [] ;
for i=1:n
q(1:i) = i;
w = [w q(1:i)];
end
y = w;
end

MATLAB - Efficient methods for populating matrices using information in other (sparse) matrices?

Apologies for the awkward title, here is a more specific description of the problem. I have a large (e.g. 10^6 x 10^6) sparse symmetric matrix which defines bonds between nodes.
e.g. The matrix A = [0 1 0 0 0; 1 0 0 2 3; 0 0 0 4 0; 0 2 4 0 5; 0 3 0 5 0] would describe a 5-node system, such that nodes 1 and 2 are connected by bond number A(1,2) = 1, nodes 3 and 4 are connected by bond number A(3,4) = 4, etc.
I want to form two new matrices. The first, B, would list the nodes connected to each node (i.e. each row i of B has elements given by find(A(i,:)), and padded with zeros at the end if necessary) and the second, C, would list the bonds connected to that node (i.e. each row i of C has elements given by nonzeros(A(i,:)), again padded if necessary).
e.g. for the matrix A above, I would want to form B = [2 0 0; 1 4 5; 4 0 0; 2 3 5; 2 4 0] and C = [1 0 0; 1 2 3; 4 0 0; 2 4 5; 3 5 0]
The current code is:
B=zeros(length(A), max(sum(spones(A))))
C=zeros(length(A), max(sum(spones(A))))
for i=1:length(A)
B(i,1:length(find(A(i,:)))) = find(A(i,:));
C(i,1:length(nonzeros(A(i,:)))) = nonzeros(A(i,:));
end
which works, but is slow for large length(A). I have tried other formulations, but they all include for loops and don't give much improvement.
How do I do this without looping through the rows?
Hmm. Not sure how to vectorize (find returns linear indices when given a matrix, which is not what you want), but have you tried this:
B=zeros(length(A), 0);
C=zeros(length(A), 0);
for i=1:length(A)
Bi = find(A(i,:));
B(i,1:length(Bi)) = Bi;
Ci = nonzeros(A(i,:));
C(i,1:length(Ci)) = Ci;
end
I made two changes:
removed call to spones (seems unnecessary; the performance hit needed to expand the # of columns in B and C is probably minimal)
cached result of find() and nonzeros() so they're not called twice
I know it's hard to read, but that code is a vectorized version of your code:
[ i j k ] = find(A);
A2=(A~=0);
j2=nonzeros(cumsum(A2,2).*A2);
C2=accumarray([i,j2],k)
k2=nonzeros(bsxfun(#times,1:size(A,2),A2));
B2=accumarray([i,j2],k2);
Try it and tell me if it works for you.