Matlab 版 (精华区)
发信人: hanker (追梦人), 信区: Matlab
标 题: 画3d箭头程序(arrow3)
发信站: 哈工大紫丁香 (Mon Aug 18 17:12:43 2003)
function H=arrow3(p1,p2,s,w,h,ip,alpha,beta)
% ARROW3
% ARROW3(P1,P2) will draw vector lines (2D/3D) from P1 to P2 with
% arrowheads, where P1 and P2 can be either nx2 matrices (for 2D),
% or nx3 matrices (for 3D).
% ARROW3(P1,P2,S,W,H,IP,ALPHA,BETA) can be used to specify properties
% of the line and arrowhead. S is a character string made with one
% element from any or all of the following 3 columns:
% Usage Examples:
% % 2D vectors
% Arrow3([0 0],[1 3])
% Arrow3([0 0],[1 2],'-.e')
% Arrow3([0 0],[10 10],'--x2',1)
% Arrow3(zeros(10,2),50*rand(10,2),'x',1,3)
% Arrow3(zeros(10,2),[10*rand(10,1),500*rand(10,1)],'u')
% Arrow3(10*rand(10,2),50*rand(10,2),'x',1,[],1)
%
% % 3D vectors
% Arrow3([0 0 0],[1 1 1])
% Arrow3(zeros(20,3),50*rand(20,3),'--x1.5',2)
% Arrow3(zeros(100,3),50*rand(100,3),'x',1,3)
% Arrow3(zeros(10,3),[10*rand(10,1),500*rand(10,1),50*rand(10,1)],'a')
% Arrow3(10*rand(10,3),50*rand(10,3),'x',[],[],0)
%
% % Just for fun
% Arrow3(zeros(100,3),50*rand(100,3),'x',10,3,[],0.95)
% light('Position',[-10 -10 -10],'Style','local')
% light('Position',[60,60,60]), lighting gouraud
%
% % ColorOrder variable, color code prefixes, and Beta
% global ColorOrder, ColorOrder='^ui^e_hq^v';
% theta=[0:pi/22:pi/2]';
% Arrow3(zeros(12,2),[cos(theta),sin(theta)],'1.5o',0.1,[],[],[],0.5)
%
% % ColorOrder property, LineStyleOrder, LineWidthOrder, and Alpha
% global ColorOrder, ColorOrder=[];
% set(gca,'ColorOrder',[1,0,0;0,0,1;0.25,0.75,0.25;0,0,0])
% set(gca,'LineStyleOrder',{'-','--','-.',':'})
% global LineWidthOrder, LineWidthOrder=[1,2,4,8];
% w=[5,10,15,20]; h=[20,40,30,40]; alpha=[1,1,0.2,0.2];
% Arrow3(zeros(4,2),[10*rand(4,1),500*rand(4,1)],'o*/',w,h,10,alpha)
%
% % Log plot
% loglog([1e2,1e8],[1e-2,1e-1],'wo','MarkerSize',eps), hold on
% p1=repmat([1e3,2e-2],15,1);
% q1=[1e7,1e6,1e5,1e4,1e3,1e7,1e7,1e7,1e7,1e7,1e7,1e6,1e5,1e4,1e3];
% q2=1e-2*[9,9,9,9,9,7,5,4,3,2,1,1,1,1,1]; p2=[q1',q2'];
% global ColorOrder, ColorOrder=[];
% set(gca,'ColorOrder',rand(15,3))
% Arrow3(p1,p2,'o'), grid on, hold off
%
% % Color tables
% Arrow3('colors') % default color table
% Arrow3('colors',0.3) % low contrast color table
% Arrow3('colors',0.5) % high contrast color table
%
% % Update initial point markers and arrowheads
% Arrow3('update') % redraw same size
% Arrow3('update',2) % redraw double size
% Arrow3('update',0.5) % redraw half size
% Arrow3('update',[0.5,2,1]) % redraw W half size,
% % H double size, and
% % IP same size
%==========================================================================
% Error Checking
oldver=0; v=version; if v(1)<'6', oldver=1; end % matlab version
if nargin<8 | isempty(beta), beta=0.4; end, beta=abs(beta(1));
if strcmpi(p1,'colors') % plot color table
if nargin>1, beta=abs(p2(1)); end
LocalColorTable(1,beta); return
end
fig=gcf; ax=gca;
if strcmpi(p1,'update'), ud=get(ax,'UserData'); % update surfaces
if size(ud,2)<13, error('Invalid UserData'), end
set(ax,'UserData',[]); sf=[1,1,1];
if nargin>1, sf=p2(1)*sf; n=length(p2(:));
if n>1, sf(2)=p2(2); if n>2, sf(3)=p2(3); end, end
end
LocalUpdate(fig,ax,ud,sf); return
end
InputError=['Invalid input, type HELP ',upper(mfilename),...
' for usage examples'];
if nargin<2, error(InputError), end
[r1,c1]=size(p1); [r2,c2]=size(p2); n=r1; Zeros=zeros(n,1);
if c1<2 | c1>3, error(InputError), end
if r1~=r2, error('P1 and P2 must have same number of rows'), end
if c1~=c2, error('P1 and P2 must have same number of columns'), end
if c1==2, p1=[p1,Zeros]; p2=[p2,Zeros];
elseif ~any([p1(:,3);p2(:,3)]), c1=2; end
L=get(ax,'LineStyleOrder'); C=get(ax,'ColorOrder');
ST=get(ax,'DefaultSurfaceTag'); LT=get(ax,'DefaultLineTag');
EC=get(ax,'DefaultSurfaceEdgeColor');
if strcmp(get(ax,'nextplot'),'add') & strcmp(get(fig,'nextplot'),'add')
Xr=get(ax,'xlim'); Yr=get(ax,'ylim'); Zr=get(ax,'zlim');
set(ax,'XLimMode','auto','YLimMode','auto','ZLimMode','auto');
xs=strcmp(get(ax,'xscale'),'log');
ys=strcmp(get(ax,'yscale'),'log');
zs=strcmp(get(ax,'zscale'),'log');
if zs, error('Z log scale not supported'), end
xys=xs+ys; restore=1;
if xys & any([p1(:,3);p2(:,3)])
error('3D log plot not supported')
end
else, restore=0; cla; view(c1); xys=0;
set(fig,'nextplot','add'); set(ax,'UserData',[],'nextplot','add');
end
%==========================================================================
% Style Control
[vc,cn]=LocalColorTable(0); prefix=''; OneColor=0;
if nargin<3, [c,ls,lw]=LocalValidateCLSW; % default Color, LineStyle/Width
else,
[c,ls,lw]=LocalValidateCLSW(s);
if length(c)>1, if sum('_^'==c(1)), prefix=c(1); end, c=c(2); end
if c=='x', c=cn(randperm(23),:); % random named color (less white)
elseif c=='o', global ColorOrder % ColorOrder
if length(ColorOrder)
[c,failed]=LocalColorMap(lower(ColorOrder),vc,cn,beta);
if failed, warning(['Invalid ColorOrder variable, ',...
'current ColorOrder property will be used'])
else, C=c; end
end, c=C;
elseif ~sum(vc==c), c='k'; warning(['Invalid color switch, ',...
'default color (black) will be used'])
end
end
if length(c)==1 % single color
c=LocalColorMap([prefix,c],vc,cn,beta); OneColor=1;
end
set(ax,'ColorOrder',c); c=repmat(c,ceil(n/size(c,1)),1);
if ls~='*', set(ax,'LineStyleOrder',ls); end % LineStyleOrder
if lw=='/', global LineWidthOrder % LineWidthOrder
if length(LineWidthOrder)
lw=repmat(LineWidthOrder(:),ceil(n/length(LineWidthOrder)),1);
else, lw=0.5; warning(['Undefined LineWidthOrder, ',...
'default width (0.5) will be used'])
end
end
if nargin<7 | isempty(alpha), alpha=1; end
a=repmat(alpha(:),ceil(n/length(alpha)),1); % FaceAlpha
%==========================================================================
% Log Plot
if xys
units=get(ax,'units'); set(ax,'units','points');
pos=get(ax,'position'); set(ax,'units',units);
if strcmp(get(ax,'PlotBoxAspectRatioMode'),'auto')
set(ax,'PlotBoxAspectRatio',[pos(3),pos(4),1]);
end
par=get(ax,'PlotBoxAspectRatio');
set(ax,'DataAspectRatio',[par(2),par(1),par(3)]);
% map coordinates onto unit square
q=[p1;p2]; xr=Xr; yr=Yr;
if xs, xr=log10(xr); q(:,1)=log10(q(:,1)); end
if ys, yr=log10(yr); q(:,2)=log10(q(:,2)); end
q=q-repmat([xr(1),yr(1),0],2*n,1);
dx=xr(2)-xr(1); dy=yr(2)-yr(1);
q=q*diag([1/dx,1/dy,1]);
q1=q(1:n,:); q2=q(n+1:end,:);
else, xs=0; ys=0; dx=0; dy=0; xr=0; yr=0; end
%==========================================================================
% Line
set(ax,'DefaultLineTag','arrow3');
if length(lw)==1
if lw>0
if OneColor & ls~='*' % single color, linestyle, and linewidth
P=zeros(3*n,3); i=1:n;
P(3*i-2,:)=p1(i,:); P(3*i-1,:)=p2(i,:); P(3*i,1)=NaN;
H1=plot3(P(:,1),P(:,2),P(:,3),'LineWidth',lw);
else % single linewidth
H1=plot3([p1(:,1),p2(:,1)]',[p1(:,2),p2(:,2)]',...
[p1(:,3),p2(:,3)]','LineWidth',lw);
end
else, H1=[]; end
else % use LineWidthOrder
ls=repmat(cellstr(L),ceil(n/size(L,1)),1);
H1=Zeros;
for i=1:n
H1(i)=plot3([p1(i,1),p2(i,1)],[p1(i,2),p2(i,2)],[p1(i,3),p2(i,3)],...
ls{i},'Color',c(i,:),'LineWidth',lw(i));
end
end
%==========================================================================
% Scale
ar=get(ax,'DataAspectRatio'); ar=sqrt(3)*ar/norm(ar);
set(ax,'DataAspectRatioMode','manual');
if nargin<4 | isempty(w) % width
if xys, w=1;
else, xr=get(ax,'xlim'); yr=get(ax,'ylim'); zr=get(ax,'zlim');
w=norm([xr(2)-xr(1),yr(2)-yr(1),zr(2)-zr(1)])/72;
end
end
w=repmat(w(:),ceil(n/length(w)),1);
if nargin<5 | isempty(h), h=3*w; end % height
h=repmat(h(:),ceil(n/length(h)),1);
if nargin>5 & ~isempty(ip) % ip
i=find(ip==0); ip(i)=w(i);
ip=repmat(ip(:),ceil(n/length(ip)),1);
else, ip=-ones(n,1); end
%==========================================================================
% UserData
set(ax,'UserData',[get(ax,'UserData');...
p1,p2,c(1:n,:),w(1:n),h(1:n),ip(1:n),a]);
%==========================================================================
% Arrowhead
if xys, whip=[w,h,ip]*sqrt(2)/72;
w=whip(:,1); h=whip(:,2); ip=whip(:,3); p1=q1; p2=q2;
end
W=(p1-p2)./repmat(ar,n,1);
W=W./repmat(sqrt(sum(W.*W,2)),1,3); % new z direction
U=[-W(:,2),W(:,1),Zeros];
N=sqrt(sum(U.*U,2)); i=find(N<eps); j=length(i);
U(i,:)=repmat([1,0,0],j,1); N(i)=ones(j,1);
U=U./repmat(N,1,3); % new x direction
V=[W(:,2).*U(:,3)-W(:,3).*U(:,2),... % new y direction
W(:,3).*U(:,1)-W(:,1).*U(:,3),...
W(:,1).*U(:,2)-W(:,2).*U(:,1)];
m1=30; m2=10; num=200; % max, min grid spacing, and threshold
if n<num, m=round((m2-m1)*n/num+m1); % adjust grid spacing automatically
else m=m2; end % for speed when matrix size > num
set(ax,'DefaultSurfaceTag','arrow3','DefaultSurfaceEdgeColor','none');
[x,y,z]=cylinder([0,1],m);
G=surface(x/2,y/2,z); dar=diag(ar);
X=get(G,'XData'); Y=get(G,'YData'); Z=get(G,'ZData');
H2=Zeros; [j,k]=size(X);
for i=1:n % translate, rotate, and scale
H2(i)=copyobj(G,ax);
xyz=[w(i)*X(:),w(i)*Y(:),h(i)*Z(:)]*[U(i,:);V(i,:);W(i,:)]*dar;
x=reshape(xyz(:,1),j,k)+p2(i,1);
y=reshape(xyz(:,2),j,k)+p2(i,2);
z=reshape(xyz(:,3),j,k)+p2(i,3);
LocalSetSurface(xys,xs,ys,dx,dy,xr,yr,...
x,y,z,a(i),c(i,:),H2(i),oldver);
end, delete(G);
%==========================================================================
% Initial Point Marker
if any(ip>0)
[x,y,z]=sphere(m);
G=surface(x*ar(1)/2,y*ar(2)/2,z*ar(3)/2);
X=get(G,'XData'); Y=get(G,'YData'); Z=get(G,'ZData');
H3=zeros(n,1);
for i=1:n % translate
if ip(i)>0
H3(i)=copyobj(G,ax);
x=p1(i,1)+X*ip(i); y=p1(i,2)+Y*ip(i); z=p1(i,3)+Z*ip(i);
LocalSetSurface(xys,xs,ys,dx,dy,xr,yr,...
x,y,z,a(i),c(i,:),H3(i),oldver);
end
end, delete(G);
else, H3=[]; end
%==========================================================================
% Finish
if xys, xr=Xr; yr=Yr; zr=Zr;
set(ax,'DataAspectRatioMode','auto');
else, set(fig,'Renderer','OpenGL');
w=max(w)*ar/2; ip=max([ip;0])*ar/2;
xr=[min([p1(:,1)-ip(1);p2(:,1)-w(1)]),max([p1(:,1)+ip(1);p2(:,1)+w(1)])];
yr=[min([p1(:,2)-ip(2);p2(:,2)-w(2)]),max([p1(:,2)+ip(2);p2(:,2)+w(2)])];
zr=[min([p1(:,3)-ip(3);p2(:,3)-w(3)]),max([p1(:,3)+ip(3);p2(:,3)+w(3)])];
if restore
xr=[min(xr(1),Xr(1)),max(xr(2),Xr(2))];
yr=[min(yr(1),Yr(1)),max(yr(2),Yr(2))];
zr=[min(zr(1),Zr(1)),max(zr(2),Zr(2))];
else, set(ax,'nextplot','replace'); end
end
set(ax,'LineStyleOrder',L,'ColorOrder',C,'DefaultLineTag',LT,...
'DefaultSurfaceTag',ST,'DefaultSurfaceEdgeColor',EC,...
'xlim',xr,'ylim',yr,'zlim',zr);
if c1==3, set(ax,'CameraViewAngle',get(ax,'CameraViewAngle'),...
'PlotBoxAspectRatio',get(ax,'PlotBoxAspectRatio'));
end
if nargout, H=[H1(:);H2(:);H3(:)]; end
%==========================================================================
% Update
function LocalUpdate(fig,ax,ud,sf)
p1=ud(:,1:3); p2=ud(:,4:6); c=ud(:,7:9); a=ud(:,13);
w=sf(1)*ud(:,10); h=sf(2)*ud(:,11); ip=sf(3)*ud(:,12);
H=get(ax,'children'); tag=get(H,'tag'); type=get(H,'type');
delete(H(strcmp(tag,'arrow3') & strcmp(type,'surface')));
set(fig,'nextplot','add'); set(ax,'ColorOrder',c,'nextplot','add');
global ColorOrder, ColorOrder=[]; arrow3(p1,p2,'o0',w,h,ip,a);
%==========================================================================
% SetSurface
function LocalSetSurface(xys,xs,ys,dx,dy,xr,yr,x,y,z,a,c,H,oldver)
if xys
x=x*dx+xr(1); y=y*dy+yr(1);
if xs, x=10.^x; end
if ys, y=10.^y; end
end
if oldver
set(H,'XData',x,'YData',y,'ZData',z,'FaceColor',c);
else
set(H,'XData',x,'YData',y,'ZData',z,'FaceAlpha',a,'FaceColor',c);
end
%==========================================================================
% ColorTable
function [vc,cn]=LocalColorTable(n,beta)
vc='kymcrgbadefhijlnpqstuvzw'; % valid color codes
% k y m c
cn=[0.00,0.00,0.00; 1.00,1.00,0.00; 1.00,0.00,1.00; 0.00,1.00,1.00;
% r g b a
1.00,0.00,0.00; 0.00,1.00,0.00; 0.00,0.00,1.00; 0.00,0.70,0.00;
% d e f h
0.40,0.40,0.40; 0.00,0.40,0.00; 0.90,0.00,0.40; 1.00,0.80,0.00;
% i j l n
0.00,0.00,0.70; 0.20,0.80,0.50; 0.80,0.40,0.80; 0.50,0.20,0.00;
% p q s t
1.00,0.40,0.60; 1.00,0.40,0.00; 0.00,0.80,1.00; 0.80,0.40,0.00;
% u v z w
0.70,0.00,0.00; 0.60,0.00,1.00; 0.60,0.60,0.60; 1.00,1.00,1.00;];
if n % plot color table
name={'black','yellow','magenta','cyan',...
'red','green','blue','apple green',...
'dark gray','evergreen','fuchsia','honey',...
'indigo','jade','lilac','nutbrown',...
'pink','kumquat','sky blue','tan',...
'umber','violet','zinc','white'};
c=['yhtn';'gjae';'csbi';'plmv';'frqu';'wzdk'];
clf, set(gcf,'DefaultAxesXTick',[],'DefaultAxesYTick',[],...
'DefaultAxesXTickLabel',[],'DefaultAxesYTickLabel',[],...
'DefaultAxesXLim',[0,0.75],'DefaultAxesYLim',[0,0.75],...
'DefaultRectangleEdgeColor','none');
for i=1:24
subplot(4,6,i); j=find(vc==c(i)); title(name{j});
dark=LocalBrighten(cn(j,:),-beta);
light=LocalBrighten(cn(j,:),beta);
rectangle('Position',[0,0.00,0.75,0.25],'FaceColor',dark);
rectangle('Position',[0,0.25,0.75,0.25],'FaceColor',cn(j,:));
rectangle('Position',[0,0.50,0.75,0.25],'FaceColor',light);
rectangle('Position',[0,0.00,0.75,0.75],'EdgeColor','k');
if rem(i,6)==1
set(gca,'YTickLabel',{'dark','normal','light'},...
'YTick',[0.125,0.375,0.625]);
if i==19
text(0,-0.25,['{\bf\itARROW3} Named Color Table ',...
'( \beta = ',num2str(beta),' )']);
end
end
end
end
%==========================================================================
% ColorMap
function [C,failed]=LocalColorMap(c,vc,cn,beta)
n=length(c); failed=0; C=zeros(n,3); i=1; j=1;
while 1
if isempty(find([vc,'_^']==c(i))), failed=1; break, end
if sum('_^'==c(i))
if i+1>n, failed=1; break, end
if ~sum(vc==c(i+1)), failed=1; break, end
cc=cn(find(vc==c(i+1)),:); gamma=beta;
if c(i)=='_', gamma=-beta; end
C(j,:)=LocalBrighten(cc,gamma); i=i+2;
else, C(j,:)=cn(find(vc==c(i)),:); i=i+1; end
if i>n, break, end, j=j+1;
end, if n>j, C(j+1:n,:)=[]; end
%==========================================================================
% Brighten
function C=LocalBrighten(c,beta)
C=c.^((1-min(1-sqrt(eps),abs(beta)))^sign(beta));
%==========================================================================
% Generate valid value for color, linestyle and linewidth
function [c,ls,lw]=LocalValidateCLSW(s)
if nargin<1, c='k'; ls='-'; lw=0.5;
else
% identify linestyle
if findstr(s,'--'), ls='--'; s=strrep(s,'--','');
elseif findstr(s,'-.'), ls='-.'; s=strrep(s,'-.','');
elseif findstr(s,'-'), ls='-'; s=strrep(s,'-','');
elseif findstr(s,':'), ls=':'; s=strrep(s,':','');
elseif findstr(s,'*'), ls='*'; s=strrep(s,'*','');
else, ls='-'; end
% identify linewidth
tmp=double(s);
tmp=find(tmp>45 & tmp<57);
if length(tmp)
if any(s(tmp)=='/'), lw='/'; else, lw=str2num(s(tmp)); end
s(tmp)='';
else, lw=0.5; end
% identify color
if length(s), s=lower(s);
if length(s)>1, c=s(1:2);
else, c=s(1); end
else, c='k'; end
end
--
~~
*~-~*_hanker
※ 来源:.哈工大紫丁香 bbs.hit.edu.cn [FROM: 210.21.220.189]
Powered by KBS BBS 2.0 (http://dev.kcn.cn)
页面执行时间:204.820毫秒