function measureStruct = obtainMeasureInfo(measureName, facetNormalMatrix)
% returns information of an available measures in a struct
%
% Syntax: measureStruct = obtainMeasureInfo(measureName)
%   or    measureStruct = obtainMeasureInfo(measureName, facetNormalMatrix)
%
% Translates a measure name to a known measure in form of a struct
%   containing the following information:
%     .name  - the name of the measure
%     .dim   - the dimension of the measure refering a 3-dimensional object
%     .isPar - whether the measure requires a parameter that usually is a
%              direction
%     .handleHrep - this is a function handle (anonymous function) to the
%                   function that calculates the measure based on a
%                   H-representaation.
%     .handleVrep - same as above based on a V-representaation.
%     .handleH - same as above based on a h- vector (only provided, if matrix of
%                facet normals is provided)
%
% The input measureName might be empty so that all possible measures are
%   returned in a struct vector. Or a cell array of measure names are
%   provided which results in a struct vector of the given measures.
%
% Available measures and possible names:
%   volume - volume
%   surface - surface, surfaceArea, surface area
%   facet - facet, facetArea, facet area
%   projection - projection, projectionArea, projection area
%   feret - feret, feret diameter
%   support - support, support value
%   meanWidth - meanWidth, mean width
%   edgeLength - edgeLength, edge length
%

% 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
if ~exist('facetNormalMatrix', 'var')
    facetNormalMatrix = [];
end
if ~exist('measureName', 'var') || isempty(measureName)
    measureName = {'volume', ...
                   'surface', 'facet', 'projection', ...
                   'feret', 'support'};
end
if ~iscell(measureName)
    measureName = {measureName};
end

%% Build struct
measureStruct = struct();
for iMeasure = 1:length(measureName)
    [thisMeasureStruct functionName] = internalMeasureInfo(measureName{iMeasure});
    measureStruct(iMeasure).name = thisMeasureStruct.name;
    measureStruct(iMeasure).dim = thisMeasureStruct.dim;
    measureStruct(iMeasure).isPar = thisMeasureStruct.isPar;
    
    if ~measureStruct(iMeasure).isPar
        % handle for V- and H-representation
        measureStruct(iMeasure).handleVrep = @(vrep)(eval(...
            [functionName 'Vrep(vrep)']));
        measureStruct(iMeasure).handleHrep = @(hrep)(eval(...
            [functionName 'Hrep(hrep)']));
        % handles for H and Hc vectors
        if ~isempty(facetNormalMatrix)
            measureStruct(iMeasure).handleH = @(h)(...
                measureStruct(iMeasure).handleHrep(struct(...
                'A', facetNormalMatrix, 'h', h)));
        end
    else
        % handle for V- and H-representation
        measureStruct(iMeasure).handleVrep = @(vrep, par)(eval(...
            [functionName 'Vrep(vrep, par)']));
        measureStruct(iMeasure).handleHrep = @(hrep, par)(eval(...
            [functionName 'Hrep(hrep, par)']));
        % handles for H and Hc vectors
        if ~isempty(facetNormalMatrix)
            measureStruct(iMeasure).handleH = @(h,par)(...
                measureStruct(iMeasure).handleHrep(struct(...
                'A', facetNormalMatrix, 'h', h), ...
                par));
        end
    end

end

end

function [measureStruct, functionName] = internalMeasureInfo(measureName)

%% Volume
if strcmp(measureName, 'volume')
        measureStruct.name = 'volume';
        measureStruct.dim = 3;
        measureStruct.isPar = 0;
        functionName = 'computeVolume';
        
%% Surface
elseif strcmpi(measureName, 'surface') || ...
       strcmpi(measureName, 'surfaceArea') || strcmp(measureName, 'surface area')

        measureStruct.name = 'surface';
        measureStruct.dim = 2;
        measureStruct.isPar = 0;
        functionName = 'computeFacetArea';
        
%% Facet
elseif strcmpi(measureName, 'facet') || ...
       strcmpi(measureName, 'facetarea') || strcmpi(measureName, 'facet area')

        measureStruct.name = 'facet';
        measureStruct.dim = 2;
        measureStruct.isPar = 1;
        functionName = 'computeFacetArea';

%% Projection Area
elseif strcmpi(measureName, 'projection') || ...
       strcmpi(measureName, 'projectionArea') || strcmpi(measureName, 'projection area')

        measureStruct.name = 'projection';
        measureStruct.dim = 2;
        measureStruct.isPar = 1;
        functionName = 'computeProjectionArea';
        
%% Feret Diameter
elseif strcmpi(measureName, 'feret') || strcmpi(measureName, 'feret diameter')

        measureStruct.name = 'feret';
        measureStruct.dim = 1;
        measureStruct.isPar = 1;
        functionName = 'computeFeret';
                                   
%% Support value
elseif strcmpi(measureName, 'support') || strcmpi(measureName, 'support value')
        measureStruct.name = 'support';
        measureStruct.dim = 1;
        measureStruct.isPar = 1;
        functionName = 'computeSupportValue';
        
%% Mean width
elseif strcmpi(measureName, 'meanWidth') || strcmpi(measureName, 'mean width')
        measureStruct.name = 'meanWidth';
        measureStruct.dim = 1;
        measureStruct.isPar = 0;
        functionName = 'computeMeanWidth';    
%% Mean width
elseif strcmpi(measureName, 'edgeLength') || strcmpi(measureName, 'edge length')
        measureStruct.name = 'edgeLength';
        measureStruct.dim = 1;
        measureStruct.isPar = 1;
        functionName = 'computeEdgeLength';   
else
%% Failure
        error('elk:polytope:wrongInput', ...
            ['Given measure ''' measureName ''' is unknown']);
end

end