function varargout = houghgui(varargin)
% HOUGHGUI MATLAB code for houghgui.fig
%      HOUGHGUI, by itself, creates a new HOUGHGUI or raises the existing
%      singleton*.
%
%      H = HOUGHGUI returns the handle to a new HOUGHGUI or the handle to
%      the existing singleton*.
%
%      HOUGHGUI('CALLBACK',hObject,eventData,handles,...) calls the local
%      function named CALLBACK in HOUGHGUI.M with the given input arguments.
%
%      HOUGHGUI('Property','Value',...) creates a new HOUGHGUI or raises the
%      existing singleton*.  Starting from the left, property value pairs are
%      applied to the GUI before houghgui_OpeningFcn gets called.  An
%      unrecognized property name or invalid value makes property application
%      stop.  All inputs are passed to houghgui_OpeningFcn via varargin.
%
%      *See GUI Options on GUIDE's Tools menu.  Choose "GUI allows only one
%      instance to run (singleton)".
%
% See also: GUIDE, GUIDATA, GUIHANDLES

% Edit the above text to modify the response to help houghgui

% Last Modified by GUIDE v2.5 28-Nov-2017 01:58:47

% Begin initialization code - DO NOT EDIT
gui_Singleton = 1;
gui_State = struct('gui_Name',       mfilename, ...
                   'gui_Singleton',  gui_Singleton, ...
                   'gui_OpeningFcn', @houghgui_OpeningFcn, ...
                   'gui_OutputFcn',  @houghgui_OutputFcn, ...
                   'gui_LayoutFcn',  [] , ...
                   'gui_Callback',   []);
if nargin && ischar(varargin{1})
    gui_State.gui_Callback = str2func(varargin{1});
end

if nargout
    [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
else
    gui_mainfcn(gui_State, varargin{:});
end
% End initialization code - DO NOT EDIT


% --- Executes just before houghgui is made visible.
function houghgui_OpeningFcn(hObject, eventdata, handles, varargin)
% This function has no output args, see OutputFcn.
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
% varargin   command line arguments to houghgui (see VARARGIN)

% Choose default command line output for houghgui
handles.output = hObject;

 % create the listener for the sliders
 handles.threshold_sliderListener = addlistener(handles.threshold_slider,'ContinuousValueChange', ...
                                      @(hFigure,eventdata) threshold_sliderContValCallback(...
                                        hObject,eventdata));
 handles.scale_sliderListener = addlistener(handles.scale_slider,'ContinuousValueChange', ...
                                      @(hFigure,eventdata) scale_sliderContValCallback(...
                                        hObject,eventdata));
 
set(handles.scale_slider, 'min', 0.05, 'max', 2.0, 'value', 1.0);

axes(handles.lines)
set(gca, 'ydir', 'reverse', 'xtick', [], 'ytick', [])
axes(handles.original_image)
set(gca, 'ydir', 'reverse', 'xtick', [], 'ytick', [])

% Update handles structure
guidata(hObject, handles);

% UIWAIT makes houghgui wait for user response (see UIRESUME)
% uiwait(handles.figure1);


% --- Outputs from this function are returned to the command line.
function varargout = houghgui_OutputFcn(hObject, eventdata, handles) 
% varargout  cell array for returning output args (see VARARGOUT);
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Get default command line output from handles structure
varargout{1} = handles.output;


% --- Executes on button press in load_button.
function load_button_Callback(hObject, eventdata, handles)
% hObject    handle to load_button (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
%Look for .png files
[file, path] = uigetfile('*.png');
handles.file = [path file];
RGB = imread([path file]);
scale = get(handles.scale_slider, 'value');
%Rescale image by slider position
RGB = imresize(RGB, scale);
axes(handles.original_image)
imshow(RGB)
%Limit axes to max size
xlim([1 466])
ylim([1 308])
handles.RGB = RGB;
guidata(hObject, handles);

% --- Executes on slider movement.
 function threshold_sliderContValCallback(hFigure,eventdata)
% hObject    handle to threshold_slider (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'Value') returns position of slider
%        get(hObject,'Min') and get(hObject,'Max') to determine range of slider
%Slider to adjust houghpeaks threshold value
handles = guidata(hFigure);
val = get(handles.threshold_slider, 'value');
caption = sprintf('Threshold = %1.2f (Fraction of peak detected value)', val);
set(handles.threshold_label, 'String', caption);


% --- Executes during object creation, after setting all properties.
function threshold_slider_CreateFcn(hObject, eventdata, handles)
% hObject    handle to threshold_slider (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: slider controls usually have a light gray background.
if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor',[.9 .9 .9]);
end


% --- Executes on button press in process_button.
function process_button_Callback(hObject, eventdata, handles)
% hObject    handle to process_button (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
maxlines = 1500;
%Convert to intensity and take Hough transform
I = im2bw(handles.RGB);
inverse = ~I;
[H,T,R] = hough(inverse);
%Use threshold to find peaks in Hough output matrix
threshold = get(handles.threshold_slider, 'value');
peaks = houghpeaks(H, maxlines, 'Threshold', threshold*max(H(:)));
lines = houghlines(inverse, T, R, peaks);
dimension = size(I);
axes(handles.lines)
cla
hold on
tx = [];
for line = 1:length(lines)
    %Find endpoints, plot detected lines, then compensate for overshoot
    xstart = min(max(lines(line).point1(1),10),456);
    ystart = min(max(lines(line).point1(2),10),298);
    xstop = min(max(lines(line).point2(1),10),456);
    ystop = min(max(lines(line).point2(2),10),298);
    theta = lines(line).theta;
    plot([xstart xstop], [ystart ystop], 'LineWidth', 2, 'Color', 'r')
    dx = xstop - xstart;
    dy = ystop - ystart;
    dist = sqrt(dx^2+dy^2);
    overshoot_comp = min(dist,9e-11*dist^5 - 1e-7*dist^4 + 6e-5*dist^3 - .0124*dist^2 + 1.2471*dist - 10);
    if (dx ~= 0) xstop = round(xstop - (overshoot_comp*dx/dist)); end
    ystop = round(ystop - (overshoot_comp*dy/dist));
    ystop = 308-ystop;
    ystart = 308-ystart;
    points = de2bi([xstart ystart xstop ystop], 16, 'left-msb');
    for point = 1:4
        %Convert to concatenated chars and add to transmission vector
        coord_bin = points(point,:);
        coord_dec = [bi2de(coord_bin(1:8), 'left-msb') bi2de(coord_bin(9:16), 'left-msb')];
        tx = [tx char(coord_dec(1)) char(coord_dec(2))];
    end
end
%Set axes to plotter max size and convert to graphics axes (y goes down)
xlim([1 466])
ylim([1 308])
set(gca, 'ydir', 'reverse', 'xtick', [], 'ytick', [])
tx = [tx char(0) char(0) char(0) char(0) char(0) char(0) char(0) char(0)];
handles.tx = tx;
guidata(hObject, handles);

% --- Executes on button press in send_button.
function send_button_Callback(hObject, eventdata, handles)
% hObject    handle to send_button (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
%Open serial code
s = serial('COM3');
fopen(s)
tx = handles.tx;
while (~isempty(tx))
    %Print 2 chars at once to serial connection, get 2 chars back to
    %acknowledge that PIC32 received them
    fprintf(s, tx(1:2))
    tx = tx(3:end);
    fgetl(s)
end
fclose(s)
delete(s)
clear s


% --- Executes on slider movement.
function scale_sliderContValCallback(hFigure,eventdata)
% hObject    handle to scale_slider (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'Value') returns position of slider
%        get(hObject,'Min') and get(hObject,'Max') to determine range of slider
%Slider to rescale image
handles = guidata(hFigure);
scale = get(handles.scale_slider, 'value');
caption = sprintf('Scale = %1.2fx', scale);
set(handles.scale_label, 'String', caption);




% --- Executes during object creation, after setting all properties.
function scale_slider_CreateFcn(hObject, eventdata, handles)
% hObject    handle to scale_slider (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: slider controls usually have a light gray background.
if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor',[.9 .9 .9]);
end


% --- Executes on slider movement.
function scale_slider_Callback(hObject, eventdata, handles)
% hObject    handle to scale_slider (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'Value') returns position of slider
%        get(hObject,'Min') and get(hObject,'Max') to determine range of slider
%Rescale image dynamically while sliding
scale = get(handles.scale_slider, 'value');
if isfield(handles, 'file')
    RGB = imread(handles.file);
    RGB = imresize(RGB, scale);
    axes(handles.original_image)
    imshow(RGB, 'parent', handles.original_image)
    xlim([1 466])
    ylim([1 308])
    handles.RGB = RGB;
    guidata(hObject, handles);
end
