Closing the figure window causes a new figure window to open - matlab

This is a analog clock. It runs perfectly. But once I close the clock, another figure opens up, and only the clock hands show. This makes it difficult to stop the program. How can I stop the program?
x=0;y=0;r=10;
hold on;
theta = 0:pi/60:2*pi;
xc = r * cos(theta);
yc = r * sin(theta);
h = plot(xc,yc,'r','linewidth',4);
axis off
r=9; i=1;
set(gca,'FontWeight','bold');
for theta = pi/6: pi/6: 2*pi
y1 = r * cos(theta);
x1 = r * sin(theta);
plot([x1/9*8 x1/9*7],[y1/9*8 y1/9*7],'color',[0 0 1])
text(x1/9*9.5,y1/9*9.5,num2str(i),'color',[0 0 1]);
i=i+1;
end
for theta=pi/30 : pi/30 : 2*pi
y1 = 10 * cos(theta);
x1 = 10 * sin(theta);
plot([x1/9*8 x1/9*7],[y1/9*8 y1/9*7],'color',[0 0 0])
end
while(1)
tic
c = clock;
c = c(1,4:6);
minute =c(1,2); sec=c(1,3);
if (c(1,1)>12)
hr = c(1,1)-12;
else
hr = c(1,1);
end
min1 = ceil(minute/12);
theta = (hr*pi)/6 + (min1*pi)/30;
f=figure(1); hold on;
y1 = 3 * cos(theta); Yhr = [0 y1];
x1 = 3 * sin(theta); Xhr = [0 x1];
hrhnd=plot(Xhr,Yhr);hold on;
theta1 = (minute*pi)/30;
y2 = 4.5 * cos(theta1); Ymin = [0 y2];
x2 = 4.5 * sin(theta1); Xmin = [0 x2];
minhnd=plot(Xmin,Ymin);
theta2 = (sec*pi)/30;
y3 = 5 * cos(theta2); Ysec = [0 y3];
x3 = 5 * sin(theta2); Xsec = [0 x3];
sechnd=plot(Xsec,Ysec);
z=toc;
pause(1-z);
delete(sechnd);
delete(minhnd);
delete(hrhnd);
end

The simplest way to stop the script when you close the window is to have the script test inside its loop if the window still exists.
We start the script by creating a figure window and recording its handle:
fig = figure;
Next, in the loop, we check to see if the window still exists using ishandle:
while(ishandle(fig))
...
end
The full program:
x=0;y=0;r=10;
fig = figure; %!!! NEW LINE
hold on;
theta = 0:pi/60:2*pi;
xc = r * cos(theta);
yc = r * sin(theta);
h = plot(xc,yc,'r','linewidth',4);
axis off
r=9; i=1;
set(gca,'FontWeight','bold');
for theta = pi/6: pi/6: 2*pi
y1 = r * cos(theta);
x1 = r * sin(theta);
plot([x1/9*8 x1/9*7],[y1/9*8 y1/9*7],'color',[0 0 1])
text(x1/9*9.5,y1/9*9.5,num2str(i),'color',[0 0 1]);
i=i+1;
end
for theta=pi/30 : pi/30 : 2*pi
y1 = 10 * cos(theta);
x1 = 10 * sin(theta);
plot([x1/9*8 x1/9*7],[y1/9*8 y1/9*7],'color',[0 0 0])
end
while(ishandle(fig)) %!!! UPDATED LINE
tic
c = clock;
c = c(1,4:6);
minute =c(1,2); sec=c(1,3);
if (c(1,1)>12)
hr = c(1,1)-12;
else
hr = c(1,1);
end
min1 = ceil(minute/12);
theta = (hr*pi)/6 + (min1*pi)/30;
f=figure(1); hold on;
y1 = 3 * cos(theta); Yhr = [0 y1];
x1 = 3 * sin(theta); Xhr = [0 x1];
hrhnd=plot(Xhr,Yhr);hold on;
theta1 = (minute*pi)/30;
y2 = 4.5 * cos(theta1); Ymin = [0 y2];
x2 = 4.5 * sin(theta1); Xmin = [0 x2];
minhnd=plot(Xmin,Ymin);
theta2 = (sec*pi)/30;
y3 = 5 * cos(theta2); Ysec = [0 y3];
x3 = 5 * sin(theta2); Xsec = [0 x3];
sechnd=plot(Xsec,Ysec);
z=toc;
pause(1-z);
delete(sechnd);
delete(minhnd);
delete(hrhnd);
end
You could improve your program by not deleting and re-drawing the hands, but updating their position. You'd do hrhnd=plot(Xhr,Yhr); before the loop, to draw the hand in its initial position, and then set(hrhnd,'XData',Xhr,'YData', Yhr) to update its position.
You could also do axis equal after drawing the clock face, to ensure it is round.
Note that you only need to give hold on once at the top, it is not needed after every plot command.

Related

Using the if Statement in a for Loop in 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.

Make the heart bounce in and out

I was able to make a heart in matlab as:
n=100;
x=linspace(-3,3,n);
y=linspace(-3,3,n);
z=linspace(-3,3,n);
[X,Y,Z]=ndgrid(x,y,z);
F=((-(X.^2) .* (Z.^3) -(9/80).*(Y.^2).*(Z.^3)) + ((X.^2) + (9/4).* (Y.^2) + (Z.^2)-1).^3);
isosurface(F,0)
lighting phong
axis equal
Would it be possible to make it bounce in and out? What approach might be taken?
try this
step = 0.05;
x = -1.5 : step : 1.5;
y = -1 : step : 1;
z = -1.5 : step : 1.5;
[X,Y,Z] = meshgrid(x, y, z);
f = (X.^2 + 9/4 .* Y.^2 + Z.^2 - 1).^3 - X.^2 .* Z.^3 - 9/80 .* Y.^2 .* Z.^3;
isosurface(X,Y,Z,f,0)
axis tight
axis equal
colormap flag
axis manual
ax = gca;
k=1.25;
ax.XLim = ax.XLim*k;
ax.YLim = ax.YLim*k;
ax.ZLim = ax.ZLim*k;
tempLims.XLim = ax.XLim;
tempLims.YLim = ax.YLim;
tempLims.ZLim = ax.ZLim;
t=0;
heartData = sin((1:250)/100*2*pi)/6.*hamming(250)';
heartData(251:400) = 0;
while 1
t=t+1;
t=mod(t, length(heartData))+1;
k = 1 + heartData(t);
ax.XLim = tempLims.XLim * k;
ax.YLim = tempLims.YLim * k;
ax.ZLim = tempLims.XLim * k;
pause(0.01);
end

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.

Solving Boundary Value with bvp4c Matlab

i'm trying to solve a boundary value problem of an system q' = f(q(t), a(t)) with an input a using bvp4c in Matlab. Where q = [q1, q2, q1_dot, q2_dot]'
My Matlab Code does not work properly. Does anyone know how to solve this?
img: System Equation of the One Pendulum
a is a input function.
the initial state: q1(0) = pi, q2(0) = 0, q1_dot(0) = 0, q2_dot(0) = 0.
the end state: q1(te) = 0, q2(te) = 0, q1_dot(te) = 0, q2_dot(te) = 0.
input initial state: a(0) = 0, and the end state: a(te) = 0.
i've in total 10 boundaries. one_pendulum_bc can take only 5 and not more and fewer.
function one_pendulum
options = []; % place holder
solinit = bvpinit(linspace(0,1,1000),[pi, 0, 0, 0],0);
sol = bvp4c(#one_pendulum_ode,#one_pendulum_bc,solinit,options);
t = sol.x;
plot(t, sol.y(1,:))
figure(2)
plot(t, sol.y(2,:))
figure(3)
plot(t, sol.y(3,:))
figure(4)
plot(t, sol.y(4,:))
% --------------------------------------------------------------------------
function dydx = one_pendulum_ode(x,y,a)
% Parameter of the One-Pendulum
m1 = 0.3583; % weight of the pendulum [kg]
J1 = 0.03799; % moment of inertia [Nms^2]
a1 = 0.43; % center of gravity [m]
d1 = 0.006588; % coefficient of friction [Nms]
g = 9.81; % gravity [m/s^2]
dydx = [ y(3)
y(4)
(a*a1*m1*cos(y(1)) + a1*g*m1*sin(y(1)) - d1*y(3))/(J1 + a1^2 *m1)
a ];
% --------------------------------------------------------------------------
function res = one_pendulum_bc(ya,yb,a)
res = [ya(1) - pi
ya(2)
ya(4)
yb(1)
yb(3)];
img: The result should look like this
i just solved it with a model function.
function one_pendulum
options = bvpset('stats', 'on', 'NMax', 3000);
T = 2.5;
sol0 = [
-5.3649
119.5379
-187.3080
91.6670];
solinit = bvpinit(linspace(0, T, T/0.002),[pi, 0, 0, 0], sol0);
sol = bvp4c(#one_pendulum_ode,#one_pendulum_bc,solinit,options, T);
t = sol.x;
ax1 = subplot(2,2,1);
ax2 = subplot(2,2,2);
ax3 = subplot(2,2,3);
ax4 = subplot(2,2,4);
plot(ax1, t, sol.y(1,:))
title(ax1, 'phi');
plot(ax2, t, sol.y(2,:))
title(ax2, 'x');
plot(ax3, t, sol.y(3,:))
title(ax3, 'phi_d');
plot(ax4, t, sol.y(4,:))
title(ax4, 'x_d');
length = size(t)
k = sol.parameters
for i=1:length(2)
k5 = -(k(1) * sin(pi) + k(2) * sin(2*pi) + k(3) * sin(3*pi) + k(4) * sin(4*pi))/sin(5*pi);
x = t(i);
acc(i)=k(1) * sin(pi*x/T) + k(2) * sin(2*pi*x/T) + k(3) * sin(3*pi*x/T) + k(4) * sin(4*pi*x/T) + k5* sin(5*pi*x/T);
end
figure(2)
plot(t,acc)
% --------------------------------------------------------------------------
function dydx = one_pendulum_ode(x,y,k,T)
% Parameter of the One-Pendulum
m1 = 0.3583; % weight of the pendulum [kg]
J1 = 0.03799; % moment of inertia [Nms^2]
a1 = 0.43; % center of gravity [m]
d1 = 0.006588; % coefficient of friction [Nms]
g = 9.81; % gravity [m/s^2]
% Ansatzfunktion
k5 = -(k(1) * sin(pi) + k(2) * sin(2*pi) + k(3) * sin(3*pi) + k(4) * sin(4*pi))/sin(5*pi);
a = k(1) * sin(pi*x/T) + k(2) * sin(2*pi*x/T) + k(3) * sin(3*pi*x/T) + k(4) * sin(4*pi*x/T) + k5* sin(5*pi*x/T);
dydx = [ y(3)
y(4)
(a*a1*m1*cos(y(1)) + a1*g*m1*sin(y(1)) - d1*y(3))/(J1 + a1^2 *m1)
a ];
% --------------------------------------------------------------------------
function res = one_pendulum_bc(ya,yb,k,T)
res = [ya(1) - pi
ya(2)
ya(3)
ya(4)
yb(1)
yb(2)
yb(3)
yb(4)];

Rotating a gaussian function - matlab

Good day,
I have code that stretches and rotates a gaussian 2d pdf as such:
mu = [0 0];
Sigma = [1 0; 0 1];
Scale = [3 0; 0 1];
Theta = 10;
Rotate = [cosd(Theta) -sind(Theta); sind(Theta) cosd(Theta)];
Sigma = (Sigma*Scale)*Rotate
x1 = -100:1:100; x2 = -100:1:100;
[X1,X2] = meshgrid(x1,x2);
F = mvnpdf([X1(:) X2(:)],mu,Sigma);
F = reshape(F,length(x2),length(x1));
imshow(F*255)
Unfortunately, when I change Theta to a value other than 0, it says
SIGMA must be a square, symmetric, positive definite matrix. Can I know what's going on
If you consult the article on Wikipedia about the general elliptical version of the Gaussian 2D PDF, it doesn't look like you're rotating it properly. In general, the equation is:
Source: Wikipedia
where:
Usually, A = 1 and we'll adopt that here. The angle theta will rotate the PDF counter-clockwise, and so we can use this raw form of the equation over mvnpdf. Using your definitions and constants, it would become this:
x1 = -100:1:100; x2 = -100:1:100;
[X1,X2] = meshgrid(X1, X2);
sigma1 = 1;
sigma2 = 1;
scale1 = 3;
scale2 = 1;
sigma1 = scale1*sigma1;
sigma2 = scale2*sigma2;
Theta = 10;
a = ((cosd(Theta)^2) / (2*sigma1^2)) + ((sind(Theta)^2) / (2*sigma2^2));
b = -((sind(2*Theta)) / (4*sigma1^2)) + ((sind(2*Theta)) / (4*sigma2^2));
c = ((sind(Theta)^2) / (2*sigma1^2)) + ((cosd(Theta)^2) / (2*sigma2^2));
mu = [0 0];
A = 1;
F = A*exp(-(a*(X1 - mu(1)).^2 + 2*b*(X1 - mu(1)).*(X2 - mu(2)) + c*(X2 - mu(2)).^2));
imshow(F*255);
I see that you are trying to rotate the variances in 2D... You have to hit your sigma matrix with your transform on both sides of it since the "sigma" matrix is essentially a tensor.
mu = [0 0];
Sigma = [1 0; 0 1];
Scale = [10 0;0 1];
Theta = pi/3;
m = makehgtform('zrotate',Theta);
m = m(1:2,1:2);
Sigma = m*(Sigma*Scale)*m.';
x1 = -100:1:100;
x2 = -100:1:100;
[X1,X2] = meshgrid(x1,x2);
F = mvnpdf([X1(:) X2(:)],mu,Sigma);
F = reshape(F,length(x2),length(x1));
imshow(F*255)