| h=movsph(r,A,B,V,op1,ph)
|
function h=movsph(r,A,B,V,op1,ph)
% MOVSPH move sphere
% movsph(r,A,B,V,op1) creates a randomly coloured sphere with radius r and
% moves it from point A to point B with speed V.
%
%=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
% Parameters:
%
% r : Radius of sphere
%
% A : Two element vector specifying starting position of centre of sphere
%
% B : Two element vector specifying ending position of centre of sphere
%
% V : Speed of rotation
%
% op1: 1 -> Plot ground on which sphere moves and adjust axis
% 0 -> Only plot the sphere and move it (default)
%
% ph : Handle of previously created sphere (optional).
% If this value is granted, then the inputs (A) is ignored
%
% h : Handle of sphere
%
%=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
%
% The ball moves on the ground, specified by 0z. The code can manually
% adjusts axis limits and even plots the ground with use of op1.
%
% Example:
%
% % create sphere and move it from [0 0] to [15 30] with speed 25
% h=movsph(1,[0,0],[15,30],25,1);
%
% % move same sphere from its location to [1,1] with speed 10
% movsph(1,[rand,rand],[1,1],30,0,h);
%
% numandina@gmail.com
% Feb. 2009
%
% check inputs
if nargin < 5
op1=0;
elseif nargin < 6
ph=[];
end
if length(A)~=length(B) || length(A)~=2
error('movsph:lengths',...
['A and B both need to be two element vectors. ',...
'Please check input documentation.'])
end
% just to make sure (user should put this before calling
% the function)
hold on
if isempty(ph) % no handle of previous sphere present, create new sphere
% create unit sphere
[a,b,c]=sphere(25);
% adjust size of sphere my multiplying by the radius
% also, move sphere to starting position by adding
% and put sphere on the ground (0z) by adding r to z
h=surf(a.*r+A(1),b.*r+A(2),c.*r+r);
% give sphere a random colour
set(h,'facecolor','interp','edgecolor','interp')
colormap(rand(2,3).*.7+.3)
% get sphere colour data
s2=get(h,'cdata');
% take the sphere top and change its colour to something
s2(end-3:end,:)=repmat(.2,4,size(s2,2));
% take the rest of the sphere and give it a different number
s2(s2~=.2)=.4;
% now because of the interpolation of facecolor and randomization
% of the colormap, you'll get two different colours each time for
% both the sphere and its " top spot".
set(h,'cdata',s2)
else % if sphere was already created
% obtain its handle
h=ph;
% get sphere's current position
A=[(max(max(get(h,'xdata')))+min(min(get(h,'xdata'))))/2,...
(max(max(get(h,'ydata')))+min(min(get(h,'ydata'))))/2];
end
% the following are bonus lines of code that should have been applied
% by the user before calling this function
% the lines adjust the axis for proper viewing
% they are only performed if the input op1 is set to 1.
if op1
axis([min([A(1) B(1) A(2) B(2)]-r*7), max([A(1) B(1) A(2) B(2)]+r*7),...
min([A(1) B(1) A(2) B(2)]-r*7), max([A(1) B(1) A(2) B(2)]+r*7),...
-r*5, r*5])
axis equal
view(3)
rotate3d
xlabel('X')
ylabel('Y')
grid on
% plot destination point
plot3(B(1),B(2),r,'k.')
% for future reference
v=axis;
% create a patch that spans the axis edges (acts as ground)
% again, this is bonus code
aaa=[v(1) v(3) 0;
v(2) v(3) 0;
v(2) v(4) 0;
v(1) v(4) 0;
v(1) v(3) 0;
v(2) v(3) 0;
v(2) v(4) 0;
v(1) v(4) 0];
b=[1 2 6 5;2 3 7 6;3 4 8 7;4 1 5 8;1 2 3 4;5 6 7 8];
patch('vertices',aaa,'faces',b,'edgecolor',[1 1 1],'facecolor',[.3 .3 .3],...
'facevertexalphadata',0.5,'facealpha','flat');
end
% for future reference
v=axis;
% for while loop initial status
ctr=[1e9 1e9];
% while centre of the sphere is at least .1 away from the destination points
while mean(abs(ctr-B))>1e-1
% get centre of sphere
ctr=[(max(max(get(h,'xdata')))+min(min(get(h,'xdata'))))/2,...
(max(max(get(h,'ydata')))+min(min(get(h,'ydata'))))/2];
% vector from current point to destination
rot=B-ctr;
% get orthogonal vector (which the ball will spin around)
yu=rot(2);
rot(2)=rot(1);
rot(1)=-yu;
% rotate around sphere about said vector
% origin is centre of sphere
rotate(h,[rot,0],V,[ctr,r])
% move sphere according to its speed
% the sign commands are for the direction of movement
% the sphere moves in X and Y the same distance as the one it has rolled
% in other words it moves V/360
% but it doesn't move the entirety of this roll since it is divided between
% X and Y rolling, we find out how much is shared between X and Y using atan
set(h,'xdata',get(h,'xdata')...
-(sign(rot(1))-~sign(rot(1)))...
*V/360*...
atan(-rot(2)/rot(1)))
set(h,'ydata',get(h,'ydata')+(sign(rot(2))+sign(rot(2)))*V/360*atan(rot(1)/-rot(2)))
% so that axis wouldn't change while animating
axis(v)
% update plot
drawnow()
end
end
% EOF
|
|