% Demo of perceptron learning

% Roger Jang, Oct-8-96

figure('name', 'Iterative Solution', 'NumberTitle', 'off');
x1 = -1; y1 = 2*rand-1;
x2 = 1; y2 = 2*rand-1;
lineH(1) = line([x1 x2], [y1 y2], 'erase', 'xor');
set(lineH(1), 'userdata', [x1, y1; x2 y2]);

y3 = -1; x3 = 2*rand-1;
y4 = 1; x4 = 2*rand-1;
lineH(2) = line([x3 x4], [y3 y4], 'erase', 'xor');
set(lineH(2), 'userdata', [x3, y3; x4, y4]);

axis([-1 1 -1 1]);
axis image; set(gca, 'box', 'on');

data = [x1, y1; x2, y2; x3, y3; x4, y4];
data_n = size(data, 1);
for i = 1:data_n,
	dotH(i) = line(data(i,1), data(i,2), ...
		'linestyle', 'o', 'color', 'c', 'erase', 'xor');
end
motionH = line(nan, nan, 'color', 'g', 'erase', 'none');

AxisH = gca; FigH = gcf;
curr_info = get(AxisH, 'CurrentPoint');
current_x = curr_info(1,1);

% The following is for animation
% action when button is first pushed down
action1 = ['curr_info=get(AxisH, ''currentPoint'');', ...
	'start_x=curr_info(1,1);', ...
	'start_y=curr_info(1,2);', ...
	'prev_x=start_x;', ...
	'prev_y=start_y;', ...
	'[dist,index]=min(sqrt(sum(((ones(data_n,1)*[start_x start_y]-data(:, 1:2)).^2)'')));'...
	'if dist > 0.1, index = 0; end;', ...
	'freeze=1;'];
% actions after the mouse is pushed down
action2 = ['if index ~= 0,', ...
	'curr_info=get(AxisH, ''currentPoint'');', ...
	'curr_x=curr_info(1,1);', ...
	'curr_y=curr_info(1,2);', ...
	'data(index,1) = data(index,1)+curr_x-prev_x;', ...
	'if data(index,1)<-1, data(index,1)=-1; end;', ...
	'if data(index,1)>1, data(index,1)=1; end;', ...
	'data(index,2) = data(index,2)+curr_y-prev_y;', ...
	'if data(index,2)<-1, data(index,2)=-1; end;', ...
	'if data(index,2)>1, data(index,2)=1; end;', ...
	'prev_x = curr_x;', ...
	'prev_y = curr_y;', ...
	'set(dotH(index),''xdata'',data(index,1),''ydata'',data(index,2));', ...
	'line_index = floor((index-1)/2)+1;', ...
	'new_x = data(2*line_index-1:2*line_index, 1);', ...
	'new_y = data(2*line_index-1:2*line_index, 2);', ...
	'set(lineH(line_index),''xdata'',new_x,''ydata'',new_y);', ...
	'set(lineH(line_index),''userdata'',[new_x new_y]);', ...
	'end'];
% action when button is released
action3 = ['set(FigH, ''color'', get(FigH, ''color''));', ...
	'freeze=0;', ...
	'axis off; axis on;'];

% temporary storage for the recall in the down_action
set(AxisH,'UserData',action2);

% set action when the mouse is pushed down
down_action=[ ...
    'set(FigH,''WindowButtonMotionFcn'',get(AxisH,''UserData''));' ...
    action1];
set(FigH,'WindowButtonDownFcn',down_action);

% set action when the mouse is released
up_action=[ ...
    'set(FigH,''WindowButtonMotionFcn'','' '');', action3];
set(FigH,'WindowButtonUpFcn',up_action);

% Make everything interruptible
set(findobj(FigH,'Interrupt','no'), 'Interrupt','yes');

stop = 0;
freeze = 0;
stopH = uicontrol('string', 'Stop', 'callback', 'stop=1;', 'inter', 'yes');

% The main loop
tmp = get(lineH(1), 'userdata');
now = tmp(1, :);
%for i = 1:100,
while ~stop,
	% Horizontal motion from line 1 to line 2
	drawnow;
%	fprintf('Next movement --> horizontal to line 2\n');
	if ~freeze,
%	pause;
	next = now;
	tmp = get(lineH(2), 'userdata');
	x1 = tmp(1,1); y1 = tmp(1,2);
	x2 = tmp(2,1); y2 = tmp(2,2);
	slope = (y2-y1)/(x2-x1);
	next(1) = (now(2)-y1)/slope+x1;
	set(motionH, 'xdata', [now(1) next(1)], 'ydata', [now(2) next(2)]);
	now = next;
	end
	
	% Vertical motion from line 2 to line 1
	drawnow;
%	fprintf('Next movement --> vertical to line 1\n');
	if ~freeze,
%	pause;
	next = now;
	tmp = get(lineH(1), 'userdata');
	x1 = tmp(1,1); y1 = tmp(1,2);
	x2 = tmp(2,1); y2 = tmp(2,2);
	slope = (y2-y1)/(x2-x1);
	next(2) = (now(1)-x1)*slope+y1;
	set(motionH, 'xdata', [now(1) next(1)], 'ydata', [now(2) next(2)]);
	now = next;
	end
end
