Using the if Statement in a for Loop in MATLAB - matlab

I am working on a project and my aim is to color and 20 randomly generated lines of all fixed length, then count all lines crossing y=0 and color them green else color them blue.
I have come up with the code below but it doesn't work well in the if statement.
Can someone please have at look? Thank you if you can help!
Question:
How do I correct the if statement to display all the lines and count those lines crossing y = 0?
clear
clc
L = 1.5;
a = -5;
b = 5;
GLines = 0:5:5;
m = 0;
for i = 1:20
X1 = rand(1,i)*(b-a)+a;
Y1 = rand(1,i)*(b-a)+a;
Angle = rand(1,i)*360;
X2 = L*cosd(Angle) + X1;
Y2 = L*sind(Angle) + X2;
if X1(i) < L/2* sind(Angle)
m = m + 1;
plot([X1(i); X2(i)],[Y1(i); Y2(i)], '-g');
else
plot([X1(i); X2(i)],[Y1(i); Y2(i)], '-b');
end
for j = 1:length(GLines)
axis square
ylim([-5 5]);
xlim([-5 5]);
y = yline(GLines(j));
end
end
disp(m)

If a line crosses zero, the sign of Y1 and Y2 will be opposite, so you can do the following:
clear; clc
L = 1.5;
a = -5;
b = 5;
GLines = 0:5:5;
m = 0;
figure;
hold all;
for i = 1:20
X1 = rand*(b-a)+a;
Y1 = rand*(b-a)+a;
Angle = rand*360;
X2 = L*cosd(Angle) + X1;
Y2 = L*sind(Angle) + Y1;
if Y1*Y2 < 0 % if line crosses zero
m = m + 1;
c = 'g'; % color = green
else
c = 'b'; % color = blue
end
plot([X1; X2],[Y1; Y2],'color',c);
end
axis equal
disp(m)
which gives the follwing plot
and correctly outputs m = 2.

Related

Why is the scatter Circle Color not resulting in a rainbow?

I am trying to follow this example from Matlab about coloring scatter points as a rainbow, while the x-position of the points is progressing towards the right side.
Here under "Vary Circle Color":
https://de.mathworks.com/help/matlab/ref/scatter.html
x = linspace(0,3*pi,200);
y = cos(x) + rand(1,200);
c = linspace(1,10,length(x));
scatter(x,y,[],c)
While c as a variable goes from 1 to 20 with 200 interpolations. I am trying to replicate this for my piece of code, but I keep getting random color and the x-axis isn't matching the rainbow distribution as this:
g = 6;
pt_x = [0, g, -g];
pt_y = [g, -g, -g];
sz = 10;
loop = 100;
% var(1, loop) = 0;
% c = linspace(-10,10,length(var));
% c = 1:loop;
c = -loop/2:1:loop/2 -1;
rand_x = randi([-g,g],1,1);
rand_y = randi([-g,g],1,1);
for i = 1:loop
r = randi([1,3],1,1);
x1 = (rand_x + pt_x(r)) / 2;
y1 = (rand_y + pt_y(r)) / 2;
seq_x(1, i) = x1;
seq_y(1, i) = y1;
rand_x = x1;
rand_y = y1;
end
scatter(seq_x, cos(seq_x),[],c, 'filled');
What am I missing here exactly? I would appreciate any help!
Expected to get a rainbow pattern
It resulted in a random pattern

Is there a possibility to have a quiver plot with vectors of same length?

I am using a quiver plot in MATLAB to simulate a velocity field. Now I would like the vectors produced by the quiver plot to be all the same length, so that they just indicate the vectors direction. The value of the velocity in each point should be illustrated by different colors then.
Is there a possibility to have quiver plotting vectors of same length?
That's my current code:
%defining parameters:
age = 900;
vis= 15;
turbulences = zeros(9,3);
a = 0.01;
spacing = 1000;
[x,y] = meshgrid(-100000:spacing:100000);%, 0:spacing:10000);
u = a;
v = 0;
n = 0;
for i = 1:4
turbulences(i,1) = -80000 + n;
turbulences(i,2) = 15000;
n = 15000 * i;
end
n = 0;
for i = 5:9
turbulences(i,1) = -15000 + n*5000;
turbulences(i,2) = 4000;
n = n+1;
end
for i = 1:4
turbulences(i,3) = -1000;
end
for i = 5:9
turbulences(i,3) = 800;
end
%compute velocities in x and y direction
for k = 1:9
xc = turbulences(k,1);
yc = turbulences(k,2);
r1 = ((x-xc).^2 + (y-yc).^2);
r2 = ((x-xc).^2 + (y+yc).^2);
u = u + turbulences(k,3)/2*pi * (((y-yc)./r1).*(1-exp(-(r1./(4*vis*age)))) - ((y+yc)./r2).*(1-exp(-(r2./(4*vis*age)))));
v = v - turbulences(k,3)/2*pi* (((x-xc)./r1).*(1-exp(-(r1./(4*vis*age)))) - ((x-xc)./r2).*(1-exp(-(r2./(4*vis*age)))));
end
quiver(x,y,u,v);
grid on;
Thank you for your help!
One way to do this would be to normalize each component of your vectors to +- 1 just to keep their direction.
un = u./abs(u); % normalized u
vn = v./abs(v); % normalized v
quiver(x, y, un, vn)

Plot equally spaced markers along a spiral

I want to move a red star marker along the spiral trajectory with an equal distance of 5 units between the red star points on its circumference like in the below image.
vertspacing = 10;
horzspacing = 10;
thetamax = 10*pi;
% Calculation of (x,y) - underlying archimedean spiral.
b = vertspacing/2/pi;
theta = 0:0.01:thetamax;
x = b*theta.*cos(theta)+50;
y = b*theta.*sin(theta)+50;
% Calculation of equidistant (xi,yi) points on spiral.
smax = 0.5*b*thetamax.*thetamax;
s = 0:horzspacing:smax;
thetai = sqrt(2*s/b);
xi = b*thetai.*cos(thetai);
yi = b*thetai.*sin(thetai);
plot(x,y,'b-');
hold on
I want to get a figure that looks like the following:
This is my code for the circle trajectory:
% Initialization steps.
format long g;
format compact;
fontSize = 20;
r1 = 50;
r2 = 35;
r3= 20;
xc = 50;
yc = 50;
% Since arclength = radius * (angle in radians),
% (angle in radians) = arclength / radius = 5 / radius.
deltaAngle1 = 5 / r1;
deltaAngle2 = 5 / r2;
deltaAngle3 = 5 / r3;
theta1 = 0 : deltaAngle1 : (2 * pi);
theta2 = 0 : deltaAngle2 : (2 * pi);
theta3 = 0 : deltaAngle3 : (2 * pi);
x1 = r1*cos(theta1) + xc;
y1 = r1*sin(theta1) + yc;
x2 = r2*cos(theta2) + xc;
y2 = r2*sin(theta2) + yc;
x3 = r3*cos(theta3) + xc;
y3 = r3*sin(theta3) + yc;
plot(x1,y1,'color',[1 0.5 0])
hold on
plot(x2,y2,'color',[1 0.5 0])
hold on
plot(x3,y3,'color',[1 0.5 0])
hold on
% Connecting Line:
plot([70 100], [50 50],'color',[1 0.5 0])
% Set up figure properties:
% Enlarge figure to full screen.
set(gcf, 'Units', 'Normalized', 'OuterPosition', [0, 0, 1, 1]);
drawnow;
axis square;
for i = 1 : length(theta1)
plot(x1(i),y1(i),'r*')
pause(0.1)
end
for i = 1 : length(theta2)
plot(x2(i),y2(i),'r*')
pause(0.1)
end
for i = 1 : length(theta3)
plot(x3(i),y3(i),'r*')
pause(0.1)
end
I can't think of a way to compute distance along a spiral, so I'm approximating it with circles, in hopes that it will still be useful.
My solution relies on the InterX function from FEX, to find the intersection of circles with the spiral. I am providing an animation so it is easier to understand.
The code (tested on R2017a):
function [x,y,xi,yi] = q44916610(doPlot)
%% Input handling:
if nargin < 1 || isempty(doPlot)
doPlot = false;
end
%% Initialization:
origin = [50,50];
vertspacing = 10;
thetamax = 5*(2*pi);
%% Calculation of (x,y) - underlying archimedean spiral.
b = vertspacing/(2*pi);
theta = 0:0.01:thetamax;
x = b*theta.*cos(theta) + origin(1);
y = b*theta.*sin(theta) + origin(2);
%% Calculation of equidistant (xi,yi) points on spiral.
DST = 5; cRes = 360;
numPts = ceil(vertspacing*thetamax); % Preallocation
[xi,yi] = deal(NaN(numPts,1));
if doPlot && isHG2() % Plots are only enabled if the MATLAB version is new enough.
figure(); plot(x,y,'b-'); hold on; axis equal; grid on; grid minor;
hAx = gca; hAx.XLim = [-5 105]; hAx.YLim = [-5 105];
hP = plot(xi,yi,'r*');
else
hP = struct('XData',xi,'YData',yi);
end
hP.XData(1) = origin(1); hP.YData(1) = origin(2);
for ind = 2:numPts
P = InterX([x;y], makeCircle([hP.XData(ind-1),hP.YData(ind-1)],DST/2,cRes));
[~,I] = max(abs(P(1,:)-origin(1)+1i*(P(2,:)-origin(2))));
if doPlot, pause(0.1); end
hP.XData(ind) = P(1,I); hP.YData(ind) = P(2,I);
if doPlot, pause(0.1); delete(hAx.Children(1)); end
end
xi = hP.XData(~isnan(hP.XData)); yi = hP.YData(~isnan(hP.YData));
%% Nested function(s):
function [XY] = makeCircle(cnt, R, nPts)
P = (cnt(1)+1i*cnt(2))+R*exp(linspace(0,1,nPts)*pi*2i);
if doPlot, plot(P,'Color',lines(1)); end
XY = [real(P); imag(P)];
end
end
%% Local function(s):
function tf = isHG2()
try
tf = ~verLessThan('MATLAB', '8.4');
catch
tf = false;
end
end
function P = InterX(L1,varargin)
% DOCUMENTATION REMOVED. For a full version go to:
% https://www.mathworks.com/matlabcentral/fileexchange/22441-curve-intersections
narginchk(1,2);
if nargin == 1
L2 = L1; hF = #lt; %...Avoid the inclusion of common points
else
L2 = varargin{1}; hF = #le;
end
%...Preliminary stuff
x1 = L1(1,:)'; x2 = L2(1,:);
y1 = L1(2,:)'; y2 = L2(2,:);
dx1 = diff(x1); dy1 = diff(y1);
dx2 = diff(x2); dy2 = diff(y2);
%...Determine 'signed distances'
S1 = dx1.*y1(1:end-1) - dy1.*x1(1:end-1);
S2 = dx2.*y2(1:end-1) - dy2.*x2(1:end-1);
C1 = feval(hF,D(bsxfun(#times,dx1,y2)-bsxfun(#times,dy1,x2),S1),0);
C2 = feval(hF,D((bsxfun(#times,y1,dx2)-bsxfun(#times,x1,dy2))',S2'),0)';
%...Obtain the segments where an intersection is expected
[i,j] = find(C1 & C2);
if isempty(i), P = zeros(2,0); return; end
%...Transpose and prepare for output
i=i'; dx2=dx2'; dy2=dy2'; S2 = S2';
L = dy2(j).*dx1(i) - dy1(i).*dx2(j);
i = i(L~=0); j=j(L~=0); L=L(L~=0); %...Avoid divisions by 0
%...Solve system of eqs to get the common points
P = unique([dx2(j).*S1(i) - dx1(i).*S2(j), ...
dy2(j).*S1(i) - dy1(i).*S2(j)]./[L L],'rows')';
function u = D(x,y)
u = bsxfun(#minus,x(:,1:end-1),y).*bsxfun(#minus,x(:,2:end),y);
end
end
Result:
Note that in the animation above, the diameter of the circle (and hence the distance between the red points) is 10 and not 5.

How to find Orientation of axis of contour in matlab?

I want to find Orientation, MajorAxisLengthand MinorAxisLength of contour which is plotted with below code.
clear
[x1 , x2] = meshgrid(linspace(-10,10,100),linspace(-10,10,100));
mu = [1,3];
sigm = [2,0;0,2];
xx_size = length(mu);
tem_matrix = ones(size(x1));
x_mesh= cell(1,xx_size);
for i = 1 : xx_size
x_mesh{i} = tem_matrix * mu(i);
end
x_mesh= {x1,x2};
temp_mesh = [];
for i = 1 : xx_size
temp_mesh = [temp_mesh x_mesh{i}(:)];
end
Z = mvnpdf(temp_mesh,mu,sigm);
z_plat = reshape(Z,size(x1));
figure;contour(x1, x2, z_plat,3, 'LineWidth', 2,'color','m');
% regionprops(z_plat,'Centroid','Orientation','MajorAxisLength','MinorAxisLength');
In my opinion, I may have to use regionprops command but I don't know how to do this. I want to find direction of axis of contour and plot something like this
How can I do this task? Thanks very much for your help
Rather than trying to process the graphical output of contour, I would instead recommend using contourc to compute the ContourMatrix and then use the x/y points to estimate the major and minor axes lengths as well as the orientation (for this I used this file exchange submission)
That would look something like the following. Note that I have modified the inputs to contourc as the first two inputs should be the vector form and not the output of meshgrid.
% Compute the three contours for your data
contourmatrix = contourc(linspace(-10,10,100), linspace(-10,10,100), z_plat, 3);
% Create a "pointer" to keep track of where we are in the output
start = 1;
count = 1;
% Now loop through each contour
while start < size(contourmatrix, 2)
value = contourmatrix(1, start);
nPoints = contourmatrix(2, start);
contour_points = contourmatrix(:, start + (1:nPoints));
% Now fit an ellipse using the file exchange
ellipsedata(count) = fit_ellipse(contour_points(1,:), contour_points(2,:));
% Increment the start pointer
start = start + nPoints + 1;
count = count + 1;
end
orientations = [ellipsedata.phi];
% 0 0 0
major_length = [ellipsedata.long_axis];
% 4.7175 3.3380 2.1539
minor_length = [ellipsedata.short_axis];
% 4.7172 3.3378 2.1532
As you can see, the contours are actually basically circles and therefore the orientation is zero and the major and minor axis lengths are almost equal. The reason that they look like ellipses in your post is because your x and y axes are scaled differently. To fix this, you can call axis equal
figure;contour(x1, x2, z_plat,3, 'LineWidth', 2,'color','m');
axis equal
Thank you #Suever. It help me to do my idea.
I add some line to code:
clear
[X1 , X2] = meshgrid(linspace(-10,10,100),linspace(-10,10,100));
mu = [-1,0];
a = [3,2;1,4];
a = a * a';
sigm = a;
xx_size = length(mu);
tem_matrix = ones(size(X1));
x_mesh= cell(1,xx_size);
for i = 1 : xx_size
x_mesh{i} = tem_matrix * mu(i);
end
x_mesh= {X1,X2};
temp_mesh = [];
for i = 1 : xx_size
temp_mesh = [temp_mesh x_mesh{i}(:)];
end
Z = mvnpdf(temp_mesh,mu,sigm);
z_plat = reshape(Z,size(X1));
figure;contour(X1, X2, z_plat,3, 'LineWidth', 2,'color','m');
hold on;
% Compute the three contours for your data
contourmatrix = contourc(linspace(-10,10,100), linspace(-10,10,100), z_plat, 3);
% Create a "pointer" to keep track of where we are in the output
start = 1;
count = 1;
% Now loop through each contour
while start < size(contourmatrix, 2)
value = contourmatrix(1, start);
nPoints = contourmatrix(2, start);
contour_points = contourmatrix(:, start + (1:nPoints));
% Now fit an ellipse using the file exchange
ellipsedata(count) = fit_ellipse(contour_points(1,:), contour_points(2,:));
% Increment the start pointer
start = start + nPoints + 1;
count = count + 1;
end
orientations = [ellipsedata.phi];
major_length = [ellipsedata.long_axis];
minor_length = [ellipsedata.short_axis];
tet = orientations(1);
x1 = mu(1);
y1 = mu(2);
a = sin(tet) * sqrt(major_length(1));
b = cos(tet) * sqrt(major_length(1));
x2 = x1 + a;
y2 = y1 + b;
line([x1, x2], [y1, y2],'linewidth',2);
tet = ( pi/2 + orientations(1) );
a = sin(tet) * sqrt(minor_length(1));
b = cos(tet) * sqrt(minor_length(1));
x2 = x1 + a;
y2 = y1 + b;
line([x1, x2], [y1, y2],'linewidth',2);

Finding correct index value for matrix in Matlab using meshgrid

I'm trying to build make a code where an equation is not calculated for some certain values. I have a meshgrid with several values for x and y and I want to include a for loop that will calculate some values for most of the points in the meshgrid but I'm trying to include in that loop a condition that if the points have a specified index, the value will not be calculated. In my second group of for/if loops, I want to say that for all values of i and k (row and column), the value for z and phi are calculated with the exception of the specified i and k values (in the if loop). What I'm doing at the moment is not working...
The error I'm getting is:
The expression to the left of the equals sign is not a valid target for an assignment.
Here is my code at the moment. I'd really appreciate any advice on this! Thanks in advance
U_i = 20;
a = 4;
c = -a*5;
b = a*10;
d = -20;
e = 20;
n = a*10;
[x,y] = meshgrid([c:(b-c)/n:b],[d:(e-d)/n:e]');
for i = 1:length(x)
for k = 1:length(x)
% Zeroing values where cylinder is
if sqrt(x(i,k).^2 + y(i,k).^2) < a
x(i,k) = 0;
y(i,k) = 0;
end
end
end
r = sqrt(x.^2 + y.^2);
theta = atan2(y,x);
z = zeros(length(x));
phi = zeros(length(x));
for i = 1:length(x)
for k = 1:length(x)
if (i > 16 && i < 24 && k > 16 && k <= length(x))
z = 0;
phi = 0;
else
z = U_i.*r.*(1-a^2./r.^2).*sin(theta); % Stream function
phi = U_i*r.*(1+a^2./r.^2).*cos(theta); % Velocity potential
end
end
end
The original code in the question can be rewritten as seen below. Pay attention in the line with ind(17:24,:) since your edit now excludes 24 and you original question included 24.
U_i = 20;
a = 4;
c = -a*5;
b = a*10;
d = -20;
e = 20;
n = a*10;
[x,y] = meshgrid([c:(b-c)/n:b],[d:(e-d)/n:e]');
ind = find(sqrt(x.^2 + y.^2) < a);
x(ind) = 0;
y(ind) = 0;
r = sqrt(x.^2 + y.^2);
theta = atan2(y,x);
ind = true(size(x));
ind(17:24,17:length(x)) = false;
z = zeros(size(x));
phi = zeros(size(x));
z(ind) = U_i.*r(ind).*(1-a^2./r(ind).^2).*sin(theta(ind)); % Stream function
phi(ind) = U_i.*r(ind).*(1+a^2./r(ind).^2).*cos(theta(ind)); % Velocity potential