function h = viewPolytope(poly, varargin)
% plots a polytope in H-representation or V-representation
%
% h = viewPolytope returns the handles to the patch objects, which
%   represent the facets of the polytope.
%
% viewPolytope(Pt, 'optionname', option) applies the following options:
%    option   - a structure containing fields with options as below
%                (additional values are preferred compared to options given
%                here)
%    color     - sets default color {'r' or [1 1 1]}
%    shade     - level of transparency (0 - transparent, 1 - opaque)
%    colormap  - sets a different colormap (default: 'hsv')
%    edgecolor - color of edges (default is black)
%    linewidth - width of the border of polytope (default is 1)
%    linestyle - style of the border of each polytope (could be either '-',
%                ':', ';' or 'none') (default is '-')
%    flatness  - for degenerate objects; look for: help convertVrepToHrep.
%                (default is 0)
%    zerotol   - zerotol is used to identify values that are close to zero 
%                by zero. (default is 1e-7)
%    infinityBoxSize - look for: help convertHrepToVrep (default is 1e3)
%
% See also: obtainVrep, paintFacet

% The elk-library: convex geometry applied to crystallization modeling.
%   Copyright (C) 2012 Alexander Reinhold
%
% This program is free software: you can redistribute it and/or modify it 
%   under the terms of the GNU General Public License as published by the 
%   Free Software Foundation, either version 3 of the License, or (at your 
%   option) any later version.
%
% This program is distributed in the hope that it will be useful, but 
%   WITHOUT ANY WARRANTY; without even the implied warranty of 
%   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
%   General Public License for more details.
%
% You should have received a copy of the GNU General Public License along 
%   with this program.  If not, see <http://www.gnu.org/licenses/>.

%% map options
% [opt.option, opt.shade, opt.color,...
%  opt.linestyle, opt.linewidth, opt.edgecolor,...
%  opt.flatness, opt.infinityBoxSize, opt.zerotol] = ...
% mapOption(varargin,...
%     'option', struct([]),...
%     'shade', 0.8,...    
%     'color', [1 1 1]*0.5,...
%     'linestyle', '-',...
%     'linewidth', 1.5,...
%     'edgecolor', [0 0 0],...
%     'flatness', 0, ...
%     'infinityBoxSize', 1e2, ...
%     'zerotol', elkZerotol ...
%     );
opt = mapOptionStruct(varargin,...
    'shade', 0.8,...    
    'color', [1 1 1]*0.5,...
    'linestyle', '-',...
    'linewidth', 1.5,...
    'edgecolor', [0 0 0],...
    'flatness', 0, ...
    'infinityBoxSize', 1e2, ...
    'zerotol', elkZerotol ...
    );

% opt = mergeStruct(opt.option, opt);
% opt = rmfield(opt, 'option');

%% check input dimension
infoPoly = identifyPolytope(poly);
if infoPoly.dim > 3 || infoPoly.dim < 2
    error('elk:polytope:wrongType', ...
        'viewPolytope can only plot 2D and 3D polytopes');
end

%% convert input to plottable polytope
[vrep, hrep] = makePlottablePolytope(poly, opt.zerotol, opt.flatness, ...
    opt.infinityBoxSize);
% empty polytope
if isempty(vrep.V)
    h = [];
    return
end

%% Plot
switch infoPoly.dim
    case 2
        % all at once - a single patch
        if size(vrep.V, 1) > 2
            K = convhull(vrep.V(:, 1), vrep.V(:, 2)); 
        elseif size(vrep.V, 1) == 2
            K = 1:2;
        elseif size(vrep.V, 1) == 1
            K = 1;
        end
        h = patch(vrep.V(K, 1), vrep.V(K, 2), vrep.V(K, 2)*0+1);
    case 3
        % cycle through facet normals - each facet a patch
        h = zeros(size(hrep.A, 1), 1);
        for iFacet = 1:size(hrep.A, 1)
            % filter vertices
            thisFacetVrep.V = ...
                vrep.V(isZero(...
                  hrep.A(iFacet, :) * vrep.V' - hrep.h(iFacet), ...
                  opt.zerotol), :);
            
            % calculate facet in 2d
            thisFacetVrep2d = rotateVrep3d(...
                thisFacetVrep, 'vector', hrep.A(iFacet, :), [0 0 0]);
            thisFacetVrep2d = moveVrep(...
                thisFacetVrep2d,  hrep.h(iFacet)*[0 0 -1]);
            thisFacetVrep2d.V(:, 3) = [];
            
            % resort vertices for facet
            if size(thisFacetVrep2d.V, 1) > 2
                K = convhull(thisFacetVrep2d.V(:, 1), ...
                    thisFacetVrep2d.V(:, 2));
            elseif size(thisFacetVrep2d.V, 1) == 2
                K = 1:2;
            elseif size(thisFacetVrep2d.V, 1) == 1
                K = 1;
            else
                continue
                error('elk:polytope:NumericalProblem', ...
                    'something is wrong with the dimension of the provided polytope');
            end
            thisFacetVrep.V = thisFacetVrep.V(K, :);
            
            % plot vertices
            h(iFacet) = patch(thisFacetVrep.V(:, 1), ...
                              thisFacetVrep.V(:, 2), ...
                              thisFacetVrep.V(:, 3), ...
                              ones(1,3));
            view([42, 23]);
        end
end

% filter empty patches - should this happen??
h(h==0) = [];

%% apply options
set(h, 'facealpha', opt.shade, ...
       'facecolor', opt.color, ...
       'linewidth', opt.linewidth, ...
       'linestyle', opt.linestyle, ...
       'edgecolor', opt.edgecolor);

if opt.shade == 0
    set(h, 'facecolor', 'none')
end


set(gca, 'PlotBoxAspectRatio', [1 1 1], ...
         'DataAspectRatio', [1 1 1],...
         'XGrid', 'off', 'YGrid', 'off', 'ZGrid', 'off');

if nargout < 1
    clear h
end


