% Plot commands for the 3D voronoi polyhedra.
% Arguments : M, indexed individuals
% S, a matrix of the referenced individuals to be highlighted.
% for example, S = [1 10 19] would highlight the first, tenth, and
% nineteenth individual (ranked in order of ascending distance from center)

%Created by Jim Work, University of South Carolina, August 13th, 2003

function vor_highlight_points(M,S)
% First, there's no point in running this function if the selected cells
% don't exist.  If the user want us to highlight cell #75, and our
% individual matrix (M) only has 20 points, this whole thing is going to
% break, and the user won't know why.  So we check to make sure that that's
% not going to happen, and we send a little polite message to the user.  The
% figure screen will still pop up, but it will be blank.
cantwork = 0;
for i = 1:size(S,2)
    if (S(1,i)>size(M,1)&(cantwork==0))
        'Please limit your cell selections (S) to cells within the array.'
        cantwork = 1;
    end
end

% So, if we can continue, we do so!
if (cantwork == 0)
    
    % find the center of mass, using the center_of_mass function
    
    center = [];
    center = center_of_mass(M);
    centerX = center(1,1);
    centerY = center(1,2);
    centerZ = center(1,3);
    
    % sort the array, with those closest to the center at the top of the array
    
    M = sortbydistance(M);
    
    % find the greatest distance between any two points, which is going to
    % be our group diameter
    
    currentMax = 0;
    j=0;
    
    for i=1:(size(M,1))
        for j=1:(size(M,1))
            if dist3d(M(i,2), M(i,3), M(i,4), M(j,2), M(j,3), M(j,4))>currentMax
                currentMax = dist3d(M(i,2), M(i,3), M(i,4), M(j,2), M(j,3), M(j,4));
            end
        end
    end
    
    diameter = currentMax;
    
    
    % define a regular dodecahedron, centered at the origin with radius of
    % one.  This was produced in Maple, and just transplanted here.
    
    BOUND = [[.3568220896, -.9341723582, 0.]; [-.3568220896, -.9341723582, 0.]; [-.5773502686, -.5773502686, .5773502686]; [0., -.3568220896, .9341723586]; [.5773502686, -.5773502686, .5773502686]; [0., .3568220896, -.9341723582]; [-.5773502686, .5773502686, -.5773502686]; [-.3568220896, .9341723586, 0.]; [.3568220896, .9341723586, 0.]; [.5773502686, .5773502686, -.5773502686]; [0., -.3568220896, -.9341723582]; [-.5773502686, -.5773502686, -.5773502686]; [-.9341723582, 0., -.3568220896]; [-.9341723582, 0., .3568220896]; [-.5773502686, .5773502686, .5773502686]; [0., .3568220896, .9341723586]; [.5773502686, .5773502686, .5773502686]; [.9341723586, 0., .3568220896]; [.9341723586, 0., -.3568220896]; [.5773502686, -.5773502686, -.5773502686]];
    
    % explode BOUND about the origin.  This makes the bounding dodecahedron
    % just a bit bigger than the diameter of the group, so that all
    % points of the dodecahedron's surface will be outside of the group
    
    BOUND = BOUND*diameter*1.5; 
    
    % this removes our index from M, so that it and BOUND will have the
    % same number of columns (three, in fact, with the form [x y z]).
    M = remIndex(M);
    
    % Now we shift the bounding dodecahedron to be centered around our
    % group's center of mass, which we found earlier.  After this step, the
    % group will be contained by the dodecahedron, as planned.
    for i = 1:size(BOUND,1)
        BOUND(i,1)=BOUND(i,1)+centerX;
        BOUND(i,2)=BOUND(i,2)+centerY;
        BOUND(i,3)=BOUND(i,3)+centerZ;
    end
    
    % We build a full matrix (F), which is our original individual points
    % and the bounding vertices of the dodecahedron.  It's important that
    % the original matrix (M) is at the top, as we shall see.
    F = [M; BOUND];
    
    % Now we actually do the voronoi calculation.  V holds the vertices of
    % the voronoi cells, C is the index of the cells themselves.  Voronoin
    % is a default Matlab function, so see "help voronoin" for a good
    % explanation of what's going on here.
    [V,C] = voronoin(F);
    
    % Here we start the graphics calls.
    hold on
    figure(1)
    
    % We perform a convex hull calculation on the cells from our original
    % group (which is why we set hull equal to the size of M, instead of
    % the size of F).  You can check "help convhulln" in Matlab to find out
    % about the convex hull function.
    
    for hull = 1:size(M,1);
        
        % For each volume 'hull'
        X = V(C{hull},:);      % View hull Voronoi cell.
        K = convhulln(X);
        d = [1:size(K,2), 1];
        % d = [1 2 3 1]; Index into K
        % For each face i;
        
        for i = 1:size(K,1)
            j = K(i,d);
            % Plot a polygon that is almost completely transparent green,
            % on each face i, with slightly less opaque edges
            h(i)=patch(X(j,1),X(j,2),X(j,3),'w');
            set(h(i),'facecolor', 'green');
            set(h(i),'facealpha', .15);
            set(h(i),'edgealpha', .05);
            
        end
        for q=1:size(S,2);
            
            if (hull==S(1,q))
                
                for i = 1:size(K,1)
                    j = K(i,d);
                    % Plot a polygon that is white with black lines, on each face i
                    h(i)=patch(X(j,1),X(j,2),X(j,3),'w');
                    
                    % set the faces of this to blue
                    set(h(i),'facecolor', 'blue');
                    set(h(i),'facealpha', .25);
                    set(h(i),'edgealpha', .05);
                    
                    
                    
                end
            end
        end
    end
end
for i=1:size(M,1)
    plot3(M(i,1),M(i,2),M(i,3),'r.')
end

hold off
view(3)
axis equal
title('highlighted voronoi cells')
rotate3d;
