% CHULL_TREE Convex hull around whole or part of a tree.
% (trees package)
%
% [HP hull] = chull_tree (intree, ipart, color, DD, alpha, options)
% -----------------------------------------------------------------
%
% plots a convex hull around indexed nodes (ipart) of a tree. If tree is
% 100% flat 3D convex hull doesn't work. If selected nodes are 2 draw a
% straight line. If selected nodes are 1 plot a point.
%
% Input
% -----
% - intree::integer:index of tree in trees or structured tree
% alternatively, intree can be a Nx3 matrix XYZ of points
% - ipart::index:index to the subpart to be convex hulled {DEFAULT: all nodes}
% (needs to be real index values not logical subset)
% - color::RGB 3-tupel: RGB values {DEFAULT black [0 0 0]}
% - DD:: XY-tupel or XYZ-tupel: coordinates offset {DEFAULT no offset [0,0,0]}
% - alpha::value:transparency value for the patch {DEFAULT 0.2}
% - options::string: {DEFAULT ''}
% '-2d': 2D
%
% Output
% ------
% - HP::handles: depending on options HP links to the graphical objects.
% - hull::convex polygon: hull.XY(Z) - X Y (Z) coordinates
% hull.ch - index to convex hull
%
% Example
% -------
% chull_tree (sample_tree)
% chull_tree (sample_tree, find (sub_tree (sample_tree, 166)), [1 0 0], 20, 1, '-2d'); shine
% plot_tree (sample_tree) % plot tree as a comparison
%
% See also dhull_tree, hull2d_tree, vhull_tree and vhull2d_tree.
% Uses cyl ver X Y Z
%
% the TREES toolbox: edit, visualize and analyze neuronal trees
% Copyright (C) 2009 Hermann Cuntz
function [HP hull] = chull_tree (intree, ipart, color, DD, alpha, options)
% trees : contains the tree structures in the trees package
global trees
if (nargin < 1)||isempty(intree),
intree = length (trees); % {DEFAULT tree: last tree in trees cell array}
end;
% use only node position for this function
if isnumeric(intree) && numel(intree)>1,
X = intree (:, 1);
Y = intree (:, 2);
Z = intree (:, 3);
else
ver_tree (intree); % verify that input is a tree structure
if ~isstruct (intree),
X = trees {intree}.X;
Y = trees {intree}.Y;
Z = trees {intree}.Z;
else
X = intree.X;
Y = intree.Y;
Z = intree.Z;
end
end
if (nargin <2 )||isempty(ipart),
ipart = (1 : length (X))'; % {DEFAULT index: select all nodes/points}
end
if (nargin < 3)||isempty(color),
color = [0 0 0]; % {DEFAULT color: black}
end
if (nargin <4)||isempty(DD),
DD = [0 0 0]; % {DEFAULT 3-tupel: no spatial displacement from the root}
end
if length(DD)<3,
DD = [DD zeros(1, 3-length (DD))]; % append 3-tupel with zeros
end
if (nargin <5)||isempty(alpha),
alpha = 0.2; % {DEFAULT value: quite a bit transparent}
end
if (nargin <6)||isempty(options),
options = ''; % {DEFAULT: no option}
end
% this is basically simple patching the output of convhull
if strfind (options, '-2d')
if length (ipart) > 2,
ch = convhull (X (ipart), Y (ipart));
HP = patch (X (ipart (ch)) + DD (1), Y (ipart (ch)) + DD (2), color);
set (HP, 'facealpha', alpha, 'edgecolor', 'none');
elseif length (ipart) == 2,
HP = line (X (ipart) + DD (1), Y (ipart) + DD (2));
set (HP, 'color', color);
elseif length (ipart) < 2,
HP = plot (X (ipart) + DD (1), Y (ipart) + DD (2), 'k.');
set (HP, 'color', color);
end;
else
if length (ipart) > 2,
XYZ = [X(ipart)+DD(1), Y(ipart)+DD(2), Z(ipart)+DD(3)];
ch = convhulln (XYZ);
xc = XYZ (:, 1);
yc = XYZ (:, 2);
zc = XYZ (:, 3);
HP = patch (xc (ch)', yc (ch)', zc (ch)', color);
set (HP, 'facealpha', alpha, 'edgecolor', 'none');
elseif length (ipart) == 2,
HP = line (X (ipart) + DD (1), Y (ipart) + DD (2), Z (ipart) + DD (3));
set (HP, 'color', color);
elseif length (ipart) < 2,
HP = plot3 (X (ipart) + DD (1), Y (ipart) + DD (2), Z (ipart) + DD (3) , 'k.');
set (HP, 'color', color);
end;
end
axis equal
if (nargout > 1),
if strfind (options, '-2d'),
hull = []; hull.XY = [X(ipart)+DD(1) Y(ipart)+DD(2)];
else
hull = []; hull.XYZ = [X(ipart)+DD(1) Y(ipart)+DD(2) Z(ipart)+DD(3)];
end
hull.ch = ch;
end