How to make 2 circles rotate/spin like a wheel in Matlab - matlab

I've plotted two circles and filled them with the colormap 'jet'. However, every time I try to rotate the circles using rotate function or even the spin function of colormap to make the colour jet spin inside the circle - It changes the plot entirely - Rotating only 1 circle, filling up the screen, and rotating it at an angle.
Can someone please explain how I can rotate those 2 circles, as though they are wheels of a car?
The code is as follows: (I commented out my attempt at rotating and spin)
%First Circle
r1 = linspace(0,1,10);
theta1 = linspace(0, 2*pi, 100);
[rg, thg] = meshgrid(r1,theta1);
[x1,y1] = pol2cart(thg,rg);
circ1 = pcolor(x1,y1,thg);
colormap(jet);
ylim([-2 2]);
hold on
%Second Circle
r2 = linspace(0,1,10);
theta2 = linspace(0, 2*pi, 100);
[rg, thg] = meshgrid(r2,theta2);
[x2,y2] = pol2cart(thg,rg);
circ2 = pcolor(x2+2.5,y2,thg);
%colormap(jet);
%for ang=1:360
% rotate(circ2,[0 1 1],-1);
% drawnow;
%end
%spinmap(5,1); %Spins colorjet map
view ([0 90]);
shading interp;
axis equal;
grid off;
hold off

Change your plotting to:
for ang=1:360
cla; hold on
circ1 = pcolor(x1,y1,thg);
circ2 = pcolor(x2,y2,thg);
rotate(circ2,[0 0 1],-ang);
rotate(circ1,[0 0 1],-ang);
set(circ1,'XData',get(circ1,'Xdata')+2.5); %change circ1 position
view ([0 90]);
shading interp;
axis equal;
grid off;
hold off
drawnow;
end
The problem with rotate is that rotates the whole figure, so once one circle is rotating on place, if you apply rotate again the other one will rotate around the first one. To solve that, create both circles in the same place, rotate both, and then put one in a different position

Related

Matlab: Plot colourful line over background gray image whilst retaining colorbar information

I am using MATLAB I would like to plot a colourful trajectory on top of a grayscale png image whilst retaining the colour information of the trajectory. For example with the data below, I would like to plot Data B over Image A. Without Data B turning gray and without making the colourbar represent the grayscaled image. Any help would be greatly appreciated!
%Image A
RGB = imread('peppers.png');
I = rgb2gray(RGB);
figure
imshow(I)
hold on
%Data B
x = 1:1000;
y = x;
z = zeros(size(x));
lineColor = x;
surface([x;x], [y;y], [z;z], [lineColor;lineColor],...
'FaceColor', 'no',...
'EdgeColor', 'interp',...
'LineWidth', 8);
cc = colorbar();
Many thanks!
MATLAB doesn't seem to like to do more than one colourmap pet axes. By using hold on we're plotting both the image (gray colormap) and surface (e.g. jet colormap) to the same plot. By default from the non-RGB image in imshow the colormap is set to gray, and so it is the same for the surface plot. Trying to change the colourmap by invoking colormap('jet') changes the colormap for both the image and surface.
Seems that there have been others with the same problem:
https://uk.mathworks.com/matlabcentral/answers/194554-how-can-i-use-and-display-two-different-colormaps-on-the-same-figure
The best solution appears to be defining two seperate axes to the same figure and linking them so that positional information matches. You need to specify which axis to plot to, so imshow has been replaced with imagesc which has more flexibility.Then you can define a different colourmap to each axis. Unfortunately, the colorbar probably won't play ball everytime so you gotta fiddle with its positional information a bit.
In practice for your code:
figure
%Image A
ax1 = axes;
RGB = imread('peppers.png');
I = rgb2gray(RGB);
imagesc(ax1,I)
colormap(ax1,'gray')
%Data B
ax2 = axes;
ax2.Visible = 'off'; % make transparent
x = 1:1000;
y = x;
z = zeros(size(x));
lineColor = x;
h = surface(ax2, [x;x], [y;y], [z;z], [lineColor;lineColor],...
'FaceColor', 'no',...
'EdgeColor', 'interp',...
'LineWidth', 8);
colormap(ax2,'jet') % colourful colourmap
% Gotta reposition the colourbar, tedious bit!
% Position: [left bottom width height]
cb2 = colorbar(ax2,'Position',[.91 .11 .0375 .815]);
linkaxes([ax1,ax2]) % same positions in 1st and 2nd plot
Result:

Does anybody know how should I use animatedline in order to draw me an orbit immediately?

This is the main code
%%%%%%%%%%%% Valori pentru Rcsc
%%%%Pozitiile si vitezele pe cele 3 axe
y0(1,1)= 743322.3616 ;
y0(2,1)= -6346021.219 ;
y0(3,1)= -3394131.349 ;
y0(4,1)= 5142.38067;
y0(5,1)= 4487.44895 ;
y0(6,1)= -7264.00872;
%%%% Timpul
tspan=[0 :864];
%%%% Masa(kg) si aria suprafetei satelitului (m^2)
m = 217 ; %320;
A = 1.2; %8;
%%%% Metoda Runge-Kutta de ordin 4
h=1;
y = zeros(6, tspan(end)/h);
y(:,1) = y0;
for i=1:(tspan(end)/h)
H=sqrt(y(1,i)^2+y(2,i)^2+y(3,i)^2);
k_1 = proiectia(tspan(i), y(:,i), H, m, A, y(4:6, i));
k1=double(k_1);
k_2 = proiectia(tspan(i)+0.5*h, y(:,i)+0.5*h*k_1, H, m, A, y(4:6, i));
k2=double(k_2);
k_3 = proiectia((tspan(i)+0.5*h), (y(:,i)+0.5*h*k_2), H, m, A, y(4:6, i));
k3=double(k_3);
k_4 = proiectia((tspan(i)+h),(y(:,i)+k_3*h), H, m, A, y(4:6, i));
k4=double(k_4);
y(:,i+1) = double(y(:,i) + (1/6)*(k1+2*k2+2*k3+k4)*h);
end
%%% Distanta satelitului
Rcsc = ((y(1,:).^2 + y(2,:).^2 + y(3,:).^2).^0.5);
n=50;
%plot(tspan,Rcsc)
%% Textured 3D Earth example
%
% Ryan Gray
% 8 Sep 2004
% Revised 9 March 2006, 31 Jan 2006, 16 Oct 2013
%% Options
space_color = 'k';
npanels = 180; % Number of globe panels around the equator deg/panel = 360/npanels
alpha = 1; % globe transparency level, 1 = opaque, through 0 = invisible
GMST0 = []; % Don't set up rotatable globe (ECEF)
%GMST0 = 4.89496121282306; % Set up a rotatable globe at J2000.0
% Earth texture image
% Anything imread() will handle, but needs to be a 2:1 unprojected globe
% image.
image_file = 'https://upload.wikimedia.org/wikipedia/commons/thumb/c/cd/Land_ocean_ice_2048.jpg/1024px-Land_ocean_ice_2048.jpg';
% Mean spherical earth
erad = 6371008.7714; % equatorial radius (meters)
prad = 6371008.7714; % polar radius (meters)
erot = 7.2921158553e-5; % earth rotation rate (radians/sec)
%% Create figure
figure('Color', space_color);
hold on;
orbit=animatedline;
addpoints(orbit,y(1,:),y(2,:),y(3,:));
drawnow
% Turn off the normal axes
set(gca, 'NextPlot','add', 'Visible','off');
axis equal;
axis auto;
% Set initial view
view(0,30);
axis vis3d;
%% Create wireframe globe
% Create a 3D meshgrid of the sphere points using the ellipsoid function
[x, y, z] = ellipsoid(0, 0, 0, erad, erad, prad, npanels);
globe = surf(x, y, -z, 'FaceColor', 'none', 'EdgeColor', 0.5*[1 1 1]);
%% Texturemap the globe
% Load Earth image for texture map
cdata = imread(image_file);
% Set image as color data (cdata) property, and set face color to indicate
% a texturemap, which Matlab expects to be in cdata. Turn off the mesh edges.
set(globe, 'FaceColor', 'texturemap', 'CData', cdata, 'FaceAlpha', alpha, 'EdgeColor', 'none');
What I wanna do is that when I run the script a figure with the Earth should appear, and while the positions are being caluclated by the runge kutta algorithm it should upload the orbit in real time. But now the figure appears only after the Rk algorithm is being calculated till the end of tspan and the orbit from the figure is already uploaded without intermediate points. What should I do? I've seen on github that others use animatedline and drawnow.
I was thinking about
orbit=animatedline;
addpoints(orbit,y(1,:),y(2,:),y(3,:));
drawnow
end
But where should I put this line exactly? if I put it in the rk loop it doesn't work and if I put it
% Create figure
figure('Color', space_color);
%%
orbit=animatedline;
addpoints(orbit,y(1,:),y(2,:),y(3,:));
drawnow
it first displays a figure with the orbit but not by intermediate points and then a different figure with the Earth ,while the orbit and the Earth should be in the same figure.
You are using animatedline in a wrong way.
The line:
orbit = animatedline;
should be placed before the loop that calculates the points, and the lines:
addpoints(orbit,y(1,i),y(2,i),y(3,i));
drawnow
should be placed within it, to add one (or several) points to the line on each iteration. But, a better approach, would be to first calculate all the orbit and then use a loop for the animation. This way you have more control over the rate of the animation. Here is a small example using your case:
orbit = animatedline;
for k = 1:size(y,2)
addpoints(orbit,y(1,k),y(2,k),y(3,k));
drawnow
end
Alternative option
Don't use animated line just keep updating the data in the plot. Here is a simple workout for this:
% create a sphere with earth map on it:
set(gcf,'Color','k')
earth = imread('earth.jpg');
[X,Y,Z] = sphere(50);
warp(-X,Y,-Z,earth)
axis off
view(-46,17)
% set an animation of a simple orbit:
Nframes = 100; % number of steps in the orbit
% calculation of the orbit:
orb = linspace(-pi,pi,Nframes);
x = cos(orb).*1.5;
y = sin(orb);
hold on
% plot the whole orbit invisible, just for setting the axes limits:
tmp = plot(x,y,'Color','none');
p = plot(x(1),y(1),'LineWidth',3,'Color','m'); % plot the first step
hold off
for k = 1:numel(orb)
p.XData = x(1:k); % update the data of the plot
p.YData = y(1:k);
pause(0.05) % delay
end
The result:

Labeling 3D Surface Plots in MATLAB along respective axes

I have doubts regarding Labeling 3D Surface Plots in MATLAB along respective axes.
for j=1:length(op)
x = op{j}(:,1);
z = st:inc:en;
y = op{j}(:,2:end);
figure
surf(x,z,y.','FaceAlpha',1.0) % surface plot
xlabel('Non-Dimensional Number (k_0a)')
ylabel('Non-Dimensional Horizontal Force (HF_P)')
zlabel('Non-Dimensional Porous Parameter (G_S)')
axis tight
view(30,40)
grid on
end
The result is the following 3D plot having labels not alligned in respective axis. Any help on alligning the labels in respective axes is highly appreciated.
Many Thanks.
You can set the position and the rotation of the label as follow,
[x,y] = meshgrid(1:0.5:10,1:20);
z = sin(x) + cos(y);
figure
surf(x,y,z,'FaceAlpha',1.0) % surface plot
xlabel('Non-Dimensional Number (k_0a)','FontSize', 20)
ylabel('Non-Dimensional Horizontal Force (HF_P)','FontSize', 20)
zlabel('Non-Dimensional Porous Parameter (G_S)','FontSize', 20)
axis tight
view(30,40)
grid on
xh = get(gca,'XLabel'); % Handle of the x label
set(xh, 'Units', 'Normalized')
pos = get(xh, 'Position');
set(xh, 'Position',pos.*[1,-0.5,1],'Rotation',-10)
yh = get(gca,'YLabel'); % Handle of the y label
set(yh, 'Units', 'Normalized')
pos = get(yh, 'Position');
set(yh, 'Position',pos.*[1,-0.7,1],'Rotation',30)
the results,
Ref

Saving two fig that can be superposed_ Matlab

I am saving two matlab figures as png and I want them to have the same size in order to be perfectly superposable.
The first figure is computed by the function 'FilledCircle2' which is a circle divided in half with two colors.
The second figure is computed by function 'FilledCircleL' which is the left half of the circle computed by the function 'FilledCircle2'.
I want to be able to have two figures, both with the same size so they can be perfectly superposed.
Can someone help me understand what I am doing wrong?
Here is my code, with both of the functions and respective outputs:
function []=FilledCircle2(x0,y0,Radius,N, col1, col2)
if(N<=1)
error('N must be greater than 1');
end
hold on
axis equal
axis off
hold on
t=(0:N)*2*pi/N; %t=-pi:0.01:pi
x=Radius*cos(t)+x0;
y=Radius*sin(t)+y0;
plot(x,y)
hold on
%Divide circle in to 2 equal parts
n=2;
thetas = linspace(-pi, pi,n+1); %linspace generates n points. The space between the points is [(pi/2)-(-pi/2)]/(n)
% Specify any colors wanted
colors = [col1; col2];
for k = 1:n
tt = linspace(thetas(k), thetas(k+1));
xi = Radius * cos(tt) + x0;
yi = Radius * sin(tt) + y0;
c2= fill([xi(:); x0], [yi(:); y0], colors(k,:)); %Assign diffrent colors to each circle 'slice'
set (c2, 'edgecolor','white')
set(c2,'LineWidth',2.0)
set(gcf,'PaperUnits','inches','PaperSize',[0.8666,0.8666],'PaperPosition',[0 0 0.8666 0.8666])%setting size (130/150, 130/150, 150pixels per inch being the default size of img), paper position is imporrtant as otherwise i will have extra border
set(gca, 'Position', [0 0 1 1]);
set(gcf,'color',[0.49019607843137 0.49019607843137 0.49019607843137])%figure properties, rgb(125/255,125/255,125/255)
fig = gcf;
fig.InvertHardcopy = 'off'; %saves the fig with the set background color
%rotates the plot
az= 90; %azimuth, az, is the horizontal rotation about the z axis as measured in degrees from the negative y-axis. Positive values indicate counterclockwise rotation
el= 90; % vertical elevation of the view point in degrees
view(az,el);
hold on
end
Here is the output of the function FilledCircle2(0,0,10,300, 'y', 'r'):
[
function []=HalfFilledCircleL(x0,y0,Radius,N, col1)
if(N<=1)
error('N must be greater than 1');
end
hold on
axis equal
% axis tight
axis off
hold on
t=(0:N)*(-pi)/N; %t=-pi:0.01:pi
x=Radius*cos(t)+x0;
y=Radius*sin(t)+y0;
hold on
c1=fill(x,y,col1); %filling the semi-circle
set (c1, 'edgecolor','white') %setting the outline color of the semi-circle
set(gcf,'color',[0.49019607843137 0.49019607843137 0.49019607843137])%figure properties, rgb(125/255,125/255,125/255)
set(c1,'LineWidth',2.0)
set(gcf,'PaperUnits','inches','PaperSize',[0.8666,0.8666],'PaperPosition',[0 0 0.8666,0.8666])%setting size (130/150, 130/150, 150pixels per inch being the default size of img), paper position is imporrtant as otherwise i will have extra border
set(gca, 'Position', [0 0 1 1]);
fig = gcf;
fig.InvertHardcopy = 'off'; %saves the fig with the set background color
% %rotates the plot
az= 90; %azimuth, az, is the horizontal rotation about the z axis as measured in degrees from the negative y-axis. Positive values indicate counterclockwise rotation
el= 90; % vertical elevation of the view point in degrees
view(az,el);
end
Here is the output of the function HalfFilledCircleL(0,0,10,300, 'r'):
use xlim and ylim to set the xy limits of the axes:
figure;
HalfFilledCircleL(0,0,10,300, 'r');
xlim([-12 12]);ylim([-12 12]);
az= -90; %azimuth, az, is the horizontal rotation about the z axis as measured in degrees from the negative y-axis. Positive values indicate counterclockwise rotation
el= 90; % vertical elevation of the view point in degrees
view(az,el);
figure;
FilledCircle2(0,0,10,300, 'y', 'r');
xlim([-12 12]);ylim([-12 12]);

Calculate gradients of a 3d structure in Matlab

I try to use the Matlab function gradient to calculate the gradient of a volume. I use quiver to display the gradients of slices.
I use a cube-like volume, which is symmetric with respect to x, y, and z axis. To my surprise, the result is not the same for all slices. Actually only the result in the xy-plane (Z-slice, last image) is the expected result.
I know that there are issues when calculating the gradient at the border of an image. But for me the result at the border is not important and so I don't care if the result next to the border is correct. For me it would be important that all three images look like the last one.
Can somebody tell me what is wrong with my code? Thanks!
f=zeros(20,20,20);
space = 5;
f(:,:,space) = 1; f(:,:,end-space) = 1;
f(:,space,:) = 1; f(:,end-space,:) = 1;
f(space,:,:) = 1; f(end-space,:,:) = 1;
space = 4;
f(:,:,space) = 1; f(:,:,end-space) = 1;
f(:,space,:) = 1; f(:,end-space,:) = 1;
f(space,:,:) = 1; f(end-space,:,:) = 1;
size_iso = size(f);
x_slice = round(size_iso(1)/2);
y_slice = round(size_iso(2)/2);
z_slice = round(size_iso(3)/2);
% display the gradient of the edge map
[fx,fy,fz] = gradient(f,0.1);
figure;
image(squeeze(f(x_slice,:,:))*50); colormap(gray(64)); hold on;
quiver(squeeze(fy(x_slice,:,:)),squeeze(fz(x_slice,:,:)));
axis equal;
title(['edge map gradient of X-slice ', num2str(x_slice)]);
figure;
image(squeeze(f(:,y_slice,:))*50); colormap(gray(64)); hold on;
quiver(squeeze(fx(:,y_slice,:)),squeeze(fz(:,y_slice,:)));
axis equal;
title(['edge map gradient of Y-slice ', num2str(y_slice)]);
figure;
image(squeeze(f(:,:,z_slice))*50); colormap(gray(64)); hold on;
quiver(squeeze(fx(:,:,z_slice)),squeeze(fy(:,:,z_slice)));
axis equal;
title(['edge map gradient of Z-slice ', num2str(z_slice)]);
Things are bit more complicated with 3D matrices and coordinates.
For example
img = rand(10,30);
imagesc(img);
axis equal;
will display an image 30 pixels wide and 10 pixels high.
In MatLab when you display an image its first dimension (rows) is actually Y-axis on the plot. Second dimension (columns) is X-axis on the plot.
See, for example, http://www.mathworks.com/help/matlab/math/multidimensional-arrays.html
To illustrate mistake in your code consider simplified example:
% we need a 3D matrix with
% 10 points along the X-axis
% 20 points along the Y-axis
% 30 points along the Z-axis
f = rand(20,10,30); % note the order of numbers
size_iso = size(f), % gives [20 10 30]
x_slice = round(size_iso(2)/2) % gives 5
y_slice = round(size_iso(1)/2) % gives 10
z_slice = round(size_iso(3)/2) % gives 15
figure;
image(squeeze(f(:,x_slice,:))*50); colormap(gray(64)); hold on;
axis equal;
title(['X-slice ', num2str(x_slice)]);
% this code produces image 30 pixels wide and 20 pixels high
% Thus 1st dimension (vertical axis) is actually the Y-axis
% Thus 2nd dimension (horizontal axis) is actually the Z-axis
figure;
image(squeeze(f(y_slice,:,:))*50); colormap(gray(64)); hold on;
axis equal;
title(['Y-slice ', num2str(y_slice)]);
% this code produces image 30 pixels wide and 10 pixels high
% Thus 1st dimension (vertical axis) is actually the X-axis
% Thus 2nd dimension (horizontal axis) is actually the Z-axis
figure;
image(squeeze(f(:,:,z_slice))*50); colormap(gray(64)); hold on;
axis equal;
title(['Z-slice ', num2str(z_slice)]);
% this code produces 10 pixels wide and 20 pixels high
% Thus 1st dimension (vertical axis) is actually the Y-axis
% Thus 2nd dimension (horizontal axis) is actually the X-axis
For your code to work properly you should pay attention not only to the order of dimensions in the slice image but also to the way they are shifted by squeeze function.
Therefore you should provide proper combination of coordinates to the subsequent quiver function call.
I modified your code to fill slab perpendicular to given axis with unique value so you should be able to distinguish them easier. Also I'm using different dimensions along each axis for the same purpose.
xvalue=0.33;
yvalue=0.66;
zvalue=1.00;
% we need a 3D matrix with
% 10 points along the X-axis
% 20 points along the Y-axis
% 30 points along the Z-axis
f = zeros(20,10,30); % note the order of numbers
space = 3;
f(:,space,:) = xvalue; f(:,end-space,:) = xvalue;
f(space,:,:) = yvalue; f(end-space,:,:) = yvalue;
f(:,:,space) = zvalue; f(:,:,end-space) = zvalue;
size_iso = size(f);
x_slice = round(size_iso(2)/2); % note dimension number here for x_slice
y_slice = round(size_iso(1)/2); % note dimension number here for y_slice
z_slice = round(size_iso(3)/2);
% display the gradient of the edge map
[fx,fy,fz] = gradient(f,0.1);
figure;
image(squeeze(f(:,x_slice,:))*50); colormap(gray(64)); hold on;
quiver(squeeze(fz(:,x_slice,:)),squeeze(fy(:,x_slice,:)));
axis equal;
title(['edge map gradient of X-slice ', num2str(x_slice)]);
xlabel('Z')
ylabel('Y')
figure;
image(squeeze(f(y_slice,:,:))*50); colormap(gray(64)); hold on;
quiver(squeeze(fz(y_slice,:,:)),squeeze(fx(y_slice,:,:)));
axis equal;
title(['edge map gradient of Y-slice ', num2str(y_slice)]);
xlabel('Z')
ylabel('X')
figure;
image(squeeze(f(:,:,z_slice))*50); colormap(gray(64)); hold on;
quiver(squeeze(fx(:,:,z_slice)),squeeze(fy(:,:,z_slice)));
axis equal;
title(['edge map gradient of Z-slice ', num2str(z_slice)]);
xlabel('X')
ylabel('Y')
Yes, this is tricky and hard to understand at first but you'll get used to it with practice.