delete a line in a for loop with MATLAB - matlab

i'm struggling with this matter probably
i'm just starting with Matlab.this is my code,i
wanna rotate a two links arm,using rotation matrix:
clear all
close all
clc
myaxes = axes('Xlim',[-1 1 ],'Ylim',[-1 1],'Zlim',[-1 1]);
view(3);
grid on;
axis equal;
hold on
xlabel('X')
ylabel('y')
zlabel('Z')
P_0 = [0; 0; 0] ;
P_1 = [-0.5;0; 0] ;
P_2 = [-1; 0; 0] ;
alfa_1 = 0:1:30 ;
alfa_2 =(0:0.5:15) ;
for i = 1:length(alfa_1)
M3(:,:,i) = [cosd(alfa_1(i)) -sind(alfa_1(i)) 0
sind(alfa_1(i)) cosd(alfa_1(i)) 0
0 0 1] ;
P_1(:,i,i) = M3(:,:,i)*[-0.5;0; 0] ;
P_2(:,i,i) = M3(:,:,i)*[-1;0; 0];
figure(1)
line([0 P_1(1,i,i)],[0 P_1(2,i,i)],[0 P_1(3,i,i)]);
scatter(P_1(1,i,i),P_1(2,i,i));
hold on
M3_1(:,:,i) = [cosd(alfa_2(i)) -sind(alfa_2(i)) 0
sind(alfa_2(i)) cosd(alfa_2(i)) 0
0 0 1] ;
P_2_2(:,i,i) = M3_1(:,:,i)*P_2(:,i,i);
line([P_1(1,i,i) P_2_2(1,i,i)],[P_1(2,i,i) P_2_2(2,i,i)],[P_1(3,i,i) P_2_2(3,i,i)],'color','r');
scatter(P_2_2(1,i,i), P_2_2(2,i,i))
hold on
end
should i use delete function to obtain an animation without plotting
all the lines but only the current line?!?.
thanks in advance for your help and support.

You can use the drawnow function in MATLAB for this purpose. This function can be used inside a for loop to force a plot to be rendered every iteration, instead of being stored in a buffer until after the loop.
Update figure window and execute pending callbacks
An example: for a simpler code consider a object moves on circle
t = 0:0.05:2*pi;
x = cos(t);
y = sin(t);
for k=1:length(t)
plot(x(k),y(k),'ko')
axis([-1.2 1.2 -1.2 1.2])
axis square
drawnow
end
Please note the axis function in this method. If the axis lines are deleted from the code then, in every iteration, the axis limits will change and the animation is not smooth.
What about your code:
clear all
close all
clc
view(3);
xlabel('X');
ylabel('y');
zlabel('Z');
P_0 = [0; 0; 0] ;
P_1 = [-0.5;0; 0] ;
P_2 = [-1; 0; 0] ;
alfa_1 = 0:1:30 ;
alfa_2 = (0:0.5:15) ;
for i = 1:length(alfa_1)
% Calculate new values for plotting
M3(:,:,i) = [cosd(alfa_1(i)), -sind(alfa_1(i)), 0
sind(alfa_1(i)), cosd(alfa_1(i)), 0
0 , 0 , 1] ;
P_1(:,i,i) = M3(:,:,i)*[-0.5; 0; 0] ;
P_2(:,i,i) = M3(:,:,i)*[-1; 0; 0] ;
% Clear figure 1 and hold for all plots
figure(1)
clf
% Hold only needs to be applied around plots on same axes
hold on
line([0 P_1(1,i,i)],[0 P_1(2,i,i)],[0 P_1(3,i,i)]);
scatter(P_1(1,i,i),P_1(2,i,i));
% Recalculate plotting values
M3_1(:,:,i) = [cosd(alfa_2(i)), -sind(alfa_2(i)), 0
sind(alfa_2(i)), cosd(alfa_2(i)), 0
0 , 0 , 1] ;
P_2_2(:,i,i) = M3_1(:,:,i)*P_2(:,i,i);
line([P_1(1,i,i) P_2_2(1,i,i)], [P_1(2,i,i) P_2_2(2,i,i)], [P_1(3,i,i) P_2_2(3,i,i)], 'color', 'r');
scatter(P_2_2(1,i,i), P_2_2(2,i,i))
% Set axis limits for consistency in all plots, show grid
axis([-2 2 -2 2])
grid on
% Hold off is good practice to avoid later accidental plotting on same axes
hold off
% Draw from the buffer
drawnow
end
you can save(if you want) this animation with getFrame function and play it with movie function
and another function may helps you is comet.

Related

Creating surface map in Matlab with 2-3 user defined break point colorbar

I'm trying to create a code in Matlab that will produce a surface map that has a colorbar defined at 2 or 3 different break points, for example below 0.8 it will be white, from 0.8-1.2 it will be green, and greater than 1.2 will be blue (or 0.6, 0.8, 1 for 3 breakpoint). I have a code that will run with one defined breakpoint but am having troubles figuring out how to run it for multiple breakpoints. They need to be a defined singular color without a gradient transition in the colorbar. Any tips on what I can do to define the 2-3 breakpoint colorbar at user defined breaks?
%% Two Toned Map
% define colormap and breakpoint
cmap = [0 0 1 ; 1 1 1; 1 0 1];
breakpoint = [0.7 ; 1.2]; %CHANGE VALUE
%create a color matrix with only 2 values:
% where Profile < breakpoint => ColorData=0
% where Profile > breakpoint => ColorData=1
ColorData= zeros(size(Profile)) ;
ColorData(Profile>=breakpoint(2)) = 2 ;
ColorData(Profile<=breakpoint(1)) = 1 ;
%Plot the surface, specifying the color matrix we want to have applied
hs = surf( xa, ya, Profile, ColorData, 'EdgeColor','none' ) ;
colormap(cmap) ;
hb = colorbar ;
set (gca, 'xdir', 'reverse')
set (gca, 'ydir', 'reverse')
set (gca, 'DataAspectRatio',[1 1 1])
xlim([0 80+deltax])
ylim([0 100+deltay])
%Now adjust colorbar ticks and labels
cticks = [0.25 0.5 0.75] ; % positions of the ticks we keep
% build labels
bpstr = num2str(breakpoint) ;
cticklabels = {['<' bpstr] ; bpstr ; ['>' bpstr]}
% apply
hb.Ticks = cticks ;
hb.TickLabels = cticklabels ;
title('Sheared 4mm') %CHANGE VALUE
You need to modify the label-constructing code to handle more than one breakpoint.
%Now adjust colorbar ticks and labels
cticks = (1:numel(breakpoint))*(numel(breakpoint)/(numel(breakpoint)+1));
cticklabels = breakpoint;
% apply
hb.Ticks = cticks ;
hb.TickLabels = cticklabels ;

How to make animation in MATLAB which the curve is moving, not axes is moving?

I want to plot y=omega*x^2, which omega is -3 into 3 with step size 0.25, x from -4 into 4 with step size 0.001. But this code give me the curve is cannot moving and axes is moving. I want the curve is moving, like this.
x=-4:0.001:4;
for omega=-3:0.25:3
for i=1:length(x)
y(i)=omega*x(i)^2;
end
plot(x,y);
pause(0.1);
end
How to do that?
As another answer has indicated, you need to set the axis limits.
(Also note that there is no reason to calculate y using a loop.)
But instead of using plot every time through the loop it's more efficient to create the line only once, and then replace the x and y data of the line each time through the loop.
x=-4:0.001:4;
all_omega=-3:0.25:3;
for idx = 1:numel(all_omega)
omega = all_omega(idx);
y=omega*(x.^2);
if idx == 1
% create line
hl = plot(x,y);
axis([-4,4,-40,40]);
box on
grid on
else
% replace line data
set(hl,'XData',x,'YData',y);
end
title(sprintf('\\Omega = %.2f',omega));
pause(0.1);
end
Or you might want to use animatedline,
x=-4:0.001:4;
all_omega=-3:0.25:3;
for idx = 1:numel(all_omega)
omega = all_omega(idx);
y=omega*(x.^2);
if idx == 1
% create animated line
am = animatedline(x,y);
axis([-4,4,-40,40]);
box on
grid on
else
% replace the line
clearpoints(am)
addpoints(am,x,y);
end
title(sprintf('\\Omega = %.2f',omega));
pause(0.1);
end
A quick method is setting the x- and y-axes limits in the loop after each plot, using the axis([xmin, xmax, ymin, ymax]) command. This method isn't foolproof, in the case that the script gets help up after plotting but before setting the axes limits, but in most cases it should work.
figure(1)
x=-4:0.001:4;
for omega=-3:0.25:3
for i=1:length(x)
y(i)=omega*x(i)^2;
end
plot(x,y);
axis([-4 4 -50 50])
pause(0.1);
end
This is the same as #phil-goddard's answer, but makes more efficient use of handles to the animated YData and title string.
x = -4 : 0.001 : 4;
y = zeros(1, numel(x));
omega_range = -3 : 0.25 : 3;
% Create line and title, and obtain handles to them.
h_plot = plot(x, y);
axis([-4, 4, -40, 40]);
box on;
grid on;
h_title = title(sprintf('\\omega = %.2f', 0));
for idx = 1:numel(omega_range)
omega = omega_range(idx);
y = omega * (x.^2);
% Replace y data.
h_plot.YData = y;
% Replace title string.
h_title.String = sprintf('\\omega = %.2f', omega);
pause(0.1);
end

MATLAB can't save each axes mouse-clicks on subplot using ButtonDownFcn

I have a 3x1 subplot, and I have figured out how to capture the mouse-click coordinates and store them into an array within each axes. However, I'd like to modify my code so that I am able to store the mouse clicks from each axes all in one go around.
Here is my code:
function Callbacks
x = 0:30;
y1 = 1.5*cos(x);
y2 = 1.5*cos(x)*10;
y3 = 1.5*cos(x)*100;
subplot(3,1,1)
plot(x,y1,'ButtonDownFcn',{#lineCallBack,'plot1'})
subplot(3,1,2)
plot(x,y2,'ButtonDownFcn',{#lineCallBack,'plot2'})
subplot(3,1,3)
plot(x,y3,'ButtonDownFcn',{#lineCallBack,'plot3'})
end
function lineCallBack(src,evt,tag_name)
src.Tag = tag_name;
N=2;
P1array = zeros(N,2);
P2array = zeros(N,2);
P3array = zeros(N,2);
for k = 1:N
if strcmp(tag_name,'plot1')
[P1array(k,1),P1array(k,2)] = ginput(1);
hold on;
plot(P1array(k,1),P1array(k,2),'*r')
elseif strcmp(tag_name,'plot2')
[P2array(k,1),P2array(k,2)] = ginput(1);
hold on;
plot(P2array(k,1),P2array(k,2),'*r')
elseif strcmp(tag_name,'plot3')
[P3array(k,1),P3array(k,2)] = ginput(1);
hold on;
plot(P3array(k,1),P3array(k,2),'*r')
end
end
OUTPUT
P1array =
1 2
3 4
P2array =
0 0
0 0
P3array =
0 0
0 0
As shown on the output above, after clicking through, it seems to only capture the coordinates for the last axes I clicked on. I'd like to be able to have values for all the axes points. Can anyone help? Thanks.

MATLAB update waitbar

I am trying to implement a "percent complete" bar in a MATLAB program, using the waitbar function. However, I am having trouble with it. Here is the code that I have currently:
in my GUI
POSITION = [53.3333 20 188.5446 20];
H = uiwaitbar(POSITION);
for percentageDone = 0;
uiwaitbar(H,percentageDone);
end
then
function h = uiwaitbar(varargin)
if ishandle(varargin{1})
ax = varargin{1};
value = varargin{2};
p = get(ax,'Child');
x(3:4) = value;
set(p,'XData',x)
return
end
pos = varargin{1};
bg_color = [1 1 1];
fg_color = [0 .5 0];
h = axes('Units','pixels',...
'Position',pos,...
'XLim',[0 100],'YLim',[0 1],...
'XTick',[],'YTick',[],...
'Color',bg_color,...
'XColor',bg_color,'YColor',bg_color);
patch([0 0 0 0],[0 1 1 0],fg_color,...
'Parent',h,...
'EdgeColor','none',...
'EraseMode','none');
end
Elsewhere in the script, I have a KeyPressFcn callback, in which the user inputs the answer to their questions. At the end of this callback, for every correct answer I want the waitbar to fill up a little. However, no matter what values I assign to percentageDone variable the waitbar in the GUI does not change at all.
Can anybody help me with this?
I'm confused, you say you are using the builtin function WAITBAR, but then you seem to be implementing one yourself..
Anyway, here is a rather useless example that shows a custom progress bar. Just keep pressing "next" :)
function progressBarDemo()
%# a figure and a plot area
hFig = figure('Menubar','none');
hAxPlot = axes('Parent',hFig, 'Box','on', ...
'Units','normalized', 'Position',[0.1 0.2 0.8 0.6]);
hLine = line('Parent',hAxPlot, 'XData',1:1000, 'YData',nan(1,1000), ...
'Color','b');
%# next button
uicontrol('Style','pushbutton', 'String','next', ...
'Callback',#buttonCallback);
%# progress bar axis
x = linspace(0, 1, 13+1); %# steps
hAx = axes('Parent',hFig, 'XLim',[0 1], 'YLim',[0 1], ...
'XTick',[], 'YTick',[], 'Box','on', 'Layer','top', ...
'Units','normalized', 'Position',[0 0.9 1 0.1]);
hPatch = patch([0 0 x(1) x(1)], [0 1 1 0], 'r', 'Parent',hAx, ...
'FaceColor','r', 'EdgeColor','none');
hText = text(0.5, 0.5, sprintf('%.0f%%',x(1)*100), ...
'Parent',hAx, 'Color','w', 'BackgroundColor',[.9 .5 .5], ...
'HorizontalAlign','center', 'VerticalAlign','middle', ...
'FontSize',16, 'FontWeight','bold');
counter = 2;
%# next button callback function
function buttonCallback(src,evt)
%# draw another random plot
set(hLine, 'YData',cumsum(rand(1000,1)-0.5))
%# update progress bar
set(hPatch, 'XData',[0 0 x(counter) x(counter)])
set(hText, 'String',sprintf('%.0f%%',x(counter)*100))
%# terminate if we have reached 100%
counter = counter + 1;
if counter > numel(x)
set(src, 'Enable','off', 'String','Done')
return
end
end
end
You're probably just missing a drawnow call after setting the XData property, to force a flush of the graphics events queue. If this does not fix your problem, then include enough code to reproduce the symptoms.
Have you tried using Progressbar from the File Exchange? It might save you a lot of hassle. I've always had good results with it.
Do you first create the waitbar? Something like this:
h = waitbar(0, '1', 'Name', 'My progress bar', 'CreateCancelBtn', 'setappdata(gcbf, ''canceling'', 1)');
After that, to update the waitbar:
Edit: fixed bug with text output: percentageDone must be multiplied by 100.
waitbar(percentageDone, h, sprintf('Already %d percent ready!', 100*percentageDone));

How to plot 3D grid (cube) in Matlab

Hi I would like to plot transparent cube-shaped grid with lines in it. Something like this:
However, I managed only to draw a 2D grid:
[X,Y] = meshgrid(-8:.5:8);
Z = X+1;
surf(X,Y,Z)
I use Matlab R2009b.
If it is impossible to plot this in matlab could you recommend me a software I could use.
Consider this vectorized solution. It has the advantage that it creates a single graphic object:
%# these don't all have to be the same
x = -8:2:8; y = -8:2:8; z = -8:2:8;
[X1 Y1 Z1] = meshgrid(x([1 end]),y,z);
X1 = permute(X1,[2 1 3]); Y1 = permute(Y1,[2 1 3]); Z1 = permute(Z1,[2 1 3]);
X1(end+1,:,:) = NaN; Y1(end+1,:,:) = NaN; Z1(end+1,:,:) = NaN;
[X2 Y2 Z2] = meshgrid(x,y([1 end]),z);
X2(end+1,:,:) = NaN; Y2(end+1,:,:) = NaN; Z2(end+1,:,:) = NaN;
[X3 Y3 Z3] = meshgrid(x,y,z([1 end]));
X3 = permute(X3,[3 1 2]); Y3 = permute(Y3,[3 1 2]); Z3 = permute(Z3,[3 1 2]);
X3(end+1,:,:) = NaN; Y3(end+1,:,:) = NaN; Z3(end+1,:,:) = NaN;
%#figure('Renderer','opengl')
h = line([X1(:);X2(:);X3(:)], [Y1(:);Y2(:);Y3(:)], [Z1(:);Z2(:);Z3(:)]);
set(h, 'Color',[0.5 0.5 1], 'LineWidth',1, 'LineStyle','-')
%#set(gca, 'Box','on', 'LineWidth',2, 'XTick',x, 'YTick',y, 'ZTick',z, ...
%# 'XLim',[x(1) x(end)], 'YLim',[y(1) y(end)], 'ZLim',[z(1) z(end)])
%#xlabel x, ylabel y, zlabel z
axis off
view(3), axis vis3d
camproj perspective, rotate3d on
If you don't mind a few for loops, something like this will work:
clf
figure(1)
for g = 0:.2:2
for i = 0:.2:2
plot3([g g], [0 2], [i, i])
hold on
end
end
for g = 0:.2:2
for i = 0:.2:2
plot3([0 2], [g g], [i, i])
hold on
end
end
for g = 0:.2:2
for i = 0:.2:2
plot3([i i], [g g], [0 2])
hold on
end
end
You will just need to make the grid transparent by probably changing line properties, I don't think you can change alpha values to accomplish this. Hope that is helpful.
A more vectorized version of Stephen's answer might be the following:
i = 0:0.2:2;
[X Y] = meshgrid(i,i);
x = [X(:) X(:)]';
y = [Y(:) Y(:)]';
z = [repmat(i(1),1,length(x)); repmat(i(end),1,length(x))];
col = 'b';
hold on;
plot3(x,y,z,col);
plot3(y,z,x,col);
plot3(z,x,y,col);
Unfortunately, MATLAB does not currently support transparent lines (to my knowledge). If you really need them to be transparent I'd suggest using 'patch'.
I understand this is a late reply but it is still valid in case anyone else is looking at doing the same thing.
Assuming you are plotting cubes (/their edges), an alternative to the answers already provided is to use the 'plotcube' code from Oliver:
plotcube
The advantage of this solution is that you can:
Change the transparency of the faces (FaceAlpha), and/or,
Change the transparency of the edges (EdgeAlpha), and/or,
Change the colour of the lines (EdgeColor).
All of these can be constants, or variables.
(e.g. fixed edge colour, or a colour that changes with Z-value etc.)
To add in functionality of 2. and 3. (above) change the 'cellfun(#patch...' section in Olivers code, adding in the four extra lines of code as follows: (replace the whole cellfun section with this; including the new 'EdgeAlpha' and 'EdgeColor' lines):
cellfun(#patch,XYZ{1},XYZ{2},XYZ{3},...
repmat({clr},6,1),...
repmat({'FaceAlpha'},6,1),...
repmat({alpha},6,1),...
repmat({'EdgeAlpha'},6,1),...
repmat({0.2},6,1),... % Set this value to whatever you want; even a variable / matrix
repmat({'EdgeColor'},6,1),...
repmat({'black'},6,1)...
);
For more info on 'patch' please see patch documentation.
An important note:
- for large models (many cubes) this is very slow to run.
e.g. running this 'plotcube' function in a 'for' loop in MATLAB over thousands of blocks. I believe this is from calling the 'patch' function multiple times.
A better solution would be to vectorise; to put all your points (vertices/faces/whatever) together in a single matrix first and then call the #patch function only once (no 'for' loop). This would require changing the code somehow to update all the XYZ data.
I hope that helps someone.
Here is the 'plotcube' code in case the link to the original code by Oliver breaks someday:
function plotcube(varargin)
% PLOTCUBE - Display a 3D-cube in the current axes
%
% PLOTCUBE(EDGES,ORIGIN,ALPHA,COLOR) displays a 3D-cube in the current axes
% with the following properties:
% * EDGES : 3-elements vector that defines the length of cube edges
% * ORIGIN: 3-elements vector that defines the start point of the cube
% * ALPHA : scalar that defines the transparency of the cube faces (from 0
% to 1)
% * COLOR : 3-elements vector that defines the faces color of the cube
%
% Example:
% >> plotcube([5 5 5],[ 2 2 2],.8,[1 0 0]);
% >> plotcube([5 5 5],[10 10 10],.8,[0 1 0]);
% >> plotcube([5 5 5],[20 20 20],.8,[0 0 1]);
% Default input arguments
inArgs = { ...
[10 56 100] , ... % Default edge sizes (x,y and z)
[10 10 10] , ... % Default coordinates of the origin point of the cube
.7 , ... % Default alpha value for the cube's faces
[1 0 0] ... % Default Color for the cube
};
% Replace default input arguments by input values
inArgs(1:nargin) = varargin;
% Create all variables
[edges,origin,alpha,clr] = deal(inArgs{:});
XYZ = { ...
[0 0 0 0] [0 0 1 1] [0 1 1 0] ; ...
[1 1 1 1] [0 0 1 1] [0 1 1 0] ; ...
[0 1 1 0] [0 0 0 0] [0 0 1 1] ; ...
[0 1 1 0] [1 1 1 1] [0 0 1 1] ; ...
[0 1 1 0] [0 0 1 1] [0 0 0 0] ; ...
[0 1 1 0] [0 0 1 1] [1 1 1 1] ...
};
XYZ = mat2cell(...
cellfun( #(x,y,z) x*y+z , ...
XYZ , ...
repmat(mat2cell(edges,1,[1 1 1]),6,1) , ...
repmat(mat2cell(origin,1,[1 1 1]),6,1) , ...
'UniformOutput',false), ...
6,[1 1 1]);
cellfun(#patch,XYZ{1},XYZ{2},XYZ{3},...
repmat({clr},6,1),...
repmat({'FaceAlpha'},6,1),...
repmat({alpha},6,1)...
);
view(3);
you can make the inside line kind of transparent by setting color = [0.65, 0.65, 0.65]. And you can use dash line style for interior lines and solid lines for boundary to make it more like a 3-D object.
In my software package, I code a mesh3 function to plot the 3-D tensor product meshes.
clear all
close all
clc
Nx=11;
Ny=11;
Nz=11;
clf
hold on
[i,j]=meshgrid(1:Nx,1:Ny);
k=zeros(Ny,Nx)+Nz;
surf(i,j,k)
[i,k]=meshgrid(1:Nx,1:Nz);
j=zeros(Nz,Nx)+Ny;
surf(i,j,k)
[j,k]=meshgrid(1:Ny,1:Nz);
i=zeros(Nz,Ny)+Nx;
surf(i,j,k)
[i,j]=meshgrid(1:Nx,1:Ny);
k=zeros(Ny,Nx)+1;
surf(i,j,k)
[i,k]=meshgrid(1:Nx,1:Nz);
j=zeros(Nz,Nx)+1;
surf(i,j,k)
[j,k]=meshgrid(1:Ny,1:Nz);
i=zeros(Nz,Ny)+1;
surf(i,j,k)
view(30,30)