Source

ITE / code / shared / embedded / clinep / clinep.m

Full commit
% This function plots a 3D line (x,y,z) encoded with scalar color data (c).
% This function is an improvement over the CLINE function previously made
% available on TMW File Exchange.  Rather than using the LINE function a
% PATCH surface is generated.  This provides a way to change the
% colormapping because the surface patches use indexed colors rather than
% true colors.  Hence changing the COLORMAP or CAXIS of the figure will
% change the colormapping of the patch object.
%
% DEMO:  clinep;
%
% SYNTAX: h=clinep(x,y,z[,c,W]);
%
% INPUTS:
%   x - mx1 vector of x-position data
%   y - mx1 vector of y-position data
%   z - mx1 vector of z-position data
%
% -OPTIONAL INPUTS-
%
%   c - mx1 vector of index color-data (uses current colormap or DEFAULT)
%   W - 1x1 specifies the line thickness (DEFAULT is 3)
%
% OUTPUT:
%  
%   h - Graphics handle to the patch object.
%
% DBE 2005/09/29
%
% P.S.  The code is modified from code that generates a 3D tube, rather
% than a line, but that needs more work still.
%
%Modification (Zoltan Szabo, Sep. 2012): working environment specific cylinder.

function p=clinep(x,y,z,c,W);

if nargin==0  % Generate sample data...
  figure; axis off; axis equal;
    cameratoolbar('Show');
    cameratoolbar('SetMode','orbit','SetCoordSys','none');
  
  x=linspace(-1,1,100);
  y=sin(4*pi*x);
  z=cos(4*pi*x);
  c=sin(x);
  W=3;
  l=light; view(110,60); zoom(2);
elseif nargin<3
  error('Insufficient input arguments\n');
elseif nargin<4
  c=ones(size(x));
  W=3;
elseif nargin<5
  W=3;
end

% scl=100;
N=3;

% Create a unit disc...points lie in X-Y plane therefore have a Z-normal
 if working_environment_Matlab%Matlab
    [xc,yc,zc]=cylinder(0.00001,N); % The original function allowed you to specify N(=3) to generate a tube, and the radius(=0.01) was =1.
 else%Octave
     [xc,yc,zc]=cylinder([0.00001;0.00001],N);
 end
xc=xc(1,1:end-1);        % Only use first layer and remove replicated end point
yc=yc(1,1:end-1);
zc=zc(1,1:end-1);
Nz=[0 0 1];                  % Disc normal

xyz=[];
faces=[];
for k=1:length(x)
  % Determine the rotation between the unit disc normal and the local curves tangent
  if k==length(x)
    dl=[x(k)-x(k-1) y(k)-y(k-1) z(k)-z(k-1)];                       % Local curves tangent (at end point)
  else
    dl=[x(k+1)-x(k) y(k+1)-y(k) z(k+1)-z(k)];                       % Local curves tangent
  end
    dl=dl/norm(dl,2);                                               % Unit tangent vector
    alpha=acos(dot(Nz,dl));                                         % Angle between local curve tangent and disc normal
    R=RotMat(cross(Nz,dl),alpha);                                       % Rotation between them
    xyz=[xyz R*[xc(:)'; yc(:)'; zc(:)']+repmat([x(k) y(k) z(k)]',[1 N])]; % Rotate and translate the data
  
    if k<=length(x)-1
      faces=[faces; [(1:N)' ([2:N,1])' ([2:N,1])'+N (1:N)'+N]+N*(k-1)];
    end
end

vertices=xyz';

if isequal([1 3],size(c))
  fc=repmat(c ,[size(faces,1) 1]);
elseif isequal([3 1],size(c))
  fc=repmat(c',[size(faces,1) 1]);
else  
  fc=repmat(c(1:end),[N 1]); fc=fc(:);
end

p=patch('Vertices',vertices,'Faces',faces,'FaceVertexCData',fc,'FaceColor','Flat');
  set(p,'EdgeColor','Flat','LineWidth',W);

return

% This function generates a rotation matrix, R, for rotation about 
% the axis, ax, through an angle, alpha (radians).  
%
% SYNTAX: R=RotMat(ax,alpha)
%
% ax    - 1x3 Column vector
% alpha - 1xN or Nx1 vector of rotation angles
%
% DBE 08/28/01
function R=RotMat(ax,alpha)

sz=size(ax);
if sz(1)<sz(2)
  ax=ax';
end
ax=ax./norm(ax,2);   % Make sure it is a unit vector (normalize)

Wa=zeros(3,3); Wa(1,2)=-ax(3); Wa(1,3)=ax(2); Wa(2,1)=ax(3); Wa(2,3)=-ax(1); Wa(3,1)=-ax(2); Wa(3,2)=ax(1);

ident(1,1)=1; ident(2,2)=1; ident(3,3)=1;

ax_ax=ax*ax';
for i=1:length(alpha)
  cos_a=cos(alpha(i));
  sin_a=sin(alpha(i));
  R(:,:,i)=cos_a*ident+(1-cos_a)*ax_ax+sin_a*Wa;
end

return