Keep tracking the center of a ball with positional updates - matlab

In the code below, I am attempting to move a ball from 90 degrees to 44 degrees and back to 90 degrees. I wanted to be able to track the position of the ball's center point. I am trying to do this by plotting a marker that follows the ball. I would also like to keep seeing the (x,y) position of the ball being updated as the ball moves.
Can you help me modify my code so that:
1. The marker remains in the center of the ball, and
2. Keep displaying the (x,y) position of the marker (ball's center) as it moves?
Here is what I have done so far:
close all; clc; clear;
% Define position of arm
theta=0:10:360; %theta is spaced around a circle (0 to 360).
r=0.04; %The radius of our circle.
%Define a circular magenta patch.
x=r*cosd(theta) + 0.075;
y=r*sind(theta) + 1;
% Size figure and draw arms
figure('position', [800, 300, 600, 550]);
point = plot(0.075,1, 'bo', 'markers', 3);
hold on
myShape2=patch(x,y,'m');
set(myShape2,'Xdata',x,'Ydata',y);
axis([-1.5 3 -1 3]); grid on;
n = 1;
T=0.15; %Delay between images
for theta = pi/2:-pi/90:0,
if theta >= pi/4;
theta = theta;
else
theta = pi/2 - theta;
end
Arot = [sin(theta) cos(theta); -cos(theta) sin(theta)];
xyRot = Arot * [x; y]; % rotates the points by theta
xyTrans = xyRot;
point = plot(xyTrans(1, n),xyTrans(2, n), 'bo', 'markers', 3);
hold on;
set(myShape2,'Xdata',(xyTrans(1, :)),'Ydata',(xyTrans(2, :)));
pause(T); %Wait T seconds
end
Thanks for your time and help!

close all; clc; clear;
% Define position of arm
theta=0:10:360; %theta is spaced around a circle (0 to 360).
r=0.04; %The radius of our circle.
%Define a circular magenta patch.
x=r*cosd(theta) + 0.075;
y=r*sind(theta) + 1;
% Size figure and draw arms
figure('position', [800, 300, 600, 550]);
hold on
myShape2=patch(x,y,'m');
set(myShape2,'Xdata',x,'Ydata',y);
point = plot(0.075,1, 'bo', 'markers', 1);
dim = [.2 .5 .3 .3];
axis([-1.5 3 -1 3]); grid on;
T=0.15;
% Create annotation object to display object center
ano = annotation('textbox',dim,'String',['center position: (','0.075, 1'],'FitBoxToText','on');
for theta = pi/2:-pi/90:0,
if theta >= pi/4;
theta = theta;
else
theta = pi/2 - theta;
end
Arot = [sin(theta) cos(theta); -cos(theta) sin(theta)];
xyTrans = Arot * [x; y];
% Remove plot and annotation object from previous frame
delete(point)
delete(ano)
set(myShape2,'Xdata',(xyTrans(1, :)),'Ydata',(xyTrans(2, :)));
% Calculate the center of the patch as mean x and y position
x_pos = mean(xyTrans(1, :));
y_pos = mean(xyTrans(2, :));
point = plot(x_pos, y_pos, 'bo', 'markers', 1);
ano = annotation('textbox',dim,'String',['center position: (',sprintf('%0.3f', x_pos),', ',...
sprintf('%0.3f', y_pos),')'],'FitBoxToText','on');
axis([-1.5 3 -1 3]); grid on;
pause(T);
end

Related

(Satellite on orbit) - Create the tangent cone from point to sphere

I am trying to draw a cone, connected to the sphere in Matlab. I have the point [x1,y1,z1] outside of the sphere [x2,y2,z2] with R radius and I want it to be the top of the cone, created out of tangents.
On this pictures you can see what I have in mind:
Below you can see what I have already done. I am using it in order to mark the part of the Earth's surface, visible from the satellite position in orbit. Unfortunately, the cone in this picture is approximate, I need to create accurate one, connected with surface. For now, it is not only inaccurate, but also goes under it.
I am creating the sphere with this simple code (I am skipping the part of putting the map on it, it's just an image):
r = 6371.0087714;
[X,Y,Z] = sphere(50);
X2 = X * r;
Y2 = Y * r;
Z2 = Z * r;
surf(X2,Y2,Z2)
props.FaceColor= 'texture';
props.EdgeColor = 'none';
props.FaceLighting = 'phong';
figure();
globe = surface(X2,Y2,Z2,props);
Let's assume that I have the single point in 3D:
plot3(0,0,7000,'o');
How can I create such a cone?
There are two different questions here:
How to calculate cone dimensions?
How to plot lateral faces of a 3D cone?
Calculating Cone Dimensions
Assuming that center of sphere is located on [0 0 0]:
d = sqrt(Ax^2+Ay^2+Az^2);
l = sqrt(d^2-rs^2);
t = asin(rs/d);
h = l * cos(t);
rc = l * sin(t);
Plotting the Cone
The following function returns coordinates of lateral faces of cone with give apex point, axis direction, base radius and height, and the number of lateral faces.
function [X, Y, Z] = cone3(A, V, r, h, n)
% A: apex, [x y z]
% V: axis direction, [x y z]
% r: radius, scalar
% h: height, scalar
% n: number of lateral surfaces, integer
% X, Y, Z: coordinates of lateral points of the cone, all (n+1) by 2. You draw the sphere with surf(X,Y,Z) or mesh(X,Y,Z)
v1 = V./norm(V);
B = h*v1+A;
v23 = null(v1);
th = linspace(0, 2*pi, n+1);
P = r*(v23(:,1)*cos(th)+v23(:,2)*sin(th));
P = bsxfun(#plus, P', B);
zr = zeros(n+1, 1);
X = [A(1)+zr P(:, 1)];
Y = [A(2)+zr P(:, 2)];
Z = [A(3)+zr P(:, 3)];
end
The Results
rs = 6371.0087714; % globe radius
A = rs * 2 * [1 1 1]; % sattelite location
V = -A; % vector from sat to the globe center
% calculating cone dimensions
d = norm(A); % distance from cone apex to sphere center
l = (d^2-rs^2)^.5; % length of generating line of cone
sint = rs/d; % sine of half of apperture
cost = l/d; % cosine of half of apperture
h = l * cost; % cone height
rc = l * sint; % cone radius
% globe surface points
[XS,YS,ZS] = sphere(32);
% cone surface points
[XC, YC, ZC] = cone3(A, V, rc, h, 32);
% plotting results
hold on
surf(XS*rs,YS*rs,ZS*rs, 'facecolor', 'b', 'facealpha', 0.5, 'edgealpha', 0.5)
surf(XC, YC, ZC, 'facecolor', 'r', 'facealpha', 0.5, 'edgealpha', 0.5);
axis equal
grid on
Animating the satellite
The simplest way to animate objects is to clear the whole figure by clf and plot objects again in new positions. But a way more efficient method is to plot all objects once and in each frame, only update positioning data of moving objects:
clc; close all; clc
rs = 6371.0087714; % globe radius
r = rs * 1.2;
n = 121;
t = linspace(0, 2*pi, n)';
% point on orbit
Ai = [r.*cos(t) r.*sin(t) zeros(n, 1)];
[XS,YS,ZS] = sphere(32);
surf(XS*rs,YS*rs,ZS*rs, 'facecolor', 'b', 'facealpha', 0.5, 'edgealpha', 0.5)
hold on
[XC, YC, ZC] = cone3(Ai(1, :), Ai(1, :), 1, 1, 32);
% plot a cone and store handel of surf object
hS = surf(XC, YC, ZC, 'facecolor', 'r', 'facealpha', 0.5, 'edgealpha', 0.5);
for i=1:n
% calculating new point coordinates of cone
A = Ai(i, :);
V = -A;
d = norm(A);
l = (d^2-rs^2)^.5;
sint = rs/d;
cost = l/d;
h = l * cost;
rc = l * sint;
[XC, YC, ZC] = cone3(A, V, rc, h, 32);
% updating surf object
set(hS, 'xdata', XC, 'ydata', YC, 'zdata', ZC);
pause(0.01); % wait 0.01 seconds
drawnow(); % repaint figure
end
Another sample with 3 orbiting satellites:

how to move circle using plot in Matlab

I'd like to draw a circle and move it in Matlab plot figure.
I'm using
viscircles([8.1, 8.5], 1);
to draw circles. How do I call this again to draw a new circle and delete the original circle? Also is there a way I can use
drawnow
function to do this?
Instead of removing and redrawing, just move the circle by introducing some constant in the X and Y data.
%%%%Borrowing some code from irreducible's answer%%%%
xc=1; yc=2; r=3;
th = 0:pi/50:2*pi;
x = r * cos(th) + xc;
y = r * sin(th) + yc;
h = plot(x, y);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
axis([-20 20 -20 20]); %Fixing axis limits
for k=1:20 %A loop to visualise new shifted circles
h.XData = x + randi([-10 10],1); %Adding a constant in the x data
h.YData = y + randi([-10 10],1); %Adding a constant in the y data
pause(0.5); %Pausing for some time just for convenient visualisation
end
One possibility is to create your own circle function which returns the plot handle:
function h = my_circle(xc,yc,r)
% xc x-center of circle
% yc y-center of circle
% r radius
th = 0:pi/50:2*pi;
x = r * cos(th) + xc;
y = r * sin(th) + yc;
hold on
h = plot(x, y);
hold off;
Once having this you can plot your circle
h = my_circle(1,2,3);
and delete it if you dont need it anymore:
delete(h)
Afterwards you can plot a new one:
h2 = my_circle(1,2,4);

How do i obtain a cross section from a 3D volume?

I want to obtain a 2D slice from the 3D volume in the example (slightly modified) How do I resolve this issue with 3D image visualization? as follows:
% create input image
imageSizeX = 10;
imageSizeY = 10;
imageSizeZ = 10
% generate 3D grid using voxel size = 0.5
[Xq, Yq, Zq] = ndgrid(1:0.5:imageSizeX-1, 1:0.5:imageSizeY-1, 1:0.5:imageSizeZ-1);
% obtain coordinates of all internal vertices, faces, and edges
allCoords = [Xq(:), Yq(:), Zq(:)]; % i need this bit for something very important but not shown in the question.
% Re-generate 3D grid using voxel size = 1
[columnsInImage, rowsInImage, pagesInImage] = ndgrid(1: imageSizeX-1, 1: imageSizeY-1, 1: imageSizeZ-1);
% create the sphere in the image.
centerY = imageSizeY/2;
centerX = imageSizeX/2;
centerZ = imageSizeZ/2;
diameter = 4;
radius = diameter/2;
sphereVoxels = flipud((rowsInImage - centerY).^2 ...
+ (columnsInImage - centerX).^2 + (pagesInImage - centerZ).^2 <= radius.^2);
% change image from logical to numeric labels.
Img = double(sphereVoxels);
for ii = 1:numel(Img)
if Img(ii) == 0
Img(ii) = 2; % intermediate phase voxels
end
end
% specify the desired angle
angle = 30;
% specify desired pixel height and width of solid
width = imageSizeX;
height = imageSizeY;
page = imageSizeZ;
% Find the row point at which theta will be created
y = centerY - ( radius*cos(angle * pi/180) )
% determine top of the solid bar
y0 = max(1, y-height);
% label everything from y0 to y to be = 3 (solid)
Img(1:width, y0:y, 1:page)=3;
%%%%%% Plot the surfaces
[X, Y, Z, C] = build_voxels(Img > 0);
hSurface = patch(X, Y, Z, Img(C),...
'AmbientStrength', 0.5, ...
'BackFaceLighting', 'unlit', ...
'EdgeColor', 'none', ...
'FaceLighting', 'flat');
colormap([1 0 0; 1 1 0]);
axis equal;
axis tight;
view(45, 45);
grid on;
xlabel('x-axis (voxels)');
ylabel('y-axis (voxels)');
zlabel('z-axis (voxels)');
light('Position', get(gca, 'CameraPosition'), 'Style', 'local');
zoom on;
hold on;
Vq = griddata(columnsInImage, rowsInImage, pagesInImage, Img, Xq, Yq, Zq);
figure
h1 = slice(permute(Xq, [2 1 3]),permute(Yq, [2 1 3]),permute(Zq, [2 1 3]), Vq, 5,2,5);
When i run the code, i get an Error message:
"The number of data point locations should equal the number of data point values.
Error in griddata>useScatteredInterp (line 188)
F = scatteredInterpolant(inargs{1}(:),inargs{2}(:),inargs{3}(:), ..."
I want to believe this is so because the size of columnsInImage and size of pagesInImage are not equal to size(P,1) and size(P,3), respectively.
Nonetheless, I also tried to use a vector as follows:
figure
h1 = slice(Img(:,1), Img(:,2), Img(:,3), Img, 5,2,5);
I however still end up with the error message:
"Error using griddedInterpolant
The grid was created from grid vectors that were not strictly monotonic increasing.
Error in interp3 (line 142)
F = griddedInterpolant(X, Y, Z, V, method,extrap);"
Please, guys i need suggestions/ideas on how i could remedy these. Many thanks in advance!..

Showing angles around plot in matlab / octave

I can create a plot with pol2cart but how can I get the angles to show up at the end off the lines? See code below:
hold on ;
for angle = 0:20:(360-20)
[x1,y1] = pol2cart( angle / 180 * pi , [0 2]);
plot(x1,y1,'r')
end
for rho = 0:0.1:2
[x1,y1] = pol2cart( 0:0.01:2*pi , rho);
plot(x1,y1,'b')
end
axis equal
I'm trying to get the angle increments to show up all around see image below.
Please note I didn't draw all the numbered angles just the first couple to show what I'm trying to do
PS: I'm using octave 3.8.1 which tries to use the same language syntax as matlab
You could do something like
step = 20;
r= 2.2;
for idx = 0:step:360-step
text(r*cos(pi*idx/180),r*sin(pi*idx/180),num2str(idx), ...
'HorizontalAlignment','center', 'color',[1 .5 0])
end
For a better fit, include
axis(1.05*[-r r -r r])
axis equal
(This works for MATLAB, I dont know if the syntax is exactly the same in Octave.)
Here's the information and plot animated
%polar_chart_with_angles and there opposites
clear all, clc, clf
%find how many angles to make one full cycleremeber to divide by two if using stereo signal 180 out of phase
incr=72;
angle_wanted=incr;
n = lcm(360, 180 - angle_wanted) / (180 - angle_wanted)
angle_div=[0:incr:incr*n] %angle divsions
angle_div_mod=mod(angle_div,360) %angle divsions mod into 360
angle_div_mod_opp=mod(angle_div+180,360) %oppsite angle divsions mod into 360
%for circles
r= 2.2;
for rho = 0:0.1:2
[x1,y1] = pol2cart( 0:0.01:2*pi , rho);
plot(x1,y1,'b')
axis(1.10*[-r r -r r])
axis equal
hold on;
end
%for orig angles
for ii=1:n
angle=angle_div(ii)
[x1,y1] = pol2cart( angle / 180 * pi , [0 2]);
plot(x1,y1,'r')
hold on;
title_h=title(['Norig= ', int2str(ii)]);
%title_h = title('This is the title');
set(title_h, 'Position', [0.5, 0.02],'VerticalAlignment', 'bottom', 'HorizontalAlignment', 'left')
%%for creating orig angles
idx=angle_div_mod(ii);
text(r*cos(pi*idx/180),r*sin(pi*idx/180),num2str(idx), 'HorizontalAlignment','center', 'color',[1 .5 0])
pause (.1)
end
%for oppsite angles
for ii=1:n
angle_opp=angle_div_mod_opp(ii)
[x1,y1] = pol2cart( angle_opp/ 180 * pi , [0 2]);
plot(x1,y1,'g')
hold on;
title(['Nopp= ', int2str(ii)]);
%for creating oppsite angles
idx=angle_div_mod_opp(ii);
text(r*cos(pi*idx/180),r*sin(pi*idx/180),num2str(idx), 'HorizontalAlignment','center', 'color',[.5 .7 .7])
pause (.1)
end

MATLAB Rotate and move 2d object in the same time

I made star using this code:
t = 0:4/5*pi:4*pi;
x = sin(t);
y = cos(t);
star = plot(x, y);
axis([-1 11 -1 11])
Now I need to rotate and move this star at the same time. I tried this:
for i=1:0.1:10;
zAxis = [0 0 1];
center = [0 0 0];
rotate(star, zAxis, 5, center);
x = x+0.1;
y = y+0.1;
set(star, 'x', x, 'y', y);
pause(0.1);
end
But this code only moves star and doesn't rotate it. If I delete "set" command then it rotates. How can I combine those two actions?
This can do the job..
t = 0:4/5*pi:4*pi;
x = sin(t);
y = cos(t) ;
y = y-mean(y);
x = x-mean(x); % # barycentric coordinates
% # rotation and translation
trasl = #(dx,dy) [dy; dx]; % # this vector will be rigidly added to each point of the system
rot = #(theta) [cos(theta) -sin(theta); sin(theta) cos(theta)]; % # this will provide rotation of angle theta
for i = 1:50
% # application of the roto-translation
% # a diagonal translation of x = i*.1 , y = i*.1 is added to the star
% # once a rotation of angle i*pi/50 is performed
x_t = bsxfun(#plus,rot(i*pi/50)*([x;y]), trasl(i*.1,i*.1) );
star = plot(x_t(1,:), x_t(2,:));
axis([-1 11 -1 11])
pause(.1)
end
In principle, homogeneous coordinates (in this case in the 2D projective space) allow one to do the same job in a neater way; in fact, they would allow one to use just one linear operator (3x3 matrix).
Homogeneous coordinates version:
Op = #(theta,dx,dy) [ rot(theta) , trasl(dx,dy) ; 0 0 1];
for i = 1:50
x_t = Op(i*pi/50,i*.1,i*.1)*[x;y;ones(size(x))];
star = plot(x_t(1,:), x_t(2,:));
axis([-1 11 -1 11])
pause(.1)
end
You can just use a rotation matrix to compute the correct transformation on the vectors [x; y]:
theta = 5 * (pi / 180); % 5 deg in radians
Arot = [cos(theta) -sin(theta); sin(theta) cos(theta)];
xyRot = Arot * [x; y]; % rotates the points by theta
xyTrans = xyRot + 0.1; % translates all points by 0.1
set(star, 'x', xyTrans(1, :), 'y', xyTrans(2, :));