function dec = projectDec(decOriginal, mappingNewToProper, varargin)
% project a decomposition
%
% Syntax: dec = projectDec(decProper, mappingNewToProper)
%
% The input decomposition is projected according to the linear subspace,
%   defined by mappingNewToProper that represents base vectors of the
%   subspace in its columns.
% A proper and complete input representation is projected to obtain a
%   (usually) improper representation.
% An incomplete representation is projected, no matter if proper or
%   improper, because only a small subset of decomposition data is
%   generated.
% A complete but inproper representation cannot be projected. The mapping
%   cannot be generated. You should generate a proper embedding
%   representation.
%
% Measures are NOT converted by this function, please use addMeasureDec to
%   add the required measures again.
%
% See also: obtainDec

% The elk-library: convex geometry applied to crystallization modeling.
%   Copyright (C) 2013 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
% parameters
par = mapOptionStruct(varargin, ...
    'zerotol', elkZerotol, ...
    'verbose', 1);
% improper representations cannot be projected
if ~decOriginal.isProper && decOriginal.isComplete
    error('elk:decomposition:wrongInput', ['Projection from improper ' ...
        'decompositions is not supported.']);
end
% there should at least be a warning for incomplete representations
if ~decOriginal.isComplete
    warning('elk:decomposition:incompleteRepresentation', ['An incomplete ' ...
        'representation is projected. Only a few properties will be ' ...
        'available.']);
end

%% initial data
% this is the part about facet normals, mapping and storing the original
%   proper representation, including the mapping to the improper
%   representation.
dec.A    = decOriginal.A;
dec.nDim = decOriginal.nDim;
dec.nH   = decOriginal.nH;
dec.mappingReducedToFull = decOriginal.mappingReducedToFull * mappingNewToProper;
dec.mappingFullToReduced = pinv(dec.mappingReducedToFull);
dec.constraintMatrix = eye(dec.nH) - dec.mappingReducedToFull * ...
    dec.mappingFullToReduced;
dec.nC   = size(mappingNewToProper, 2);
dec.properData = decOriginal;
dec.properData.mappingNewToProper = mappingNewToProper;
dec.properData.mappingProperToNew = pinv(mappingNewToProper);
dec.properData.projectionMatrix = mappingNewToProper*inv(mappingNewToProper'*mappingNewToProper)*...
    mappingNewToProper';

%% fallback to complete/incomplete handling
% this part handles the confinement/validity cones including facet validity
%   data and decomposition
if decOriginal.isComplete
    dec = projectCompleteDec(dec, par);
else
    dec = projectIncompleteDec(dec, par);
end

%% cleanup of structure
dec = cleanupDecStructure(dec);