Fixed light source in MATLAB - matlab

I want to draw an earth in Matlab with a fixed light source around it, that way I can observe earth's rotation with dayside and nightside . But now I get stuck on how to use the function light.
My Matlab code is as follows:
figure
load('topo.mat','topo','topomap1');
[x,y,z] = sphere(50);
cla reset
axis square off
props.AmbientStrength = 0.1;
props.DiffuseStrength = 1;
props.SpecularColorReflectance = .5;
props.SpecularExponent = 20;
props.SpecularStrength = 1;
props.FaceColor= 'texture';
props.EdgeColor = 'none';
props.FaceLighting = 'phong';
props.Cdata = topo;
h=surface(x,y,z,props);
h1=light('position',[-1 0 0],'Style','infinite');
% light('position',[-1.5 0.5 -0.5], 'color', [.6 .2 .2]);
set(gcf,'color',[1 1 1]);
el=0;
for az=0:10:300
view(az, el)
drawnow;
end

Related

Colorbar axis ticks changing color on 3D figure in Matlab

I've been trying to change the ticks on the colorbar axis on my 3D but I've encountered the problem where if I do so the color on the entire 3D figure changes. Basically what I'm trying to do is maintain the same kind of color range on the 3D figure while changing the color bar values from 0 - 80 to 50 - 450 instead without changing the color on the actual figure.
Thanks in advance!
clc;
clear all;
close all;
filename = ['*File pathway to the datafiles*' 'filenames.txt'];
T = readtable(filename);
tsize = size(T);
tsize (1);
filename = strcat('*File pathway to the datafiles*', string(T{1,1}));
heat = double(getHeatMap(filename));
%load('myMap2.mat');
figure
set(gcf,'Visible','on')
for i = 1:tsize
filename = strcat('*File pathway to the datafiles*', string(T{i,1}));
if dir(filename).bytes == 0
continue;
end
heat = double(getHeatMap(filename));
[X,tY] = meshgrid( linspace(1,400,size(heat,2)),linspace(0,2*pi,size(heat,1)));
max_heat = max(heat, [], 'all');
min_heat = min(heat, [], 'all');
R = (((heat-min_heat)/(max_heat-min_heat))*50)+100;
Y = cos(tY) .* R;
Z = sin(tY) .* R;
[nx, ny, nz] = surfnorm(X,Y,Z);
nv = reshape([nx ny nz], size(nx,1),size(nx,2),3);
CV = R;
s = surf(X,Y,Z,heat,'VertexNormals',nv, 'EdgeColor','none');
axis([0 400 -200 200 -200 200])
colorbar
colormap('parula')
lighting gouraud
camlight
material dull
caxis([0 80])
drawnow
end
function heat = getHeatMap(filename)
s = dir(filename);
fin=fopen(filename,'r');
I=fread(fin,s.bytes,'uint8=>uint8');
w = uint16(I(1))+256*uint16(I(2));
h = uint16(I(3))+256*uint16(I(4));
skip = s.bytes - w*h + 1;
IN = I(skip:1:s.bytes);
Z=single(reshape(IN,w,h));
Z=griddedInterpolant(Z');
y_range = linspace(1.0,single(h),256);
x_range = linspace(1.0,single(w),512);
heat = uint8(Z({y_range, x_range}));
end
Pastebin link to the datafile, should be saved as 0000.OTT so it can be run.
Before colorbar axis change
After changing colorbar axis between the range 50 - 450 using caxis([50 450])
The color of the surface is given by you, as the input heat to surf. It feels like the easy thing here is simply changing that input.
If you just do surf(X,Y,Z, heat*400/80+50 ,.... you should get what you want.

gif of sphere with changing radius in Matlab

I wish to generate a .gif file of a sphere that grows in size(radius) over time based on a specified function relating radius and time. I'm having some trouble with how to formulate the animation.
Here is what I have so far:
%% Parameters
dt = 0.05;
time = 0:dt:1;
radius = 1
%% generate sphere
[X, Y, Z] = sphere(25);
X=X*radius;
Y=Y*radius;
Z=Z*radius;
mySphere = surf(X,Y,Z, 'FaceLighting','gouraud');
axis equal
shading interp
mySphere.FaceAlpha = 0.3
view([61 15])
colormap bone
hold on
%% generate gif
filename = 'Sizechange.gif';
for n = 1:20
radius = 1 + time(n)
im = frame2im(getframe(1));
[imind,cm] = rgb2ind(im,256);
if n == 1;
imwrite(imind,cm,filename,'gif', 'Loopcount',inf,'DelayTime',dt);
else
imwrite(imind,cm,filename,'gif','WriteMode','append','DelayTime',dt);
end
end
Here I am trying to get it to go from radius 1 to radius 2 in steps of 0.05.
When I run this however, the gif stays still at 1 and there is no animation.
Any help would be greatly appreciated.
As #cris-luengo said, you should redraw your sphere for each iteration on the radius.
%% Parameters
dt = 0.05;
time = 0:dt:1;
radius = 1 ;
%% generate sphere
[X, Y, Z] = sphere(25);
X=X*radius;
Y=Y*radius;
Z=Z*radius;
%figure;
%mySphere = surf(X,Y,Z, 'FaceLighting','gouraud');
% axis equal
% shading interp
% mySphere.FaceAlpha = 0.3;
% view([61 15])
% colormap bone
% hold on
%% generate gif
filename = 'Sizechange.gif';
figure;
for n = 1:20
radius = 1+ time(n);
%====================================================
X=X*radius;
Y=Y*radius;
Z=Z*radius;
mySphere = surf(X,Y,Z, 'FaceLighting','gouraud');
axis equal
shading interp
mySphere.FaceAlpha = 0.3;
view([61 15])
colormap bone
%====================================================
im = frame2im(getframe(1));
[imind,cm] = rgb2ind(im,256);
if n == 1
imwrite(imind,cm,filename,'gif', 'Loopcount',inf,'DelayTime',dt);
else
imwrite(imind,cm,filename,'gif','WriteMode','append','DelayTime',dt);
end
end

Plot the MajorAxisLength and the MinorAxisLength - Matlab

I found this script below in https://blogs.mathworks.com/steve/2010/07/30/visualizing-regionprops-ellipse-measurements/
I wish to plot also the MajorAxisLength and the MinorAxisLength, how can I do it?
Script:
url = 'https://blogs.mathworks.com/images/steve/2010/rice_binary.png';
bw = imread(url);
imshow(bw)
s = regionprops(bw, 'Orientation', 'MajorAxisLength', ...
'MinorAxisLength', 'Eccentricity', 'Centroid');
imshow(bw)
hold on
phi = linspace(0,2*pi,50);
cosphi = cos(phi);
sinphi = sin(phi);
for k = 1:length(s)
xbar = s(k).Centroid(1);
ybar = s(k).Centroid(2);
a = s(k).MajorAxisLength/2;
b = s(k).MinorAxisLength/2;
theta = pi*s(k).Orientation/180;
R = [ cos(theta) sin(theta)
-sin(theta) cos(theta)];
xy = [a*cosphi; b*sinphi];
xy = R*xy;
x = xy(1,:) + xbar;
y = xy(2,:) + ybar;
plot(x,y,'r','LineWidth',2);
end
hold off
You have a lot of unnecessary code in what you posted. I don't think you actually attempted to adjust it for what you say you want to plot. Given what you said you are trying to do in the comments, I think this is the code you want in order to plot the Major Axis Length vs. Minor Axis Length
url = 'https://blogs.mathworks.com/images/steve/2010/rice_binary.png';
bw = imread(url);
s = regionprops(bw, 'Orientation', 'MajorAxisLength', ...
'MinorAxisLength', 'Eccentricity', 'Centroid'); %Get region props
Major=zeros(size(s));
Minor=zeros(size(s));
for k = 1:length(s)
Major(k)= s(k).MajorAxisLength; %get your y values
Minor(k)= s(k).MinorAxisLength; %get your x values
end
figure %create a new figure because you don't want to plot on top of the image
plot(Minor, Major, 'o') %plot
xlabel('Minor Axis Length')
ylabel('Major Axis Length')

presenting motion of random walkers in matlab

I have simulated some random walkers. I used
plot(xb,yb,'b--o')
to show particles in each step. I saw a code in below link with beautiful particles with tail which moves in a blur way. Is there a way which I could my random walkers the same as the walkers in the link in mat lab? Could anyone tell me which should I use instead of the plot function I used?
beautiful particles
The code I tried:
clear all
close all
lbox=20;
%random fluctuation
eta = (2.*pi).*.1;
vs=0.02;
n=200;
birdl=[1:n];
axis([0 lbox 0 lbox])
axis('square')
hold on
xb=rand(n,1).*lbox; %first possition
yb=rand(n,1).*lbox; %first possition
vxb = 1;
vyb = 1;
for steps=1:5000;
xb = xb + vxb;
yb = yb+ vyb;
for bird1 = 1:n;
%periodic boundary condition
if(xb(bird1)<0);xb(bird1)=xb(bird1)+lbox; end
if (yb(bird1)<0);yb(bird1)=yb(bird1)+lbox;end
if (xb(bird1)>lbox);xb(bird1)=xb(bird1)-lbox;end
if (yb(bird1)>lbox);yb(bird1)=yb(bird1)-lbox;end
end
ang=eta.*(rand(n,1)-0.5);
vxb = vs.*cos(ang);
vyb = vs.*sin(ang);
cla
set(gcf,'doublebuffer','on')
plot(xb,yb,'.b')
%quiver(xb,yb,vxb,vyb,'b')
drawnow
end
If you want to create a sort of trail of where the particles have recently been, you can store the previous nStore plots and change their color so that older plots gradually darken and fade to black (alpha transparency like in your sample isn't possible with line objects in MATLAB). Here's a reworking of your code (with a few other improvements, like replacing the inner boundary condition loop with indexing):
clear all
close all
lbox = 20;
%random fluctuation
eta = (2.*pi).*1;
vs = 0.05;
n = 200;
set(gcf, 'doublebuffer', 'on', 'Color', 'k');
set(gca, 'Visible', 'off');
axis([0 lbox 0 lbox])
axis('square')
hold on
xb = rand(n, 1).*lbox; %first possition
yb = rand(n, 1).*lbox; %first possition
vxb = 1;
vyb = 1;
hList = [];
nStore = 30;
cMap = [zeros(nStore+1, 1) linspace(1, 0, nStore+1).' zeros(nStore+1, 1)];
for steps = 1:200
xb = xb + vxb;
yb = yb + vyb;
%periodic boundary condition
index = (xb < 0);
xb(index) = xb(index) + lbox;
index = (yb < 0);
yb(index) = yb(index) + lbox;
index = (xb > lbox);
xb(index) = xb(index) - lbox;
index = (yb > lbox);
yb(index) = yb(index) - lbox;
ang = eta.*(rand(n,1)-0.5);
vxb = vs.*cos(ang);
vyb = vs.*sin(ang);
h = plot(xb, yb, '.g', 'MarkerSize', 12);
if (numel(hList) == nStore)
delete(hList(nStore));
hList = [h hList(1:end-1)];
else
hList = [h hList];
end
set(hList, {'Color'}, num2cell(cMap(1:numel(hList), :), 2));
drawnow
end
And here's an animation:
I created the animation by adding the following code:
% After the drawnow...
frame = getframe(gca);
im = frame2im(frame);
imind(:, :, 1, steps) = uint8(rgb2ind(im, cMap, 'nodither'));
% After the loop...
imwrite(imind(:, :, 1, 1:2:end), cMap, 'randwalk.gif', ...
'Loopcount', Inf, 'DelayTime', 0);
I had to trim out some frames to make the gif smaller.
My shot at "nicer" random walk:
clear all
close all
lbox=20;
figure('Color',[0 0 0])
%random fluctuation
eta = (2.*pi).*1;
vs=0.02;
n=300;
birdl=[1:n];
axis([0 lbox 0 lbox])
axis('square')
hold on
xb=rand(n,1).*lbox; %first possition
yb=rand(n,1).*lbox; %first possition
vxb = 1;
vyb = 1;
for steps=1:5000;
xb = xb + vxb;
yb = yb+ vyb;
for bird1 = 1:n;
%periodic boundary condition
if (xb(bird1)<0);xb(bird1)=xb(bird1)+lbox; end
if (yb(bird1)<0);yb(bird1)=yb(bird1)+lbox;end
if (xb(bird1)>lbox);xb(bird1)=xb(bird1)-lbox;end
if (yb(bird1)>lbox);yb(bird1)=yb(bird1)-lbox;end
end
ang=eta.*(rand(n,1)-0.5);
vxb = vs.*cos(ang);
vyb = vs.*sin(ang);
cla
set(gca,'Color',[0 0 0]);
set(gcf,'doublebuffer','on')
set(gca,'YTick',[]);
set(gca,'XTick',[]);
plot(xb,yb,'.g','markersize',10)
% this should draw lines, but its slow and not as neat as a web app
% plot([xb xb-vxb*5]',[yb yb-vyb*5]','g')
drawnow
end

How to plot a graph of a custom surface in Matlab?

I would like to plot the surface of this function in Matlab:
w=(m*(1-p))/(h-1+m*(1-p))
Where
h=0.98;
P=[0.05:0.001:0.98];
M=[0:0.001:1];
The graph should look like this:
I tried to implement the graphing function as:
h=0.98;
P=[0.05:0.001:0.98];
M=[0:0.001:1];
W=[];
for i=1:size(P, 2)
for j=1:size(M, 2)
p=P(i);
m=M(j);
w=(m*(1-p))/(h-1+m*(1-p));
if w>1000
w=1000;
end
if w<0
w=0;
end
W(i, j) = w;
end
end
mesh(M, P, W);
But since the function changes rapidly around the boundary condition, my graph ended up looking like this:
How can I smooth out the curve and give it a nice, uniform grid like in the first picture?
Here's a way to do what you want. See comments in the code for more information.
%% //Definitions
w = #(h,m,p)(m.*(1-p))./(h-1+m.*(1-p)); %// w as a function handle
w_min = 0; w_max = 10; %// For plots
cMap = hot(200); cMap = cMap(floor(0.5*length(cMap)):ceil(0.7*length(cMap)),:);
h = 0.98;
m_start = 0; m_end = 1; m_step = [0.02 0.01 0.001];
p_start = 0.05; p_end = 0.98; p_step = [0.1 0.01 0.001];
%// Definitions of the mesh used in plotting (same for all charts)
mesh_m_step = 0.05; mesh_p_step = 0.05;
[meshM,meshP] = meshgrid(m_start:mesh_m_step:m_end,p_start:mesh_p_step:p_end);
meshW = w(h,meshM,meshP);
%% //Evaluation and plotting:
figure(); set(gcf,'Position',[240,500,1391,376]); subplot(1,3,1);
for ind1 = 1:3
%% // Evaluate equation
[MM,PP] = meshgrid(m_start:m_step(ind1):m_end,p_start:p_step(ind1):p_end);
WW = w(h,MM,PP);
%% // Plot
subplot(1,3,ind1);
surf(MM,PP,WW,'EdgeColor','none'); view([45,45]);
hold on; mesh(meshM,meshP,meshW,'EdgeColor','k','FaceColor','none');
colormap(cMap); %// Fix the colormap
zlim([w_min,w_max]); caxis(zlim) %// Modify zlim
end
Which results in: