function x_opt = plot(varargin)
%plot               plots feasible set
%
% p = plot(F,x,c,n,options)
%
% F:  set object
% x:  projected variables [At most three variables]
% c:  color [double] ([r g b] format)
% n:  #vertices [double ]
% options: options structure from sdpsettings


% Author Johan Löfberg
% $Id: plot.m,v 1.13 2006/04/25 11:22:57 joloef Exp $

% Get the onstraints
if nargin<1
    return
end

F = varargin{1};

if length(F)==0
    return;
end

if nargin < 5
    opts = sdpsettings('verbose',0);
else
    opts = varargin{5};
    if isempty(opts)
        opts = sdpsettings('verbose',0);
    end
end

if nargin < 3
    color = [1 0.1 0.1];
else
    color = varargin{3};
    if isempty(color)
        color = [1 0.1 0.1];
    end
end

% Plot onto this projection (at most in 3D)
if nargin < 2
    x = [];
else
    x = varargin{2};
    if ~isempty(x)
        x = x(:);
        x = x(1:min(3,length(x)));
    end
end

if isempty(F)
    return
end

% Create a model in YALMIPs low level format
% All we change later is the cost vector
%sol = solvesdp(F,sum(x),opts);
[model,recoverdata,diagnostic,internalmodel] = export(F,[],opts,[],[],0);
if isempty(internalmodel) | (~isempty(diagnostic) & diagnostic.problem)
    error('Could not create model. Can you actually solve problems with this model?')
end
internalmodel.options.saveduals = 0;
internalmodel.getsolvertime = 0;
internalmodel.options.dimacs = 0;

% Try to find a suitable set to plot
if isempty(x)
    if isempty(internalmodel.extended_variables)
        x = depends(F);
        x = x(1:min(3,length(x)));
        localindex = 1;
        localindex = find(ismember(recoverdata.used_variables,x));
    else
        % not extended variables
        candidates = setdiff(1:length(internalmodel.c),internalmodel.extended_variables);
        % Not nonlinear variables
        candidates = candidates(find(internalmodel.variabletype(candidates)==0));
        % Settle with this guess
        localindex = candidates(1:min(3,length(candidates)));
        x = localindex;
    end
else
    localindex = [];
    for i = 1:length(x)
        localindex = [localindex find(ismember(recoverdata.used_variables,getvariables(x(i))))];
    end
end

if nargin < 4
    if length(x)==3
        n = 100;
    else
        n = 25;
    end
else
    n = varargin{4};
    if isempty(n)
        if length(x)==3
            n = 100;
        else
            n = 25;
        end
    end
    if ~isa(n,'double')
        error('4th argument should be an integer>0');
    end
end


x_opt = [];
phi = [];
status = 0;
try % Try to ensure that we close h
    if length(x)==2
        mu =0.5;
    else
        mu=1;
    end
    n_ = n;
    n = ceil(mu*n);
    h = waitbar(0,['Please wait, solving ' num2str(n_) ' problems using ' internalmodel.solver.tag]);
    angles = (0:(n))*2*pi/n;
    if length(x)==2
        c = [cos(angles);sin(angles)];
    else
        c = randn(3,n);
    end
    i=1;
    while i<=n & status == 0
        xi = solvefordirection(c(:,i),internalmodel,localindex);
        x_opt = [x_opt xi];
        waitbar(i/n_,h)
        i=i+1;
    end

    if status==0 & length(x)==2
        % Close the set
        x_opt = [x_opt x_opt(:,1)];

        % Add points adaptively
        pick = 1;
        n = floor((1-mu)*n_);
        for i = 1:1:n
            for j= 1:(size(x_opt,2)-1)
                d = x_opt(:,j)-x_opt(:,j+1);
                distance(j,1) = d'*d;
            end
            [dist,pos]=sort(-distance);
            % Select insertion point
            phii=(angles(pos(pick))+angles(pos(pick)+1))/2;
            xi = solvefordirection([cos(phii);sin(phii)],internalmodel,localindex);
            d1=xi-x_opt(:,pos(pick));
            d2=xi-x_opt(:,pos(pick)+1);
            if d1'*d1<1e-3 | d2'*d2<1e-3
                pick = pick+1;
            else
                angles = [angles(1:pos(pick)) phii  angles((pos(pick))+1:end)];
                x_opt = [x_opt(:,1:pos(pick)) xi  x_opt(:,(pos(pick))+1:end)];
            end
            waitbar((ceil(n_*mu)+i)/n_,h);
        end
    end
    close(h);
catch
    close(h);
end

if status
    if nargout==0
        plot(0);
    end
end

if nargout == 0 & status==0
    if length(x)==2
        patch(x_opt(1,:),x_opt(2,:),color);
    else
        K = convhulln(x_opt');
        p = patch('Vertices', x_opt', 'Faces', K, 'FaceVertexCData', color, 'FaceColor', color);%, 'FaceAlpha', 0.5);
        set(p,'LineStyle','none')
        lighting gouraud;
        view(3);
        camlight('headlight','local');
        camlight('headlight','local');
        camlight('right','local');
        camlight('left','local');
    end
end


function [xout,status] = solvefordirection(c,internalmodel,uv)
internalmodel.c = 0*internalmodel.c;
internalmodel.c(uv) = c;
sol  = feval(internalmodel.solver.call,internalmodel);
xout = sol.Primal;
xout = xout(uv(:));
status = sol.problem;




