function lines = APPgetLargeConnectedEdges(grayIm, minLen)
% lines = APPgetLargeConnectedEdges(grayIm, minLen)
% 
% Uses the method of Video Compass [Kosecka, et al 2002] to get long,
% straight edges.
% 
% Input:
%   grayIm: grayscale image to be analyzed
%   minLen: minimum length in pixels for edge (suggested 0.025*diagonal)
% Output:
%   lines: parameters for long, straight lines 
%          (nlines, [x1 x2 y1 y2 theta r])
%
% To display result: 
%   figure(1), hold off, imshow(grayIm)
%   figure(1), hold on, plot(lines(:, [1 2])', lines(:, [3 4])')
%
% Copyright(C) Derek Hoiem, Carnegie Mellon University, 2007

[dX, dY] = gradient(conv2(grayIm, fspecial('gaussian', 7, 1.5), 'same'));

im_canny = edge(grayIm, 'canny');
% remove border edges
im_canny([1 2 end-1 end], :) = 0;
im_canny(:, [1 2 end-1 end]) = 0;
height = size(im_canny, 1);

ind = find(im_canny > 0);

num_dir = 8;

dX_ind = dX(ind);
dY_ind = dY(ind);
a_ind = atan(dY_ind ./ (dX_ind+1E-10));

% a_ind ranges from 1 to num_dir with bin centered around pi/2
a_ind = ceil(mod(a_ind/pi*num_dir-0.5, num_dir));
%[g, gn] = grp2idx(a_ind);

% get the indices of edges in each direction
for i = 1:num_dir
    direction(i).ind = ind(find(a_ind==i));
end


% remove edges that are too small and give all edges that have the same
% direction a unique id
% edges(height, width, [angle id])
lines = zeros(2000, 6);

used = zeros(size(im_canny));

line_count = 0;
for k = 1:num_dir
    
    num_ind = 0;
    for m = (k-1):k+1
        num_ind = num_ind + sum(~used(direction(mod(m-1, num_dir)+1).ind));
    end
    
    ind = zeros(num_ind, 1);
    dir_im = zeros(size(im_canny));
  
    count = 0;
    for m = (k-1):k+1
        m2 = mod(m-1, num_dir)+1;
        tind = direction(m2).ind(~used(direction(m2).ind));
        tmpcount = length(tind);
        ind(count+1:count+tmpcount) = tind;
        count = count + tmpcount;
    end
    dir_im(ind) = 1;
        
    [tmpL, num_edges] = bwlabel(dir_im, 8); 
    
    % get the number of pixels in each edge
    edge_size = zeros(num_edges, 1);
    edges = repmat(struct('ind', zeros(200, 1)), num_edges, 1);
    for i = 1:length(ind)
        id = tmpL(ind(i));
        edge_size(id) = edge_size(id) + 1;
        edges(id).ind(edge_size(id)) = ind(i);
    end          
    for i = 1:num_edges
        edges(i).ind = edges(i).ind(1:edge_size(i));
    end        
       
    % get the endpoints of the long edges and an image of the long edges
    for id = 1:num_edges
        if edge_size(id) > minLen         
                                    
            y = mod(edges(id).ind-1, height)+1;
            x = floor((edges(id).ind-1) / height)+1;                        
            
            mean_x = mean(x);
            mean_y = mean(y);
            zmx = (x-mean_x);
            zmy = (y-mean_y);
            D = [sum(zmx.^2) sum(zmx.*zmy); sum(zmx.*zmy) sum(zmy.^2)];
            [v, lambda] = eig(D);
            theta = atan2(v(2, 2) , v(1, 2));                       
            if lambda(1,1)>0
                conf = lambda(2,2)/lambda(1,1);
            else
                conf = 100000;
            end                
            
            if conf >= 400 
                line_count = line_count+1;
                
                used(edges(id).ind) = 1;              
                
                %disp(num2str([lambda(1,1) lambda(2,2)]))
                r = sqrt((max(x)-min(x))^2 + (max(y)-min(y))^2);
                x1 = mean_x - cos(theta)*r/2;
                x2 = mean_x + cos(theta)*r/2;
                y1 = mean_y - sin(theta)*r/2;
                y2 = mean_y + sin(theta)*r/2;            
                
                r = mean_x*cos(theta)+mean_y*sin(theta);
                
                lines(line_count, 1:6) = [x1 x2 y1 y2 theta r];
	
            end
        end
    end

end


lines = lines(1:line_count, :);
