Code covered by the BSD License  

Highlights from
Plot 3d vectors

image thumbnail
from Plot 3d vectors by Pirmin Borer
Plot real 3d arrows from .stl file. Similar to quiver

h=vector3d(X,Y,Z,U,V,W,varargin)
function h=vector3d(X,Y,Z,U,V,W,varargin)
%h=vector3d(X,Y,Z,U,V,W,'Property','Value',...)
%
% Plot 3d vectors (real 3d) from .stl file to specified location and
% direction. 
%
%basically same usage as quiver3. Property/value pairs are passed to patch.
%Some additional property/values are available:
%
%h=vector3d(...,'FileName',file)            : string arry with name of .stl file (for example 'arrow4.stl')
%h=vector3d(...,'Scale',[sx sy sz])         : scales along the x-axis by sx, along the y-axis by sy, and along the z-axis by sz.
%                                             If scalar, Vectors are scaled uniformly.
%h=vector3d(...,'MaxVert',nmax)             : Maximum number of vertices per vector. Lower this value if many vectors have to be plotted. Default is 200.
%h=vector3d(...,'Lighting','gouraud')       : Sets both, edge and face lighting. Default is flat lighting
%h=vector3d(...,'Color',rgb)                : Sets face and edge color to specified color (indexed or true rgb). 
%                                             When omitted the vector
%                                             length and current colormap
%                                             are used
%h=vector3d(...,'ColorMap',cmap)            : sets the colormap to cmap for plotting.
%                                             minimum (but non-zero) and maximum data are mapped to
%                                             the interval [0 1]. 
%
%h=vector3d(...,'LightDirection',[x y z])   : Adds a infinite light to the axes with specified position [x y z]
%
%Example:
%
%[X,Y,Z]=sphere(20);
%[U,V,W] = surfnorm(X,Y,Z);
%surf(X,Y,Z);
%hold on
%h=vector3d(X,Y,Z,U,V,W,'FileName','arrow2.stl','Scale',0.25,'Lighting',...
%'gouraud','ColorMap','jet','LightDirection',[-1 -1 1])

%-----------------default values----------------------------------
filename='arrow2.stl';
scalefactor=1;
color='flat';
lighting='flat';
cmap=[];
lightdir=[];
nmax=200;

%-------------------Parse inputs----------------------------------------
if ~any(size(X)==size(Y) & size(Y)==size(Z))
    error('Input arguments must be of same size');
end

ind=[];
for i=1:2:length(varargin)-1
    prop=varargin{i};
    val=varargin{i+1};
    switch prop
        case 'Lighting'
            lighting=val;
            ind=[ind i i+1];
        case 'ColorMap'
            cmap=val;
            color='flat';
            ind=[ind i i+1]; 
        case 'FileName'
            filename=val;
            ind=[ind i i+1];
        case 'LightDirection'
            lightdir=val;
            ind=[ind i i+1];
        case 'Scale'
            scalefactor=val;
            ind=[ind i i+1];
        case 'Color'
            color=val;
            ind=[ind i i+1];
        case 'MaxVert'
            nmax=val;
            ind=[ind i i+1];
    end
end
ind=ind(ind>0);
varargin(ind)=[];

%------------------read the stl file--------------------------------
fv=stlread(filename); %reads arrow stl file. the 3d object should be of unit length and z-oriented
if size(fv.vertices,1)>nmax
fv=reducepatch(fv,nmax);
end

%linearize
X=X(:);
Y=Y(:);
Z=Z(:);
U=U(:);
V=V(:);
W=W(:);


vec_norm=sqrt(U.^2+V.^2+W.^2); %norm of vectors
ind=(vec_norm==0); %indices where norm is zero
vec_norm(ind)=[];

X(ind)=[];
Y(ind)=[];
Z(ind)=[];
U(ind)=[];
V(ind)=[];
W(ind)=[];

max_norm=max(vec_norm); %maximum norm (used for colormap)
min_norm=min(vec_norm);

N=length(X); %number of vectors to be plotted


n=size(fv.vertices,1); %number of mesh vertices
nf=size(fv.faces,1);% number of mesh faces

fv2.vertices=zeros(n*N,3); %preallocate space for patch object
fv2.faces=zeros(N*size(fv.faces,1),size(fv.faces,2));
fv2.FaceVertexCData=zeros(n,1);


%---------------Main loop---------------------------------------------------

for i=1:N;
    
    ax_rot=cross([U(i); V(i); W(i)],[0;0;1]); %axis perpendicular to 

    if ax_rot(1)==0 && ax_rot(2)==0 && ax_rot(3)==0
        ax_rot=[1 0 0];
    end
     %norm of u,v,w vector
    theta=acos(dot([U(i); V(i); W(i)]/vec_norm(i),[0;0;1])); %angle between oz direction (arrow mesh) and vector to be plotted

    

    M1=makehgtform('scale',vec_norm(i).*scalefactor);
    M2=makehgtform('axisrotate',ax_rot,-theta);
    M3=makehgtform('translate',[X(i) Y(i) Z(i)]);

    pos=(M3*M2*M1*[fv.vertices';ones(1,size(fv.vertices,1))])'; %applying transforms
    pos(:,4)=[]; %last column is always one (affine transform)

    fv2.vertices((i-1)*n+1:i*n,:)=pos;
    fv2.faces((i-1)*nf+1:i*nf,:)=fv.faces+max(max(fv2.faces)); %increase vertex indexes

    fv2.FaceVertexCData((i-1)*n+1:i*n)=(vec_norm(i)-min_norm)/(max_norm-min_norm); %indexed color

    
end

h=patch(fv2,'FaceColor',color,'EdgeColor',color,'FaceLighting',lighting,'EdgeLighting',lighting,varargin{:});

if ~isempty(lightdir)
  if isnumeric(lightdir)
    light('Style','infinite','Position',lightdir);
  else
      camlight(lightdir)
  end
end

if ~isempty(cmap)
    colormap(cmap)
end

set(gcf,'Renderer','OpenGl')
set(gca,'CLim',[min(vec_norm) max(vec_norm)])


Contact us