gif of sphere with changing radius in Matlab - 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

Related

How do I label lines in a MatLab plot?

What my plot looks like
What the plot should look like
The code is working like it should but im trying to get the labels to show up on each line from (1-8). Just like the picture above.
I have read a bunch of posts and tried to search Matlab but i havent been able to figure it out.
clc;clear;close all;
V_inf = 20; % freestream velocity
R = 1; % cylinder radius
n = 8; % number of panels
d_theta = 2*pi/n; % resolution of angles
alpha = 0; % angle of attack
theta = pi+pi/n:-d_theta:-pi+pi/n; % angles of boundary points of panels
X = R*cos(theta); % X coordinates of boundary points of panels
Y = R*sin(theta); % Y coordinates of boundary points of panels
Phi = zeros(n,1); % angle from Vinf to bottom of panel
beta = zeros(n,1); % angle from Vinf to outward normal of panel
conX = zeros(n,1); % X coordinates of control points
conY = zeros(n,1); % Y coordinates of control points
S = zeros(n,1); % panel length
for i = 1:n
Phi(i) = -alpha + atan2((Y(i+1)-Y(i)),(X(i+1)-X(i)));
beta(i) = Phi(i)+pi/2;
if beta(i)>2*pi, beta(i)=beta(i)-2*pi;
elseif beta(i)<0, beta(i)=beta(i)+2*pi; end
conX(i) = (X(i+1)+X(i))/2;
conY(i) = (Y(i+1)+Y(i))/2;
S(i) = sqrt((X(i+1)-X(i))^2 + (Y(i+1)-Y(i))^2);
end
close all
plot(R*cos(0:0.01:2*pi),R*sin(0:0.01:2*pi),'b', X,Y,'r',conX,conY,'g^');
axis equal; legend('Exact shape','Panel approximation','Control points')
xlabel('x, m'); ylabel('y, m'); title('Fig. 1 Panel layout (n = 8, R = 1m)');
Possibly plotting the labels along the points of a circle using the text() function may suffice. There's some shifting of points and flipping that needs to be done to get the order you wish but otherwise it's just 8 points taken along a circle that is smaller in diameter in comparison to the octagon. An alternative would be using the green triangles as reference instead but that involves more math. As long as your octagon is expected to be symmetrical vertically and horizontally this should work alright.
clc;clear;close all;
V_inf = 20; % freestream velocity
R = 1; % cylinder radius
n = 8; % number of panels
d_theta = 2*pi/n; % resolution of angles
alpha = 0; % angle of attack
theta = pi+pi/n:-d_theta:-pi+pi/n; % angles of boundary points of panels
X = R*cos(theta); % X coordinates of boundary points of panels
Y = R*sin(theta); % Y coordinates of boundary points of panels
Phi = zeros(n,1); % angle from Vinf to bottom of panel
beta = zeros(n,1); % angle from Vinf to outward normal of panel
conX = zeros(n,1); % X coordinates of control points
conY = zeros(n,1); % Y coordinates of control points
S = zeros(n,1); % panel length
for i = 1:n
Phi(i) = -alpha + atan2((Y(i+1)-Y(i)),(X(i+1)-X(i)));
beta(i) = Phi(i)+pi/2;
if beta(i)>2*pi, beta(i)=beta(i)-2*pi;
elseif beta(i)<0, beta(i)=beta(i)+2*pi; end
conX(i) = (X(i+1)+X(i))/2;
conY(i) = (Y(i+1)+Y(i))/2;
S(i) = sqrt((X(i+1)-X(i))^2 + (Y(i+1)-Y(i))^2);
end
close all
plot(R*cos(0:0.01:2*pi),R*sin(0:0.01:2*pi),'b', X,Y,'r',conX,conY,'g^');
axis equal; legend('Exact shape','Panel approximation','Control points')
xlabel('x, m'); ylabel('y, m'); title('Fig. 1 Panel layout (n = 8, R = 1m)');
%*************************************************************************%
%ADDING LABELS BY PLOTTING LABELS ALONG CIRCLE%
%*************************************************************************%
Radius = 0.8;
Number_Of_Data_Points = 9;
theta = linspace(0,2*pi,Number_Of_Data_Points);
X_Circle = Radius*cos(theta);
X_Circle = X_Circle(1:end-1);
Y_Circle = Radius*sin(theta);
Y_Circle = Y_Circle(1:end-1);
X_Circle = flip(circshift(X_Circle,3));
Y_Circle = flip(circshift(Y_Circle,3));
for Point_Index = 1: numel(conX)
X_Displacement = X_Circle(Point_Index);
Y_Displacement = Y_Circle(Point_Index);
text(X_Displacement,Y_Displacement,num2str(Point_Index),'HorizontalAlignment','center','fontsize',20);
end
To Plot on Control Points:
%*************************************************************************%
%ADDING LABELS BY PLOTTING LABELS ALONG CONTROL POINTS%
%*************************************************************************%
for Point_Index = 1: numel(conX)
text(conX(Point_Index),conY(Point_Index),num2str(Point_Index),'HorizontalAlignment','center','fontsize',20);
end

How to prevent an object from being illuminated by camlight in Matlab?

[Hereafter are 4 snippets, one should only be interested in reading the two first ones. However by copy-pasting all of these, one should be able to launch what I see, although screenshots are provided at the end.]
Hi, by launching this main.m :
%To see if plotting a tick after setting camlight headlight will leads to
%its background becoming gray or not
%clear all
figure
arrow = arrow3D([0 0 0], [1 1 1], 'r', 0.8, 0.2, 1.5);
set(arrow, 'EdgeColor', 'interp', 'FaceColor', 'interp');
%camlight headlight %might be interesting to uncomment this line
pause(5)
surfaceHandle = rotateAxisTicks('lol','r',10,-0.3,0.5,0.5,1,1,1,0);
pause(5)
camlight headlight
%material(surfaceHandle,'default') %doesn't work
%surfaceHandle1.FaceLighting = 'none' %doesn't work
, which uses that function rotateAxisTicks.m
function surfaceHandle = rotateAxisTicks(str,color,fontsize,zmax,graduSpace,boxHeight,perc,labelNumber,axnumber,thetaInput)
%https://stackoverflow.com/questions/9843048/matlab-how-to-plot-a-text-in-3d
%zmax : give it a negative value to not overlap the axis
%graduSpace : space between each graduation, within the projected on [0,1] axis if axis = x||y, OR local (not yet projected on x,y) axis !!
%boxHeight : width of the boxes depend on how much the axis graduations are refined, so height shouldn't depend on graduSpace
%perc : if perc = 1 (100%), then the labels are all sticked together with no space inbetween
%labelNumber : the first tick to be displayed is actually associated to the second graduation (0 can't get several labels)
%axnumber : out of nbParams, 1 for x, 2 for y, then, from closest to x, to closest to y : 3 to nbParams.
%thetaInput : (angle around z, from x to the axis) has to be in degree
%% Seems like there is no way to get rid of the black contouring...
hFigure = figure(1000);
set(hFigure,'Color', 'w', ... % Create a figure window
'MenuBar', 'none', ...
'ToolBar', 'none');
hText = uicontrol('Parent', hFigure, ... % Create a text object
'Style', 'text', ...
'String', str, ...
'BackgroundColor', 'w', ...
'ForegroundColor', color, ...
'FontSize', fontsize, ...
'FontWeight', 'normal');
set([hText hFigure], 'Pos', get(hText, 'Extent')); %# Adjust the sizes of the
%# text and figure
imageData = getframe(hFigure); %# Save the figure as an image frame
delete(hFigure);
textImage = imageData.cdata; %# Get the RGB image of the text
%% MAKE THE X,Y,Z (text) REVERSE DEPENDING ON AZIMUT VALUE (launch a fig and see on the bottom in real time the azimut value)
% X or Y or Z(1,1) = _______
% * |
% | |
% |_______|
% X or Y or Z(1,2) = _______
% | *
% | |
% |_______|
% X or Y or Z(2,1) = _______
% | |
% | |
% x_______|
% X or Y or Z(2,2) = _______
% | |
% | |
% |_______x
if axnumber == 2 %axis = y
X = [0 0; 0 0];
Y = [0 perc*graduSpace; 0 perc*graduSpace] + labelNumber*graduSpace - perc*graduSpace/2;
%(graduSpace/2)/2 to center under the graduation, (1-perc)/2) to
%additionally shift a bit so that the perc% of graduSpace stay centered
%under the graduation
else %I assume axis = x, that I might later rotate if it's not actually x
X = [0 perc*graduSpace; 0 perc*graduSpace] + labelNumber*graduSpace - perc*graduSpace/2; %+labelNumber*((graduSpace/2)+((1-perc)/2)*graduSpace)
Y = [0 0; 0 0];
end
Z = [zmax zmax; zmax-boxHeight zmax-boxHeight];
surfaceHandle = surf(X, Y, Z, 'FaceColor', 'texturemap', 'CData', textImage);
if axnumber > 2
rotate(surfaceHandle, [0 0 1], thetaInput,[0 0 0]);
end
end
as well as that function arrow3D.m :
function arrowHandle = arrow3D(pos, deltaValues, colorCode, stemRatio, cylRad, radRatioCone)
% arrowHandle = arrow3D(pos, deltaValues, colorCode, stemRatio) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Used to plot a single 3D arrow with a cylindrical stem and cone arrowhead
% pos = [X,Y,Z] - spatial location of the starting point of the arrow (end of stem)
% deltaValues = [QX,QY,QZ] - delta parameters denoting the magnitude of the arrow along the x,y,z-axes (relative to 'pos')
% colorCode - Color parameters as per the 'surf' command. For example, 'r', 'red', [1 0 0] are all examples of a red-colored arrow
% stemRatio - The ratio of the length of the stem in proportion to the arrowhead. For example, a call of:
% arrow3D([0,0,0], [100,0,0] , 'r', 0.82) will produce a red arrow of magnitude 100, with the arrowstem spanning a distance
% of 82 (note 0.82 ratio of length 100) while the arrowhead (cone) spans 18.
%
% Example:
% arrow3D([0,0,0], [4,3,7]); %---- arrow with default parameters
% axis equal;
%
% Author: Shawn Arseneau
% Created: September 14, 2006
% Updated: September 18, 2006
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
if nargin<2 || nargin>6
error('Incorrect number of inputs to arrow3D');
end
if numel(pos)~=3 || numel(deltaValues)~=3
error('pos and/or deltaValues is incorrect dimensions (should be three)');
end
if nargin<3
colorCode = 'interp';
end
if nargin<4
stemRatio = 0.75;
end
X = pos(1); %---- with this notation, there is no need to transpose if the user has chosen a row vs col vector
Y = pos(2);
Z = pos(3);
[sphi, stheta, srho] = cart2sph(deltaValues(1), deltaValues(2), deltaValues(3));
%******************************************* CYLINDER == STEM *********************************************
%cylinderRadius = 0.05*srho;
cylinderRadius = cylRad;
cylinderLength = srho*stemRatio;
[CX,CY,CZ] = cylinder(cylinderRadius);
CZ = CZ.*cylinderLength; %---- lengthen
%----- ROTATE CYLINDER
[row, col] = size(CX); %---- initial rotation to coincide with X-axis
newEll = rotatePoints([0 0 -1], [CX(:), CY(:), CZ(:)]); %CX(:) actually reshape the 2xN matrices in a 2N vert vector, by vertically concatenating each column
CX = reshape(newEll(:,1), row, col);
CY = reshape(newEll(:,2), row, col);
CZ = reshape(newEll(:,3), row, col);
[row, col] = size(CX);
newEll = rotatePoints(deltaValues, [CX(:), CY(:), CZ(:)]);
stemX = reshape(newEll(:,1), row, col);
stemY = reshape(newEll(:,2), row, col);
stemZ = reshape(newEll(:,3), row, col);
%----- TRANSLATE CYLINDER
stemX = stemX + X;
stemY = stemY + Y;
stemZ = stemZ + Z;
%******************************************* CONE == ARROWHEAD *********************************************
coneLength = srho*(1-stemRatio);
coneRadius = cylinderRadius*radRatioCone;
incr = 100; %---- Steps of cone increments
coneincr = coneRadius/incr;
[coneX, coneY, coneZ] = cylinder(cylinderRadius*2:-coneincr:0); %---------- CONE
coneZ = coneZ.*coneLength;
%----- ROTATE CONE
[row, col] = size(coneX);
newEll = rotatePoints([0 0 -1], [coneX(:), coneY(:), coneZ(:)]);
coneX = reshape(newEll(:,1), row, col);
coneY = reshape(newEll(:,2), row, col);
coneZ = reshape(newEll(:,3), row, col);
newEll = rotatePoints(deltaValues, [coneX(:), coneY(:), coneZ(:)]);
headX = reshape(newEll(:,1), row, col);
headY = reshape(newEll(:,2), row, col);
headZ = reshape(newEll(:,3), row, col);
%---- TRANSLATE CONE
V = [0, 0, srho*stemRatio]; %---- centerline for cylinder: the multiplier is to set the cone 'on the rim' of the cylinder
Vp = rotatePoints([0 0 -1], V);
Vp = rotatePoints(deltaValues, Vp);
headX = headX + Vp(1) + X;
headY = headY + Vp(2) + Y;
headZ = headZ + Vp(3) + Z;
%************************************************************************************************************
hStem = surf(stemX, stemY, stemZ, 'FaceColor', colorCode, 'EdgeColor', 'none');
hold on
hBottStem = fill3(stemX(1,:),stemY(1,:),stemZ(1,:), colorCode, 'EdgeColor', 'none');
hold on
hHead = surf(headX, headY, headZ, 'FaceColor', colorCode, 'EdgeColor', 'none');
hold on
hBottCone = fill3(headX(1,:),headY(1,:),headZ(1,:), colorCode, 'EdgeColor', 'none');
if nargout==1
arrowHandle = [hStem, hBottStem, hHead, hBottCone];
end
which itself uses that function rotatePoints.m :
function rotatedData = rotatePoints(alignmentVector, originalData)
% rotatedData = rotatePoints(alignmentVector, originalData) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Rotate the 'originalData' in the form of Nx2 or Nx3 about the origin by aligning the x-axis with the alignment vector
%
% Rdata = rotatePoints([1,2,-1], [Xpts(:), Ypts(:), Zpts(:)]) - rotate the (X,Y,Z)pts in 3D with respect to the vector [1,2,-1]
%
% Rotating using spherical components can be done by first converting using [dX,dY,dZ] = cart2sph(theta, phi, rho); alignmentVector = [dX,dY,dZ];
%
% Example:
% %% Rotate the point [3,4,-7] with respect to the following:
% %%%% Original associated vector is always [1,0,0]
% %%%% Calculate the appropriate rotation requested with respect to the x-axis. For example, if only a rotation about the z-axis is
% %%%% sought, alignmentVector = [2,1,0] %% Note that the z-component is zero
% rotData = rotatePoints(alignmentVector, [3,4,-7]);
%
% Author: Shawn Arseneau
% Created: Feb.2, 2006
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
alignmentDim = numel(alignmentVector); %number of elements in a matrix
DOF = size(originalData,2); %---- DOF = Degrees of Freedom (i.e. 2 for two dimensional and 3 for three dimensional data)
if alignmentDim~=DOF
error('Alignment vector does not agree with originalData dimensions');
end
if DOF<2 || DOF>3
error('rotatePoints only does rotation in two or three dimensions');
end
if DOF==2 % 2D rotation...
[rad_theta, rho] = cart2pol(alignmentVector(1), alignmentVector(2));
deg_theta = -1 * rad_theta * (180/pi);
ctheta = cosd(deg_theta); stheta = sind(deg_theta);
Rmatrix = [ctheta, -1.*stheta;...
stheta, ctheta];
rotatedData = originalData*Rmatrix;
%assumption: rotate all the datas from the original base to the
%base where the original x becomes alignmentVector
else % 3D rotation...
[rad_theta, rad_phi, rho] = cart2sph(alignmentVector(1), alignmentVector(2), alignmentVector(3));
rad_theta = rad_theta * -1;
deg_theta = rad_theta * (180/pi);
deg_phi = rad_phi * (180/pi);
ctheta = cosd(deg_theta); stheta = sind(deg_theta); %MM : is it more accurate??
Rz = [ctheta, -1.*stheta, 0;...
stheta, ctheta, 0;...
0, 0, 1]; %% First rotate as per theta around the Z axis
rotatedData = originalData*Rz;
[rotX, rotY, rotZ] = sph2cart(-1* (rad_theta+(pi/2)), 0, 1); %% Second rotation corresponding to phi
%assuming alignmentVector is the x for the new base, then the
%hereabove argument corresponds to the y (z inversed)
%the hereabove output = newX(in base 0) vectorial product -z(in base0)
rotationAxis = [rotX, rotY, rotZ];
u = rotationAxis(:)/norm(rotationAxis); %% Code extract from rotate.m from MATLAB
cosPhi = cosd(deg_phi);
sinPhi = sind(deg_phi);
invCosPhi = 1 - cosPhi;
x = u(1);
y = u(2);
z = u(3);
Rmatrix = [cosPhi+x^2*invCosPhi x*y*invCosPhi-z*sinPhi x*z*invCosPhi+y*sinPhi; ...
x*y*invCosPhi+z*sinPhi cosPhi+y^2*invCosPhi y*z*invCosPhi-x*sinPhi; ...
x*z*invCosPhi-y*sinPhi y*z*invCosPhi+x*sinPhi cosPhi+z^2*invCosPhi]';
rotatedData = rotatedData*Rmatrix;
end
I end up getting:
while I would like to conserve both intermediate plots containing the interp arrow:
and the text on flashy white background:
So there are actually two questions:
1) Why calling my text tick disables the interp effect (varying color from blue to yellow) ?
2) How can I keep the camlight without enlightening my tick box? (i.e while keeping its background white)
Basically one should only need to look at the two first snippets, the later 2 ones are useless for my issue.
By thanking you a lot!
Place it in another axes
As I said in comment, you have 2 graphic objects in the same axes which have to interpret their CData in a completely different manner.
The first options I looked for was to modify one of the arrow3d or rotateAxisTicks so their graphic objects would be "compatible" (in the way the color data are interpolated on an axes), but it would be quite intensive and the aspect of the 3d text would have to be constantly monitored/adjusted for any other change in the figure.
So the easiest option is a classic MATLAB hack ... place your graphic objects in different containers (different axes), then superimpose them on a figure, and match some properties (limits, view, etc ...) so they appear to be only one.
Here it goes:
%% Draw your main arrow in the main figure
mainfig = figure ;
ax1 = axes ;
arrow = arrow3D([0 0 0], [1 1 1], 'r', 0.8, 0.2, 1.5);
set(arrow, 'EdgeColor', 'interp', 'FaceColor', 'interp');
camlight headlight
%% Draw your text in a temporary figure
tempfig = figure ;
ax2 = axes ;
surfaceHandle = rotateAxisTicks('lol','r',10,-0.3,0.5,0.5,1,1,1,0);
camlight headlight
%material(surfaceHandle,'default') %doesn't work
%surfaceHandle1.FaceLighting = 'none' %doesn't work
%% Prepare and set matching limits
xl = [ax1.XLim ; ax2.XLim] ;
xl = [min(xl(:,1)) , max(xl(:,2))] ;
yl = [ax1.YLim ; ax2.YLim] ;
yl = [min(yl(:,1)) , max(yl(:,2))] ;
zl = [ax1.ZLim ; ax2.ZLim] ;
zl = [min(zl(:,1)) , max(zl(:,2))] ;
hax = [ax1;ax2] ;
set(hax,'XLim',xl,'YLim',yl,'ZLim',zl)
% Adjust the view to be sure
ax2.View = ax1.View ;
%% Remove secondary axes background, then move it to main figure
ax2.Visible = 'off' ;
ax2.Parent = mainfig ;
delete(tempfig)
%% link the view between axes
hl = linkprop( hax , 'View' ) ;
% or link even more properties at once
% hl = linkprop( hax , 'View' , 'XLim','YLim','ZLim') ;
Which gives you:
note: Your 3d arrow is also made up of 2 different graphic objects (2x surf and 2x patch). The 2 patches are not rendered when you set the interp mode. You should modify the arrow3d function to either (a) changes the patch objects to surf so everything is the same type and compatible, or (b) remove them completely from the function (if they are not rendered they are only annoying ... triggering warnings everywhere).
edit
And here is the modified code for arrow3d.m. I changed it so the output is now only one surface object, easier to assign properties and no danger of mismatch between patch and surf. I also simplified it, removed a few bits that were not necessary, and reduced the total number of points necessary for the surface.
With this you get the bottom of the stem and the under-cone:
function arrowHandle = arrow3D(pos, deltaValues, colorCode, stemRatio, cylRad )
% arrowHandle = arrow3D(pos, deltaValues, colorCode, stemRatio) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Used to plot a single 3D arrow with a cylindrical stem and cone arrowhead
% pos = [X,Y,Z] - spatial location of the starting point of the arrow (end of stem)
% deltaValues = [QX,QY,QZ] - delta parameters denoting the magnitude of the arrow along the x,y,z-axes (relative to 'pos')
% colorCode - Color parameters as per the 'surf' command. For example, 'r', 'red', [1 0 0] are all examples of a red-colored arrow
% stemRatio - The ratio of the length of the stem in proportion to the arrowhead. For example, a call of:
% arrow3D([0,0,0], [100,0,0] , 'r', 0.82) will produce a red arrow of magnitude 100, with the arrowstem spanning a distance
% of 82 (note 0.82 ratio of length 100) while the arrowhead (cone) spans 18.
%
% Example:
% arrow3D([0,0,0], [4,3,7]); %---- arrow with default parameters
% axis equal;
%
% Author: Shawn Arseneau
% Created: September 14, 2006
% Updated: September 18, 2006
%
% Updated: December 20, 2018
% Tlab - refactored to have only one surface object as ouput
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
if nargin<2 || nargin>6
error('Incorrect number of inputs to arrow3D');
end
if numel(pos)~=3 || numel(deltaValues)~=3
error('pos and/or deltaValues is incorrect dimensions (should be three)');
end
if nargin<3
colorCode = 'interp';
end
if nargin<4
stemRatio = 0.75;
end
Ncol = 21 ; % default number of column for the "cylinder.m" function
X = pos(1); %---- with this notation, there is no need to transpose if the user has chosen a row vs col vector
Y = pos(2);
Z = pos(3);
[~, ~, srho] = cart2sph(deltaValues(1), deltaValues(2), deltaValues(3));
%******************************************* CYLINDER == STEM *********************************************
cylinderRadius = cylRad;
cylinderLength = srho*stemRatio;
[CX,CY,CZ] = cylinder(cylinderRadius,Ncol-1);
CZ = CZ.*cylinderLength; %---- lengthen
%******************************************* CONE == ARROWHEAD *********************************************
coneLength = srho*(1-stemRatio);
[coneX, coneY, coneZ] = cylinder([cylinderRadius*2 0],Ncol-1); %---------- CONE
coneZ = coneZ.*coneLength;
% Translate cone on top of the stem cylinder
coneZ = coneZ + cylinderLength ;
% now close the bottom and add the cone to the stem cylinder surface
bottom = zeros(1,Ncol) ;
CX = [ bottom ; CX ; coneX ] ;
CY = [ bottom ; CY ; coneY ] ;
CZ = [ bottom ; CZ ; coneZ ] ;
Nrow = size(CX,1);
%----- ROTATE
%---- initial rotation to coincide with X-axis
newEll = rotatePoints([0 0 -1], [CX(:), CY(:), CZ(:)]); %CX(:) actually reshape the 2xN matrices in a 2N vert vector, by vertically concatenating each column
CX = reshape(newEll(:,1), Nrow, Ncol);
CY = reshape(newEll(:,2), Nrow, Ncol);
CZ = reshape(newEll(:,3), Nrow, Ncol);
newEll = rotatePoints(deltaValues, [CX(:), CY(:), CZ(:)]);
stemX = reshape(newEll(:,1), Nrow, Ncol);
stemY = reshape(newEll(:,2), Nrow, Ncol);
stemZ = reshape(newEll(:,3), Nrow, Ncol);
%----- TRANSLATE
stemX = stemX + X;
stemY = stemY + Y;
stemZ = stemZ + Z;
%----- DISPLAY
hStem = surf(stemX, stemY, stemZ, 'FaceColor', colorCode, 'EdgeColor', 'none');
%----- DISPLAY
if nargout==1
arrowHandle = hStem ;
end

MATLAB legend does not work for plotting 2 circles

close all; clc; clear all;
A0 = 1.5; % meters
lambda = 100 % meters
k = (2*pi)/lambda;
T = 3600 % Period in seconds
ome = 2*pi/T; % omega
x = 0; z = 0;
t = linspace(0,7200,100); % 2 periods, 100 data
zz=0;
for z = 0:20:20;
zz = zz+1;
% multiplied by 100, unit in cm/s
u= 100.*ome*A0*exp(-k*z)*sin(k*x - ome*t);
w = 100.*-ome*A0*exp(-k*z)*cos(k*x - ome*t);
uu(zz,:) = u; % size(uu) 2 100
ww(zz,:) = w; % size(ww) 2 100
end
figure(1)
color = -0.8;
for zz = 1:2
color = color + 0.8;
for i=1:3:49; % plot circle for one period
plot([uu(zz,i) uu(zz,i+3)],[ww(zz,i) ww(zz,i+3)], 'color',([color+0.2 0 0]), 'linewidth', 2)
hold on
end
end
title('Plot of lines from (0,0) to (u(i), v(i). Radius or amplitude in cm/s')
axis equal;
grid on;
legend('radius at surface','radius at depth 20')%
This script plots 2 circles: the small one is red, another is black. But the legend is not consistence with these circles.
this is because you create many line objects in your axes (each loop iteration when you do plot) and the legend function addresses these line objects. sp line1 and line2 are still part of the polygon you draw.
I'll answer your question, but know that your code is sub-optimal and that it is not the best way to draw 2 circles or polygons.
so with minimal change to your code this is what you can do:
....
figure(1)
color = -0.8;
for zz = 1:2
color = color + 0.8;
for i=1:3:49; % plot circle for one period
h(zz)=plot([uu(zz,i) uu(zz,i+3)],[ww(zz,i) ww(zz,i+3)], 'color',([color+0.2 0 0]), 'linewidth', 2)
hold on
end
end
title('Plot of lines from (0,0) to (u(i), v(i). Radius or amplitude in cm/s')
axis equal;
grid on;
legend([h(1) h(2)],{'radius at surface','radius at depth 20'});

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:

hough transform for lines

I'm trying to get a Hough transform to work in MATLAB, but I'm having problems. I have a really bad way of detecting peaks that needs to be fixed, but before that I need to be able to reverse the hough transform to create the lines again properly. This is the type of stuff I'm getting right now:
looks like its rotated by 90 degrees, but I'm not sure why. I'm not sure if it's my hough space that's wrong, or if it's the way I dehough and draw the lines. Also could someone help improve my peak detection?
the images used in the code are here
Thank you
%% load a sample image; convert to grayscale; convert to binary
%create 'x' image (works well)
a = eye(255);
b = flipud(eye(255));
x = a + b;
x(128,128) = 1;
%image = rgb2gray(imread('up.png')) < 255;
%image = rgb2gray(imread('hexagon.png')) < 255;
%image = rgb2gray(imread('traingle.png')) < 255;
%%% these work
%image = x;
%image = a;
image = b;
%% set up variables for hough transform
theta_sample_frequency = 0.01;
[x, y] = size(image);
rho_limit = norm([x y]);
rho = (-rho_limit:1:rho_limit);
theta = (0:theta_sample_frequency:pi);
num_thetas = numel(theta);
num_rhos = numel(rho);
hough_space = zeros(num_rhos, num_thetas);
%% perform hough transform
for xi = 1:x
for yj = 1:y
if image(xi, yj) == 1
for theta_index = 1:num_thetas
th = theta(theta_index);
r = xi * cos(th) + yj * sin(th);
rho_index = round(r + num_rhos/2);
hough_space(rho_index, theta_index) = ...
hough_space(rho_index, theta_index) + 1;
end
end
end
end
%% show hough transform
subplot(1,2,1);
imagesc(theta, rho, hough_space);
title('Hough Transform');
xlabel('Theta (radians)');
ylabel('Rho (pixels)');
colormap('gray');
%% detect peaks in hough transform
r = [];
c = [];
[max_in_col, row_number] = max(hough_space);
[rows, cols] = size(image);
difference = 25;
thresh = max(max(hough_space)) - difference;
for i = 1:size(max_in_col, 2)
if max_in_col(i) > thresh
c(end + 1) = i;
r(end + 1) = row_number(i);
end
end
%% plot all the detected peaks on hough transform image
hold on;
plot(theta(c), rho(r),'rx');
hold off;
%% plot the detected line superimposed on the original image
subplot(1,2,2)
imagesc(image);
colormap(gray);
hold on;
for i = 1:size(c,2)
th = theta(c(i));
rh = rho(r(i));
m = -(cos(th)/sin(th));
b = rh/sin(th);
x = 1:cols;
plot(x, m*x+b);
hold on;
end
Cross Posted:
https://dsp.stackexchange.com/questions/1958/help-understanding-hough-transform
If your regenerated image looks rotated by 90 degrees or otherwise flipped, it's likely because the plotting isn't happening as you expect. You can try axis ij; to move the origin of the plot and/or you can reverse your plot command:
plot(m*x+b, x);
As for peak detection, you might want to look at imregionalmax.