function varargout = UntangleGUI(varargin)
% UNTANGLEGUI M-file for UntangleGUI.fig
% UNTANGLEGUI, by itself, creates a new UNTANGLEGUI or raises the existing
% singleton*.
%
% H = UNTANGLEGUI returns the handle to a new UNTANGLEGUI or the handle to
% the existing singleton*.
%
% UNTANGLEGUI('CALLBACK',hObject,eventData,handles,...) calls the local
% function named CALLBACK in UNTANGLEGUI.M with the given input arguments.
%
% UNTANGLEGUI('Property','Value',...) creates a new UNTANGLEGUI or raises the
% existing singleton*. Starting from the left, property value pairs are
% applied to the GUI before UntangleGUI_OpeningFcn gets called. An
% unrecognized property name or invalid value makes property application
% stop. All inputs are passed to UntangleGUI_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 UntangleGUI

% Last Modified by GUIDE v2.5 30-Sep-2013 09:19:29

% Begin initialization code - DO NOT EDIT
gui_Singleton = 1;
gui_State = struct('gui_Name', mfilename, ...
'gui_Singleton', gui_Singleton, ...
'gui_OpeningFcn', @UntangleGUI_OpeningFcn, ...
'gui_OutputFcn', @UntangleGUI_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 UntangleGUI is made visible.
function UntangleGUI_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 UntangleGUI (see VARARGIN)

% Choose default command line output for UntangleGUI
n = 20;
handles.output = hObject;
set(handles.n_slider,'Value',n,'min',4,'max',40,'SliderStep',[1/36,.1]);

[x,y,u,v,d,itMax] = GenEG(n);
Show(x,y,0,d,u,v)
handles.x = x; handles.y = y; % Define the vertices of the current polygon
handles.u = u; handles.v = v; % For displaying the limiting ellipse;
handles.d = d; % -d<=x<+d and -d<=y<=+d in the plot window
handles.itMax = itMax; % Maximum number of averagings
handles.it = 0; % number of averagings.

% Update handles structure
guidata(hObject, handles);

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

% --- Outputs from this function are returned to the command line.
function varargout = UntangleGUI_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 slider movement.
function n_slider_Callback(hObject, eventdata, handles)
% hObject handle to n_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

n = get(hObject,'Value');
n = round(n);
set(handles.n_edit,'String',sprintf('%2d',n));
% Generate a new example with the new n-value...
[x,y,u,v,d,itMax] = GenEG(n);
% Display...
Show(x,y,0,d,u,v)
% Save the key parameters in the handles structure...
handles.x = x; handles.y = y;
handles.u = u; handles.v = v;
handles.d = d; handles.itMax = itMax; handles.it = 0;
guidata(hObject, handles);

% --- Executes during object creation, after setting all properties.
function n_slider_CreateFcn(hObject, eventdata, handles)
% hObject handle to n_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

function n_edit_Callback(hObject, eventdata, handles)
% hObject handle to n_edit (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,'String') returns contents of n_edit as text
% str2double(get(hObject,'String')) returns contents of n_edit as a double

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

% Hint: edit controls usually have a white background on Windows.
% See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
set(hObject,'BackgroundColor','white');
end

function [x,y] = Simulate(x0,y0,d,k,itMax,speedy,u,v)
% x0 and y0 are column n-vectors that define the vertices of a normalized
% polygon P.
% k is a positive integer that represents the number of averagings that
% have been performed on some original polygon to obtain P.
% itMax a positive integer >=k.
% x and y are column n-vectors that define the vertices of a normalized
% polygon that is the result of itMax averagings of the same original
% polygon.
% u and v are vectors with the property that plot(u,v) displays the
% limiting ellipse.
% speedy has the value of 1 if a fast simulation is desired, 0 otherwise.
% d is a real number with the property that the simulation takes place in
% the square with vertices (d,d), (-d,d), (-d,-d), (d,-d).

% Set up the time delay based on the value of speedy...
if speedy
tDelay = 0.01;
else
tDelay = .15;
end
% The simulation...
x = x0;
y = y0;
for it=k+1:itMax
% Average and display..
[x,y] = AverageOnce(x,y);
if nargin==6
% Do not include the limiting ellipse...
Show(x,y,it,d)
else
% Include the limiting ellipse...
Show(x,y,it,d,u,v)
end
pause(tDelay)
end

function Show(x,y,k,d,u,v)
% Displays the polygon whose vertices are defined by the column n-vectors
% x and y.
% k is an integer, typically the number of completed averaging steps.
% d is a positive real. The x and y ranges will be -d to +d.
% If nargin==6, then the u and v are vector of the limiting ellipse and it
% will be displayed.
% A call of the form Show(x,y,k,d) is also valid but does not display the
% limiting ellipse.

plot([x;x(1)],[y;y(1)],'r',x,y,'.r','Markersize',20)
axis([-d d -d d])
axis square off
title(sprintf('n = %2d Number of Averagings = %1d',length(x),k),'FontSize',18)
hold on
plot([d d -d -d d],[-d d d -d -d],'linewidth',10)
if nargin==6
plot(u,v,'k','linewidth',2')
plot([-d d],[-d d],'--k','linewidth',2)
plot([-d d],[d -d],'--k','linewidth',2)
end
hold off

function [xNew,yNew] = AverageOnce(x,y)
% x and y are column n-vectors that define the vertices of a normalized
% polygon P.
% xNew and yNew are column n-vectors that define the vertices of a normalized
% polygon Q obtained by connecting the midpoints of P's edges.
n = length(x);
xNew = (x + [x(2:n);x(1)])/2; xNew = xNew - mean(xNew); xNew = xNew/norm(xNew);
yNew = (y + [y(2:n);y(1)])/2; yNew = yNew - mean(yNew); yNew = yNew/norm(yNew);

function [x,y,u,v,d,itMax] = GenEG(n)
% n is an integer >= 4.
% x and y are column n-vectors that define the vertices of a normalized polygon.
% u and v are vectors with the property that plot(u,v) displays the
% limiting ellipse.
% d is a positive real with the property that the simulation takes
% place in the square with vertices (d,d), (-d,d), (-d,-d), (d,-d).
% itMax is a positive integer with the property that with that many
% iterations, the polygon has visiably converged to the limiting ellipse.

% x and y vectors define the normalized random polygon P...
x = rand(n,1); x = x-mean(x); x = x/norm(x);
y = rand(n,1); y = y-mean(y); y = y/norm(y);
% u and v vectors...
tau = (2*pi/n)*(0:n-1)';
c = sqrt(2/n)*cos(tau);
s = sqrt(2/n)*sin(tau);
cos_theta_u = (c'*x)/sqrt((c'*x)^2+(s'*x)^2);
sin_theta_u = (s'*x)/sqrt((c'*x)^2+(s'*x)^2);
cos_theta_v = (c'*y)/sqrt((c'*y)^2+(s'*y)^2);
sin_theta_v = (s'*y)/sqrt((c'*y)^2+(s'*y)^2);
R = sqrt(2/n)*[cos_theta_u sin_theta_u ; cos_theta_v sin_theta_v];
t = linspace(0,2*pi);
M = R*[cos(t);sin(t)];
u = M(1,:)';
v = M(2,:)';
% Simulation parameters...
d = 1.6*max(max(u),max(v));
itMax = ceil(3./(-log10( 1-(3/2)*(pi/n)^2 )));

% --- Executes on button press in NewPoly_button.
function NewPoly_button_Callback(hObject, eventdata, handles)
% hObject handle to NewPoly_button (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)

% Start a new example
n = get(handles.n_slider,'Value');
[x,y,u,v,d,itMax] = GenEG(n);
% Display...
Show(x,y,0,d,u,v)
% Save the key parameters in the handles structure...
handles.x = x; handles.y = y;
handles.u = u; handles.v = v;
handles.d = d; handles.itMax = itMax; handles.it = 0;
guidata(hObject, handles);