Make the heart bounce in and out - matlab

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

Related

Closing the figure window causes a new figure window to open

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.

system of equation Runge-Kutta 4th order for system of equation using matlab [duplicate]

This question already has answers here:
Solve a system of equations with Runge Kutta 4: Matlab
(2 answers)
Closed 4 years ago.
I need to do matlab code to solve the system of equation by using Runge-Kutta method 4th order but in every try i got problem and can't solve
the derivative is
(d^2 y)/dx^(2) +dy/dx-2y=0
, h=0.1 Y(0)=1 , dy/dx (0)=-2
{clear all, close all, clc
%{
____________________TASK:______________________
Solve the system of differential equations below
in the interval 0<x<1, with stepsize h = 0.1.
y= y1 y(0)=0
y3= 2y1-y2 y2(0)=-2
_______________________________________________
%}
h = 0.1;
x = 0:h:1
N = length(x);
y = zeros(N,1);
y3 = zeros(N,1);
g = #(x, y, y1, y2) y1;
f = #(x, y, y1, y2) 2*y1-y2;
y1(1) = 0;
y2(1) =-2;
for i = 1:(N-1)
k_1 = x(i)+y(i)
k_11=g(x(i),y,y(i))
k_2 = (x(i)+h/2)+(y(i)+0.5*h*k_1)
k_22=g((x(i)+0.5*h),y,(y(i)+0.5*h*k_11))
k_3 = (x(i)+h/2)+(y(i)+0.5*h*k_2)
k_33=g((X(i)+0.5*h),y,(y(i)+0.5*h*k_22));
k_4 = (x(i)+h)+(y(i)+h*k_33)
k_44=g((x(i)+h),y,(y(i)+k_33*h));
y3(i+1) = y(i) + (1/6)*(k_1+2*k_2+2*k_3+k_4)*h
y3(:,i)=y;
end
Answer_Matrix = [x' y3 ];}
You used functions, that's not really necessary, but it might be easier that way to see the formula more clearly. In your functions however, you list arguments that used present in the function. That's not needed, and creates unwanted overhead.
In your initial conditions you should use y and y3, since that are the ones you use in the loop. Also in the first condition you've made a typo.
In the loop you forget to call the function f, and to update the y vector.
Making these changes in your code results in the following:
h = 0.1;
x = 0:h:1;
N = length(x);
y = zeros(N,1);
y3 = zeros(N,1);
g = #(y2) y2;
f = #(y1, y2) 2*y1-y2;
y(1) = 1;
y3(1) = -2;
for i = 1:(N-1)
k_1 = f(y(i), y3(i));
k_11 = g(y3(i));
k_2 = f(y(i)+0.5*h*k_1, y3(i) +0.5*h*k_11);
k_22 = g((y3(i)+0.5*h*k_11));
k_3 = f(y(i)+0.5*h*k_2, y3(i) +0.5*h*k_22);
k_33 = g((y3(i)+0.5*h*k_22));
k_4 = f(y(i)+h*k_3, y3(i) +h*k_33);
k_44 = g((y3(i)+h*k_33));
y3(i+1) = y3(i) + (1/6)*(k_1+2*k_2+2*k_3+k_4)*h ;
y(i+1) = y(i) + (1/6)*(k_11+2*k_22+2*k_33+k_44)*h ;
end
Answer_Matrix = [x' y];
% solution of DE is exp(-2x) and is plotted as reference
plot(x,y,x,exp(-2*x))
As mentioned before, you can also solve this without the use of functions:
h = .1;
x = 0:h:1;
N = length(x);
% allocate memory
y = zeros(N,1);
z = zeros(N,1);
% starting values
y(1) = 1;
z(1) = -2;
for i=1:N-1
ky1 = z(i);
kz1 = -z(i) + 2*y(i);
ky2 = z(i) + h/2*kz1;
kz2 = -z(i) - h/2*kz1 + 2*y(i) + 2*h/2*ky1;
ky3 = z(i) + h/2*kz2;
kz3 = -z(i) - h/2*kz2 + 2*y(i) + 2*h/2*ky2;
ky4 = z(i) + h*kz3;
kz4 = -z(i) - h*kz3 + 2*y(i) + 2*h*ky3;
y(i+1) = y(i) + h/6*(ky1 + 2*ky2 + 2*ky3 + ky4);
z(i+1) = z(i) + h/6*(kz1 + 2*kz2 + 2*kz3 + kz4);
end
% exp(-2*x) is solution of DE and is plotted as reference
plot(x,y,x,exp(-2*x))

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 do I plot the output of a system with an impulse response in matlab?

I am very new to matlab and need to plot y1[n] = x[n] + y1[n − 1] where x[n] = [1,2,4] and an impulse response, h[n] = [1,1,1,1,1] and am not sure if I have went about it the right way
My code so far is
x = [1,2,4];
h = [1,1,1,1,1];
y = [];
for n=1:length(x)
if (n==1)
y(n) = x(n);
else
y(n) = (x(n)*h(n)) + (y(n-1)*h(n));
end
end
stem(y);
Please note that I cannot use the conv() function
I don't really know why it got so complicated,
x = [1,2,4];
h = [1,1,1,1,1];
y = [];
lh = length(h);
lx = length(x);
t = -lh - lx : lh + lx;
x(end + 1 : end + lh + 1) = 0;
h(end + 1 : end + lx + 1) = 0;
x = padarray(x,[0 max(t)],'pre');
h = padarray(h,[0 max(t)],'pre');
xinv = x(end:-1:1);
for n = 1 : length(t)
xinv = circshift(xinv,[0 1]);
y(n) = sum(xinv .* h);
end
y = circshift(y,[0 find(t == 0)]);
subplot(311)
stem(t,x);
xlim([-10 10])
subplot(312)
stem(t,h);
xlim([-10 10])
subplot(313)
stem(t,y);
xlim([-10 10])
It works fine but I believe it can be coded in a more simpler way.
Can you use fft?
lx = numel(x);
lh = numel(h);
m = max(lx, lh);
y = ifft(fft([h zeros(1,max(lx-lh,0)+m)]) .* fft([x zeros(1,max(lh-lx,0)+m)]));
y = y(1:lx+lh-1);

Color-pass filter by Hue

Why doesn't color filter below find green peppers?
The code:
function [ outhsv ] = ColorFilter( hsv, h, s )
%COLORFILTER Summary of this function goes here
% Detailed explanation goes here
if nargin < 2
h = [];
end
if nargin < 3
s = [];
end
if size(h,2)==1
h = padarray(h, [0 1], 1/100, 'post');
end
if size(s,2)==1
s = padarray(s, [0 1], 1/100, 'post');
end
if isempty(h)
v_of_h = ones(size(hsv,1), size(hsv,2));
else
v_of_h = WeightFunction( hsv(:,:,1), h(:,1), h(:,2));
end
if isempty(s)
v_of_s = ones(size(hsv,1), size(hsv,2));
else
v_of_s = WeightFunctionOnce( hsv(:,:,2), s(:,1), s(:,2));
end
outhsv = hsv;
outhsv(:,:,3) = hsv(:,:,3) .* v_of_h .* v_of_s;
function y = WeightFunction( x, mu, sigma )
%y = WeightFunctionOnce(x,mu,sigma) + WeightFunctionOnce(x-1,mu,sigma);
y = 1 - (1-WeightFunctionOnce(x,mu,sigma)) .* (1-WeightFunctionOnce(x-1,mu,sigma));
function y = WeightFunctionOnce( x, mu, sigma )
if nargin<2
mu=0;
elseif nargin<3
sigma=1./100.;
end
if any(size(mu) ~= size(sigma))
error('mu and sigma should be of the same size');
end
y = zeros([size(x) numel(mu)]);
for i=1:numel(mu)
y(:,:,i) = exp(-((x - mu(i)) .^ 2 ./ (2 .* sigma(i) .^ 2)));
end
%y = sum(y,3)/size(y,3);
y = 1-prod(1-y,3);
Display code:
hue = 120;
h = [hue/360 0.05];
s = [];
rgb1 = imread('huescale.png');
%rgb1 = imread('peppers.png');
hsv1 = rgb2hsv(rgb1);
hsv2 = ColorFilter(hsv1, h, s);
rgb2 = hsv2rgb(hsv2);
bitmask = hsv1(:,:,1)>(h(1)-h(2)) & hsv1(:,:,1)<(h(1)+h(2));
figure;
subplot(3,1,1); imshow(rgb1);
subplot(3,1,2); imshow(rgb2);
subplot(3,1,3); imshow(bitmask);
result on scale
(works)
result on peppers:
(does not)
Why?
If you looked closer at the H values, those green peppers are kind of yellowish, so you might want to widen the rule a bit.
I would suggest something in between 0.15 and 0.5. You can also combine with saturation channel, say only consider portions of images that are vibrant, i.e., we want to get rid of the onions. Try the following codes to get a preview.
hsv_dat = rgb2hsv(imread('peppers.png'));
imagesc(hsv_dat(:,:,1) > 0.15 & hsv_dat(:,:,1) < 0.5 & hsv_dat(:,:,2) > 0.3)
colormap(gray)
You should get