% displayPoints(I,ii,jj,ss,[size=2])
%   I -- image to display over
%   ii -- array of i-indices of interest points
%   jj -- array of j-indices of interest points
%   ss -- array of scales of the interest points
%         (standard deviation of the gaussian used to filter the image)
%   size -- scale factor used when drawing the circle
%           around a point.
%           The radius of the circle will be size*ss(i) for point i.
%
% Example:
%   displayPoints(I,[10,10,10],[10,20,30],[1,1.2,1.3])
%
%
% displayPoints(results, [size])
%   results -- a structure containing an image and information extracted
%              from it.
%     results.I -- The original image as a three-dimensional array.
%                  This can either be of type double, and have pixel values
%                  in the range [0 1], or be of type uint8, and have pixel
%                  values in the range [0 255].
%     results.points -- An array of point objects.
%       results.points.i -- The row index of the point in the original
%                           image (not in the reduced-size pyramid images)
%                           Can be fractional.
%       results.points.j -- The column index of the point in the original
%                           image.
%       results.points.sigma -- the scale of the point. This is the sigma
%                           value or standard deviation of the Gaussian
%                           filter used to blur the image.
%   size -- scale factor used when drawing the circle
%           around a point.
%           The radius of the circle will be size*ss(i) for point i.
%
% Example of second case: Suppose you have an image I, and the i, j, and sigma values 
% for your points (in the coordinate system of that image) in
% the vectors i, j, and sigma.  You can plot the points using
%
% results.I = I;
% results.points = [];
% for indPoint = 1:length(i)
%    point.i = i(indPoint);
%    point.j = j(indPoint);
%    point.sigma = sigma(indPoint);
%    results.points = [results.points point];
% end
% displayPoints(results)
%
% Version 2, Fall 2014-2015

% Author: Josiah Yoder
% Term: Summer 2014
% Course: CS498 - Computer Vision
% Lab 3: SIFT interest-point detection
%
% Updated Winter 2016-2017 to fix a bug
% that caused the displayPoints(results) case to fail
% (And would have also caused displayPoints(reults, size) to ignore the scale-factor)

function displayPoints(results,ii,jj,ss,size)
% Handle the displayPoints(I,ii,jj,ss,size) case
if nargin > 2 
    if isstruct(results)        
        error('Unexpected: Structure (results?) provided with multiple arguments.  Must provide structure as a single argument.')
    end
    
    if nargin < 4
        error('Missing arguments. See help for alternatives.')
    elseif nargin < 5
        size = 2;
    end
        
    I = results;
    clear results
    results.I = I;
    results.points = [];
    for indPoint = 1:length(ii(:))
       point.i = ii(indPoint);
       point.j = jj(indPoint);
       point.sigma = ss(indPoint);
       results.points = [results.points point];
    end
% handle the displayPoints(results, [size]) case
elseif isstruct(results)
    I = results.I;
    if nargin >= 2
        size = ii;
    else
        size = 2;
    end
else
    error('Unexpected: One non-struct argument provided. With one argument, "results" structure expected. See options in help.')
end

%% Display all levels
imshow(I)
hold on
for indPoint = 1:length(results.points)
    point = results.points(indPoint);
    plotCircle(point.j,point.i,point.sigma*size);
    plot(point.j,point.i,'ro');
end
hold off

end

% plotCircle(j,i,r)
%
%  Plot a circle over an image centered at pixel (i,j) with radius r
% 
%  i,j -- the center of the circle
%  r -- the radius
%
% plotCircle(...,'ro-')
% plotCircle(...,'LineWidth',3,...)
%   Any extra paramters are passed straight along to the plot function.
function plotCircle(j,i,r,varargin)
n = min(ceil(r*4),20);
theta = (0:n)/n*2*pi;
plot(j+r*cos(theta),i+r*sin(theta),varargin{:})

end
