function partitionData = decomposeCone(dec, A, genericPartition, ...
    zerotol, verbose)
% decompose the cone of valid polytopes into regions of equal a-type
%
% rayMatrix contains a "scaledToClose" extreme ray in each row.
%
% THIS FUNCTION IS NO USER FUNCTION.

% 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/>.

%% input handling
% the input cone is provided in hrep with its facet normals in A; we 
%   require the closed cone
hrepCone = struct('A', A, 'h', zeros(size(A, 1), 1));
hrepClosed = closeCone(hrepCone, dec.centerRay);
coneVolume = computeVolumeHrep(hrepClosed);
% this is also the starting remaining domain
remainingDomain = {hrepClosed};

%% Initializing
% initialize random number generator
randState = rng;
rng(1);
% loop initialization
partitionData = genericPartition();
gatheredVolume = 0;

if verbose,fprintf('......');end

while 1 == 1
    if verbose
        fprintf('\b\b\b\b\b\b%5.1f%%', (gatheredVolume/coneVolume*100));
%         fprintf('%5.1f%%, %f ', (gatheredVolume/coneVolume*100), ...
%             length(remainingDomain));
    end
    
    %% Decompose a sample
    % We randomly generate a hC-vector from the last hrep that is entered.
    %   This hrep can be assumed to be relatively small according to the
    %   polytope difference algorithm. For the random vector, an offset of
    %   0.1 is applied so that the resulting random vector is safely in the
    %   interior of the selected cone.
    thisVrep = convertHrepToVrep(remainingDomain{end});
    thisVrep = openCone(thisVrep, zerotol);
    lam = rand([1, size(thisVrep.V, 1)]) + 0.1;
    hC = (lam * thisVrep.V)';

    %% use generic partition generator
    thisPartitionData = genericPartition(dec, hC, zerotol);
       
    % repeat, if failed
    if thisPartitionData.flagResult == 0, continue, end;
    
    % check if sample is part of partition
    if any((thisPartitionData.hrep.A * hC) > zerotol)
        error('decomposition:elk:numericalError', ['Sample is not part of ' ...
            'the generated partition. This should not happen.']);
    end
    
    if thisPartitionData.flagResult == 1
        % accept and add partition
        partitionData(end+1) = thisPartitionData;
    elseif thisPartitionData.flagResult == -1
        % partition will be ignored, nothing to do
    else
        error('elk:decomposition:numericalError', ['flagResult is unknown. ' ...
            'This should not happen.']);
    end
%     fprintf(' part ');
    
    % compute volume
    thisHrep = closeCone(thisPartitionData.hrep, dec.centerRay);
    thisVolume = computeVolumeHrep(thisHrep);
    gatheredVolume = gatheredVolume + thisVolume;
%     fprintf(' %f \n', thisVolume);
    
    %% Update remaining domain
    % we substract the unified partition, we just found. note that we
    %   subtract the unclosed cone from the closed remaining domain, which
    %   is perfectly OK.
    remainingDomain = subtractPolytopeHrep(remainingDomain, ...
        thisPartitionData.hrep, zerotol);
    
    %    if this is empty, we have obviously finished
    if isempty(remainingDomain)
        break;
    end
end
if verbose, fprintf('\b\b\b\b\b\b');end

% recover random number generator
rng(randState);

end