Polyarea returns false value - matlab

X = [0 0 1 1];
Y = [0 1 0 1];
polyarea(X,Y)
ans = 0
Here the answer should be 1 , but I got this as answer , there is no prob with other co ordinates

Take care of the vertices order
X = [0 0 1 1];
Y = [0 1 1 0];
should work.

Related

Undefined function or variable for 3dos mechanism

I tried to make a 3dof(3 degrees of freedom mechanism) in matlab but i get this error and i don't know why.
this is for a school project and i need to simulate a human finger.
the code is running normal but after i enter the values for the angles it says that A,B,C are
undefined and i don't know why
a1 = input('valuarea lui q1(grade):');
a2 = input('valuarea lui q2(grade):');
a3 = input('valuarea lui q3(grade):');
L1=35;
L2=45;
L3=30;
z = [-10 10];
plot(z,10);
grid ON;
O=[0;0;0;1];
m= linspace(pi/2,pi/2+a1*pi/180,100);
n = linspace(-pi/2,a2*pi/180,100);
k=linspace(-pi/2,a3*pi/180,100);
for a=1:100
[A1,B1,C1] = Transform(m(a),n(a),k(a),L1,L2,L3);
x = [O(1) A(1) B(1) C(1)];
y = [O(2) A(2) B(2) C(2)];
Cx(i)= C1(1);
Cy(i) = C1(2);
i=i+1;
Plot = plot(x,y,'r',...1
'LineWidth',1);
title('Sumularea unui deget');
plot(Cx,Cy,'--g',...
'LineWidth',1);
pause(0.075);
delete(Plot);
end
plot(x,y,'r',...
'LineWidth',3);
function [A,B,C ] = Transform( m,n,p,l1,l2,l3 )
P = [0;0;0;1];
T1 = [cos(m) -sin(m) 0 0;sin(m) cos(m) 0 0;0 0 1 0; 0 0 0 1];
T2 = [cos(n) -sin(n) 0 11;sin(n) cos(n) 0 0;0 0 1 0; 0 0 0 1];
T3 = [cos(p) -sin(p) 0 12;sin(p) cos(p) 0 0;0 0 1 0; 0 0 0 1];
T4 = [1 0 0 13;0 1 0 0; 0 0 1 0; 0 0 0 1];
A = T1*T2*P;
B = T1*T2*T3*P;
C = T1*T2*T3*T3*P;
end
In your main function, this is the first use of the variables:
x = [O(1) A(1) B(1) C(1)];
They are never written previously. Instead A1 is written, which is a different variable. I guess you mixed the two up.

Writing a loop that works for any value of N

I have a code for a 1D heat equation. Im trying to format a for loop so that the A matrix will follow a certain pattern of 1 -2 1 down the entire diagonal of a matrix that could be infinite. The pattern starts to take shape when I mess around with the initialized count at the beginning of the for loop but this changes the size of the matrix which fails the rest of the code.
My current code is below. The commented A matrix edits are what it should be.
N = 5;
%A(2,1:3) = [1 -2 1];
%A(3,2:4) = [1 -2 1];
%A(4,3:5) = [1 -2 1];
%A(5,4:6) = [1 -2 1];
A = zeros(N+1,N+1);
A(1,1) = 1;
for count=N:N+1
A(count+1,count:count+2) = [1 -2 1];
end
A(N+1,N+1) = 1;
In Matlab you can often avoid loops. In this case you can get the desired result with 2D convolution:
>> N = 6;
>> A = [1 zeros(1,N-1); conv2(eye(N-2), [1 -2 1]); zeros(1,N-1) 1]
A =
1 0 0 0 0 0
1 -2 1 0 0 0
0 1 -2 1 0 0
0 0 1 -2 1 0
0 0 0 1 -2 1
0 0 0 0 0 1
Or, depending on what you want,
>> A = conv2(eye(N), [1 -2 1], 'same')
A =
-2 1 0 0 0 0
1 -2 1 0 0 0
0 1 -2 1 0 0
0 0 1 -2 1 0
0 0 0 1 -2 1
0 0 0 0 1 -2
There are many simple ways of creating this matrix.
Your loop can be amended as follows:
N = 5;
A = zeros(N+1,N+1);
A(1,1) = 1;
for row = 2:N
A(row, row-1:row+1) = [1 -2 1];
end
A(N+1,N+1) = 1;
I've renamed count to row, we're indexing each row (from 2 to N, skipping the first and last rows), then finding with row-1:row+1 the three indices for that row that you want to address.
Directly indexing the diagonal and off-diagonal elements. Diagonal elements for an NxN matrix are 1:N+1:end. This is obviously more complex, I'd prefer the loop:
N = 6;
A = zeros(N,N);
A(1:N+1:end) = -2;
A(2:N+1:end-2*N) = 1; % skip last row
A(2*N+2:N+1:end) = 1; % skip first row
A(1,1) = 1;
A(N,N) = 1;
Using diag. We need to special-case the first and last rows:
N = 6;
A = diag(-2*ones(N,1),0) + diag(ones(N-1,1),1) + diag(ones(N-1,1),-1);
A(1,1:2) = [1,0];
A(end,end-1:end) = [0,1];

Why does my 3 axes system coordinate orientation change x with y values?

I am using Matlab and Euler Angles in order to reorient a 3axes coordinate system. Specifically,
Rz = [cos(ψ) sin(ψ) 0;-sin(ψ) cos(ψ) 0;0 0 1];
Ry = [cos(φ) 0 -sin(φ);0 1 0;sin(φ) 0 cos(φ)];
Rx = [1 0 0;0 cos(θ) -sin(θ);0 sin(θ) cos(θ)];
Rtotal = Rz*Ry*Rz
Then I loop through my old system coordinates (x,y,z) and make a vector coord_old. Then I get the reoriented system with (xn,yn,zn)
for i=1:size(num,1)
coord_old = [x(i,1);y(i,1);z(i,1)];
coord_new = Rtotal*coord_old;
xn(i,1) = coord_new(1,1);
yn(i,1) = coord_new(2,1);
zn(i,1) = coord_new(3,1);
end
My issue is that when θ,φ,ψ≃0 then x->-y and y->x and when θ,φ≃0 and ψ=90 then x and y will not rotate! That means that when x,y should rotate they don't and when they shouldn't rotate they stay as they were!
--EDIT--
For example, when ψ=20.0871, φ=0.0580 and θ=0.0088 I get these results
See that x->-y and y->x while z doesn't change at all!
Any thoughts?
Ok, I see two main problems here:
Rtotal = Rz*Ry*Rz is probably not what you want since Rz is multiplied twice. I think you mean Rtotal = Rz*Ry*Rx.
Your rotation matrix seems to be incorrect. Check this Wikipedia artice to get the correct signs.
Here a corrected rotation matrix:
Rz = [cos(psi) -sin(psi) 0; sin(psi) cos(psi) 0; 0 0 1];
Ry = [cos(phi) 0 sin(phi); 0 1 0; -sin(phi) 0 cos(phi)];
Rx = [1 0 0; 0 cos(theta) -sin(theta); 0 sin(theta) cos(theta)];
Rtotal = Rz*Ry*Rx;
With this matrix I get the correct results:
x=1; y=2; z=3;
psi=0; phi=0; theta=0;
[xn,yn,zn] >> 1 2 3
x=1; y=2; z=3;
psi=90/180*pi; phi=0; theta=0;
[xn,yn,zn] >> -2 1 3
And here a full graphical example of a cube in 3d-space:
% Create cube (not in origin)
DVert = [0 0 0; 0 1 0; 1 1 0; 1 0 0 ; ...
0 0 1; 0 1 1; 1 1 1; 1 0 1];
DSide = [1 2 3 4; 2 6 7 3; 4 3 7 8; ...
1 5 8 4; 1 2 6 5; 5 6 7 8];
DCol = [0 0 1; 0 0.33 1; 0 0.66 1; ...
0 1 0.33; 0 1 0.66; 0 1 1];
% Rotation angles
psi = 20 /180*pi; % Z
phi = 45 /180*pi; % Y
theta = 0 /180*pi; % X
% Rotation matrix
Rz = [cos(psi) -sin(psi) 0; sin(psi) cos(psi) 0; 0 0 1];
Ry = [cos(phi) 0 sin(phi); 0 1 0; -sin(phi) 0 cos(phi)];
Rx = [1 0 0; 0 cos(theta) -sin(theta); 0 sin(theta) cos(theta)];
Rtotal = Rz*Ry*Rz;
% Apply rotation
DVertNew = Rtotal * DVert';
% Plot cubes
figure;
patch('Faces',DSide,'Vertices',DVert,'FaceColor','flat','FaceVertexCData',DCol);
patch('Faces',DSide,'Vertices',DVertNew','FaceColor','flat','FaceVertexCData',DCol);
% Customize view
grid on;
axis equal;
view(30,30);
When I use your code and insert 0 for all angles, I get Rtotal:
Rtotal =
1 0 0
0 1 0
0 0 1
This is the identity matrix and will not change your values.
You have an error in your matrix multiplication. I think you should multiply: Rtotal*coord_old. I think you are missing the _old. depending on what is in you coordvariable, this may be the bug.
When I run:
for i=1:size(1,1)
coord_old = [1;2;3];
coord_new = Rtotal*coord_old;
xn(i,1) = coord_new(1,1);
yn(i,1) = coord_new(2,1);
zn(i,1) = coord_new(3,1);
end
I get the correct result:
coord_new =
1
2
3
Thank you both #Steffen and #Matt. Unfortunately, my reputation is not high enough to vote Up your answers!
The problem was not with Rtotal as #Matt correctly stated. It should be as it was Rz*Ry*Rx. However, both your ideas helped me test my code with simple examples (5 sets of coordinates and right hand rule), and realize where my (amateur) mistake was.
I had forgotten I had erased parts of codes where I was expressing my angles to degrees... I should be using sind & cosd instead of sin and cos.

Conditionally replace neighbouring cells

Lets say I have a matrix A:
A =
0 1 0 0
0 0 0 0
0 0 0 1
0 0 0 0
And I want to create a new matrix B of the same dimension where all ones and accompanying neighbours are replaced by the following matrix:
X =
1 1 1
1 2 1
1 1 1
The 2 in matrix X should be placed 'on top' of the 1 values as to get:
B =
1 2 1 0
1 1 2 1
0 0 1 2
0 0 1 1
Values should be added up where elements overlap and matrix X should be 'cut off' in places where it extends the dimensions of matrix A/B The idea is to eventually replace X by a 2d gaussian distribution and matrix A will be large containing many more ones. So it's essential that the code is efficient and fast. This is the code i came up with:
A = [0 1 0 0;0 0 0 0;0 0 0 1;0 0 0 0]
X = [1 1 1;1 2 1;1 1 1]
B = zeros(4,4);
t=1;
indA = find(A==1);
indX = find(X==2);
all = find(X>0);
[iall jall] = ind2sub(size(X),all);
[ia ja] = ind2sub(size(A),indA)
[ix jx] = ind2sub(size(X),indX)
iv = ia-ix
jv = ja-jx
for t=1:numel(iv),
ib = iall+iv(t);
jb = jall+jv(t);
ibjb = [ib(:), jb(:)]
c1 = (ibjb(:,1)>4)|(ibjb(:,1)<1); c2 = (ibjb(:,2)>4)|(ibjb(:,1)<1);
ibjb((c1|c2),:)=[]
isel = ibjb(:,1)-iv(t)
jsel = ibjb(:,2)-jv(t)
B(ibjb(:,1), ibjb(:,2)) = B(ibjb(:,1), ibjb(:,2))+ X(isel, jsel)
t=t+1;
end
Is there a more efficient/faster way (minimizing the loops) to code this function?
What you want is a (2D) convolution. So use conv2:
B = conv2(A, X, 'same');

How to calculate the centroid of a matrix?

I have the following 5x5 Matrix A:
1 0 0 0 0
1 1 1 0 0
1 0 1 0 1
0 0 1 1 1
0 0 0 0 1
I am trying to find the centroid in MATLAB so I can find the scatter matrix with:
Scatter = A*Centroid*A'
If you by centroid mean the "center of mass" for the matrix, you need to account for the placement each '1' has in your matrix. I have done this below by using the meshgrid function:
M =[ 1 0 0 0 0;
1 1 1 0 0;
1 0 1 0 1;
0 0 1 1 1;
0 0 0 0 1];
[rows cols] = size(M);
y = 1:rows;
x = 1:cols;
[X Y] = meshgrid(x,y);
cY = mean(Y(M==1))
cX = mean(X(M==1))
Produces cX=3 and cY=3;
For
M = [1 0 0;
0 0 0;
0 0 1];
the result is cX=2;cY=2, as expected.
The centroid is simply the mean average computed separately for each dimension.
To find the centroid of each of the rows of your matrix A, you can call the mean function:
centroid = mean(A);
The above call to mean operates on rows by default. If you want to get the centroid of the columns of A, then you need to call mean as follows:
centroid = mean(A, 2);