classdef Cube < Object
    % Class 'Cube' defines a cube through six planes sampled by points.
    %
    %   Copyright (C) 2015  Florian Raudies, 05/02/2015, Palo Alto, CA.
    %   License, GNU GPL, free software, without any warranty.
    methods
        % Constructor with Interval = [xMin yMin zMin xMax yMax zMax] and
        % Samples = [nX nY nZ].
        function obj = Cube(Interval, Samples, sampleType)
            
            if nargin<3, sampleType = 'random'; end % Default value.
            
            obj             = obj@Object();
            obj.Interval    = Interval;
            xMin            = Interval(1);
            yMin            = Interval(2);
            zMin            = Interval(3);
            xMax            = Interval(4);
            yMax            = Interval(5);
            zMax            = Interval(6);
            nX              = Samples(1);
            nY              = Samples(2);
            nZ              = Samples(3);
            
            if strcmp(sampleType,'random'),
                % Left
                obj.addObject(Plane([1;0;0;0], xMin, ...
                    [zMin yMin zMax yMax], [nZ,nY], sampleType));
                % Right
                obj.addObject(Plane([1;0;0;0], xMax, ...
                    [zMin yMin zMax yMax], [nZ,nY], sampleType));
                % Top (subtract delta to avoid the sampling of edges twice)
                obj.addObject(Plane([0;1;0;0], yMax, ...
                    [xMin zMin xMax zMax], [nX,nZ], sampleType));
                % Bottom
                obj.addObject(Plane([0;1;0;0], yMin, ...
                    [xMin zMin xMax zMax], [nX,nZ], sampleType));
                % Front
                obj.addObject(Plane([0;0;1;0], zMin, ...
                    [xMin yMin xMax yMax], [nX,nY], sampleType));
                % Back
                obj.addObject(Plane([0;0;1;0], zMax, ...
                    [xMin yMin xMax yMax], [nX,nY], sampleType));
            elseif strcmp(sampleType,'regular'),
                xDelta = (xMax-xMin)/(nX-1);
                yDelta = (yMax-yMin)/(nY-1);
                % Left
                obj.addObject(Plane([1;0;0;0], xMin, ...
                    [zMin yMin zMax yMax], [nZ,nY], sampleType));
                % Right
                obj.addObject(Plane([1;0;0;0], xMax, ...
                    [zMin yMin zMax yMax], [nZ,nY], sampleType));
                % Top (subtract delta to avoid the sampling of edges twice)
                obj.addObject(Plane([0;1;0;0], yMax, ...
                    [xMin+xDelta zMin xMax-xDelta zMax], ...
                    [nX-2,nZ], sampleType));
                % Bottom
                obj.addObject(Plane([0;1;0;0], yMin, ...
                    [xMin+xDelta zMin xMax-xDelta zMax], ...
                    [nX-2,nZ], sampleType));
                % Front
                obj.addObject(Plane([0;0;1;0], zMin, ...
                    [xMin+xDelta yMin+yDelta xMax-xDelta yMax-yDelta], ...
                    [nX-2,nY-2], sampleType));
                % Back
                obj.addObject(Plane([0;0;1;0], zMax, ...
                    [xMin+xDelta yMin+yDelta xMax-xDelta yMax-yDelta], ...
                    [nX-2,nY-2], sampleType));
            else
                error('Matlab:Parameter',...
                    'The sample type %s is not valid!',sampleType);
            end
            
        end
        % Interval = [xMin yMin zMin xMax yMax zMax]
        function [obj DeleteIndex] = resizeX(obj, Interval)
            xNewMin = Interval(1);
            xNewMax = Interval(2);
            % Modify the 1st and 2nd 
            Index = obj.getObjectToPoint();
            nIndex = size(Index,1);
            PointsIndex = Index(1,1):Index(1,2);
            obj.Points(PointsIndex,1) = min(max( ...
                obj.Points(PointsIndex,1),xNewMin),xNewMax);
            PointsIndex = Index(2,1):Index(2,2);
            obj.Points(PointsIndex,1) = min(max( ...
                obj.Points(PointsIndex,1),xNewMin),xNewMax);
            DeleteIndex = [];
            for iIndex = 3:nIndex,
                PointsIndex = obj.objToPoints(iIndex,1):obj.objToPoints(iIndex,2);
                OutsideIndex = obj.Points(PointsIndex,1) < xNewMin ...
                             | obj.Points(PointsIndex,1) > xNewMax;
                DeleteIndex = [DeleteIndex; Index(iIndex-1,2) ...
                                            + find(OutsideIndex)];
                obj.objToPoints(iIndex,:) = ...
                    [Index(iIndex-1,1) Index(iIndex-1,2)-sum(OutsideIndex)];
            end
            obj.Points(DeleteIndex,:) = [];
            obj.nPoints = obj.nPoints - length(DeleteIndex);
            obj.Interval(1) = xNewMin;
            obj.Interval(4) = xNewMax;
        end
        function Ground = getGroundSegment(obj)
            Ground = (obj.Points(1:obj.nPoints,2) ...
                     - min(obj.Points(1:obj.nPoints,2))) < eps('single');
        end
        function M = getMesh(obj)
            xMin = obj.Interval(1);
            yMin = obj.Interval(2);
            zMin = obj.Interval(3);
            xMax = obj.Interval(4);
            yMax = obj.Interval(5);
            zMax = obj.Interval(6);
            M = [xMin yMin zMin; ... % ground
                 xMax yMin zMax; ...
                 xMin yMin zMax; ...
                 xMin yMin zMin; ...
                 xMax yMin zMin; ...
                 xMax yMin zMax; ...
                 NaN  NaN  NaN; ...
                 xMin yMax zMin; ... % ceiling
                 xMax yMax zMax; ...
                 xMin yMax zMax; ...
                 xMin yMax zMin; ...
                 xMax yMax zMin; ...
                 xMax yMax zMax; ...
                 NaN  NaN  NaN; ...
                 xMin yMin zMax;... % right
                 xMax yMin zMax;...
                 xMax yMax zMax;...
                 xMin yMin zMax;...
                 xMin yMax zMax;...
                 xMax yMax zMax;...
                 NaN  NaN  NaN; ...
                 xMin yMin zMin;... % left
                 xMax yMin zMin;...
                 xMax yMax zMin;...
                 xMin yMin zMin;...
                 xMin yMax zMin;...
                 xMax yMax zMin;...
                 NaN  NaN  NaN; ...
                 xMin yMin zMin; ... % bottom
                 xMin yMax zMin; ...
                 xMin yMax zMax; ...
                 xMin yMin zMin; ...
                 xMin yMin zMax; ...
                 xMin yMax zMax; ...
                 NaN  NaN  NaN; ...
                 xMax yMin zMin; ... % top
                 xMax yMax zMin; ...
                 xMax yMax zMax; ...
                 xMax yMin zMin; ...
                 xMax yMin zMax; ...
                 xMax yMax zMax];
        end
    end
end