|
clear all; |
|
hold off; |
|
|
|
bl = [0 0]; % This should remain |
|
tr = [860 500]; % Size of field |
|
|
|
%% CSV Data |
|
data = fopen('data.csv','r'); |
|
out = fscanf(data,'%d,%d,%f,%f,%f,%f\n',[6 inf]); |
|
fclose(data); |
|
|
|
%% Generating Random test-data |
|
% out = []; |
|
% for n=1:600 |
|
% out = [out;rand * 800,rand * 500,rand,rand,rand,rand]; |
|
% end |
|
% out = out'; |
|
|
|
raw_points = out(1:2,:)'; |
|
point_colours = out(3:6,:)'; |
|
|
|
% Scaling to make it pretty! |
|
raw_points(:,1) = log(raw_points(:,1) - min(raw_points(:,1)) + 2e7); |
|
raw_points(:,2) = log(raw_points(:,2) - min(raw_points(:,2)) + 1000); |
|
|
|
|
|
% Processing |
|
|
|
low = min(raw_points); |
|
high = max(raw_points); |
|
points = (raw_points - ones([length(raw_points) 2]) * [low(1) 0;0 low(2)]) * [(tr(1)-bl(1))/(high(1)-low(1)) 0;0 (tr(2)-bl(2))/(high(2)-low(2))] + ones([length(raw_points) 2]) * [bl(1) 0;0 bl(2)]; |
|
|
|
trios = []; |
|
lines = []; |
|
|
|
cells = cell(1,length(points)); |
|
|
|
plot([bl(1) bl(1) tr(1) tr(1) bl(1)],[bl(2) tr(2) tr(2) bl(2) bl(2)],'k:'); |
|
hold on; |
|
|
|
|
|
% Find good trios |
|
trios = delaunay(points(:,1),points(:,2)); |
|
|
|
mus = linspace(-6,6,21); |
|
|
|
% The list of cells we shouldn't look for fake sites |
|
dont_fake = []; |
|
|
|
for trio=trios' |
|
d = trio(1); |
|
e = trio(2); |
|
f = trio(3); |
|
la12 = 0.5; |
|
la13 = 0.5; |
|
la23 = 0.5; |
|
|
|
m12 = points(d,1:2) + la12*(points(e,1:2)-points(d,1:2)); |
|
m13 = points(d,1:2) + la13*(points(f,1:2)-points(d,1:2)); |
|
m23 = points(e,1:2) + la23*(points(f,1:2)-points(e,1:2)); |
|
|
|
perp12 = [points(e,2) - points(d,2), points(d,1) - points(e,1)]; |
|
perp13 = [points(f,2) - points(d,2), points(d,1) - points(f,1)]; |
|
perp23 = [points(f,2) - points(e,2), points(e,1) - points(f,1)]; |
|
|
|
mu12 = (m12(2) * perp13(1) - m13(2) * perp13(1) - m12(1) * perp13(2) + m13(1) * perp13(2))/(perp12(1) * perp13(2) - perp12(2) * perp13(1)); |
|
|
|
% These lines will produce helpers in the MATLAB plot output, just for debugging really |
|
% a = (m12'*ones([1 21]) + (mus' * perp12)')'; |
|
% b = (m13'*ones([1 21]) + (mus' * perp13)')'; |
|
% c = (m23'*ones([1 21]) + (mus' * perp23)')'; |
|
% plot(a(:,1),a(:,2),'r-'); |
|
% plot(m12(1),m12(2),'rx'); |
|
% plot(b(:,1),b(:,2),'g-'); |
|
% plot(m13(1),m13(2),'gx'); |
|
% plot(c(:,1),c(:,2),'b-'); |
|
% plot(m23(1),m23(2),'bx'); |
|
|
|
C = m12 + mu12*perp12; |
|
|
|
% Check to find the point closest to the line: the calculated point, or |
|
% the two points where the perpendicular hits the 4 edges |
|
newCs = []; |
|
for t=[m12 perp12;m13 perp13;m23 perp23]' |
|
m = t(1:2)'; |
|
perp = t(3:4)'; |
|
|
|
hits = [ |
|
[m(1) + ((tr(2) - m(2))/perp(2))*perp(1) tr(2)]; % top border |
|
[tr(1) m(2) + ((tr(1) - m(1))/perp(1))*perp(2)]; % right border |
|
[C(1) C(2)]; ... % The calculated point |
|
[m(1) + ((bl(2) - m(2))/perp(2))*perp(1) bl(2)]; % bottom border |
|
[bl(1) m(2) + ((bl(1) - m(1))/perp(1))*perp(2)] % left border |
|
]; |
|
|
|
vals = ((hits(:,1) + hits(:,2)) - (m(1) + m(2))); % Distance from the midpoint |
|
vals = vals * vals(3); % make bounds in the opposite direction -ve |
|
|
|
vals = vals .* (vals > 0) + (vals < 0) * 9e50; % make the -ve items enormous |
|
|
|
[v index] = min(vals); % Find the minimum value |
|
|
|
newC = hits(index,:); |
|
|
|
% plot(hits(:,1),hits(:,2),'db'); |
|
|
|
% More helper lines |
|
% for h=hits' |
|
% h |
|
% plot([h(1) m(1)],[h(2) m(2)],'k-o'); |
|
% axis([bl(1)-1000,tr(1)+1000,bl(2)-1000,tr(2)+1000]); |
|
% |
|
% end |
|
|
|
if ~(newC(1) == C(1) && newC(2) == C(2)) |
|
newCs = [newCs;newC]; |
|
end |
|
% Add to arrays for each cell, then only add to cell if its one of |
|
% the outer two |
|
|
|
end |
|
|
|
if (length(newCs) < 3) |
|
cells{d} = [cells{d};C]; |
|
cells{e} = [cells{e};C]; |
|
cells{f} = [cells{f};C]; |
|
|
|
plot(C(1),C(2),'sm'); |
|
else |
|
dont_fake = [dont_fake d e f]; |
|
ls = [0 0 0]; |
|
% 1-2 length |
|
ls(1) = (newCs(2,1) - newCs(1,1)).^2 + (newCs(2,2) - newCs(1,2)).^2; |
|
|
|
% 2-3 length |
|
ls(2) = (newCs(3,1) - newCs(2,1)).^2 + (newCs(3,2) - newCs(2,2)).^2; |
|
|
|
% 3-1 length |
|
ls(3) = (newCs(1,1) - newCs(3,1)).^2 + (newCs(1,2) - newCs(3,2)).^2; |
|
|
|
[v index] = max(ls); % Find the largest distance and don't plot |
|
|
|
if (index == 1) |
|
cells{d} = [cells{d};newCs(1,:)]; |
|
cells{d} = [cells{d};newCs(2,:)]; |
|
|
|
cells{e} = [cells{e};newCs(1,:)]; |
|
cells{f} = [cells{f};newCs(2,:)]; |
|
|
|
% plot(newCs(1,1),newCs(1,2),'ro'); |
|
% plot(newCs(2,1),newCs(2,2),'ro'); |
|
% plot(newCs(3,1),newCs(3,2),'rx'); |
|
elseif (index == 2) |
|
cells{f} = [cells{f};newCs(2,:)]; |
|
cells{f} = [cells{f};newCs(3,:)]; |
|
|
|
cells{d} = [cells{d};newCs(2,:)]; |
|
cells{e} = [cells{e};newCs(3,:)]; |
|
|
|
% plot(newCs(1,1),newCs(1,2),'gx'); |
|
% plot(newCs(2,1),newCs(2,2),'go'); |
|
% plot(newCs(3,1),newCs(3,2),'go'); |
|
elseif (index ==3) |
|
cells{e} = [cells{e};newCs(1,:)]; |
|
cells{e} = [cells{e};newCs(3,:)]; |
|
|
|
cells{d} = [cells{d};newCs(1,:)]; |
|
cells{f} = [cells{f};newCs(3,:)]; |
|
|
|
% plot(newCs(1,1),newCs(1,2),'bo'); |
|
% plot(newCs(2,1),newCs(2,2),'bx'); |
|
% plot(newCs(3,1),newCs(3,2),'bo'); |
|
end |
|
end |
|
|
|
lines = [lines;struct('m',m12,'d',perp12,'points',[d,e],'C',C);struct('m',m13,'d',perp13,'points',[d,f],'C',C);struct('m',m23,'d',perp23,'points',[e,f],'C',C)]; |
|
|
|
% axis([bl(1)-50,tr(1)+50,bl(2)-50,tr(2)+50]); |
|
end |
|
|
|
|
|
% Finding Edge (fake) sites |
|
lid = 1; |
|
while lid <= length(lines) |
|
a = (lines(lid).m'*ones([1 21]) + (mus' * lines(lid).d)')'; |
|
|
|
plot(a(:,1),a(:,2),'r:'); |
|
plot(lines(lid).m(1),lines(lid).m(2),'rx'); |
|
|
|
% Neg = 1, Pos = 2 |
|
ready = [0,0]; |
|
|
|
pid = 1; |
|
for p=points' |
|
if ~(lines(lid).points(1) == pid || lines(lid).points(2) == pid) |
|
p = p'; |
|
v = dot(lines(lid).d,p - lines(lid).m); |
|
if v > 0 |
|
ready(2) = ready(2) + 1; |
|
elseif v < 0 |
|
ready(1) = ready(1) + 1; |
|
end |
|
end |
|
|
|
pid = pid + 1; |
|
end |
|
|
|
ready(1) = ready(1) < 1; |
|
ready(2) = ready(2) < 1; |
|
|
|
if (ready(1) || ready(2)) |
|
%x |
|
% To hit the left |
|
intersector1 = (bl(1) - lines(lid).m(1))/lines(lid).d(1); |
|
y1 = lines(lid).m(2) + intersector1 * lines(lid).d(2); |
|
% To hit the right |
|
intersector2 = (tr(1) - lines(lid).m(1))/lines(lid).d(1); |
|
y2 = lines(lid).m(2) + intersector2 * lines(lid).d(2); |
|
|
|
|
|
if (ready(1)) |
|
if (intersector1 <= 0 && y1 >= bl(2) && y1 <= tr(2) && lines(lid).C(1) >= bl(1)) |
|
newsite = [bl(1) y1]; |
|
plot(newsite(1),newsite(2),'sr'); |
|
|
|
cells{lines(lid).points(1)} = [cells{lines(lid).points(1)};newsite]; |
|
cells{lines(lid).points(2)} = [cells{lines(lid).points(2)};newsite]; |
|
end |
|
if (intersector2 <= 0 && y2 >= bl(2) && y2 <= tr(2) && lines(lid).C(1) <= tr(1)) |
|
newsite = [tr(1) y2]; |
|
plot(newsite(1),newsite(2),'sg'); |
|
|
|
cells{lines(lid).points(1)} = [cells{lines(lid).points(1)};newsite]; |
|
cells{lines(lid).points(2)} = [cells{lines(lid).points(2)};newsite]; |
|
end |
|
end |
|
if (ready(2)) |
|
if (intersector1 >= 0 && y1 >= bl(2) && y1 <= tr(2) && lines(lid).C(1) >= bl(1)) |
|
newsite = [bl(1) y1]; |
|
plot(newsite(1),newsite(2),'sb'); |
|
|
|
cells{lines(lid).points(1)} = [cells{lines(lid).points(1)};newsite]; |
|
cells{lines(lid).points(2)} = [cells{lines(lid).points(2)};newsite]; |
|
end |
|
if (intersector2 >= 0 && y2 >= bl(2) && y2 <= tr(2) && lines(lid).C(1) <= tr(1)) |
|
newsite = [tr(1) y2]; |
|
plot(newsite(1),newsite(2),'sk'); |
|
|
|
cells{lines(lid).points(1)} = [cells{lines(lid).points(1)};newsite]; |
|
cells{lines(lid).points(2)} = [cells{lines(lid).points(2)};newsite]; |
|
end |
|
end |
|
|
|
%y |
|
% To hit the bottom |
|
intersector1 = (bl(2) - lines(lid).m(2))/lines(lid).d(2); |
|
x1 = lines(lid).m(1) + intersector1 * lines(lid).d(1); |
|
% To hit the top |
|
intersector2 = (tr(2) - lines(lid).m(2))/lines(lid).d(2); |
|
x2 = lines(lid).m(1) + intersector2 * lines(lid).d(1); |
|
|
|
if (ready(1)) |
|
if (intersector1 <= 0 && x1 >= bl(1) && x1 <= tr(1) && lines(lid).C(2) >= bl(2)) |
|
newsite = [x1 bl(2)]; |
|
plot(newsite(1),newsite(2),'dr'); |
|
|
|
cells{lines(lid).points(1)} = [cells{lines(lid).points(1)};newsite]; |
|
cells{lines(lid).points(2)} = [cells{lines(lid).points(2)};newsite]; |
|
end |
|
if (intersector2 <= 0 && x2 >= bl(1) && x2 <= tr(1) && lines(lid).C(2) <= tr(2)) |
|
newsite = [x2 tr(2)]; |
|
plot(newsite(1),newsite(2),'dg'); |
|
|
|
cells{lines(lid).points(1)} = [cells{lines(lid).points(1)};newsite]; |
|
cells{lines(lid).points(2)} = [cells{lines(lid).points(2)};newsite]; |
|
end |
|
end |
|
if (ready(2)) |
|
if (intersector1 >= 0 && x1 >= bl(1) && x1 <= tr(1) && lines(lid).C(2) >= bl(2)) |
|
newsite = [x1 bl(2)]; |
|
plot(newsite(1),newsite(2),'db'); |
|
|
|
cells{lines(lid).points(1)} = [cells{lines(lid).points(1)};newsite]; |
|
cells{lines(lid).points(2)} = [cells{lines(lid).points(2)};newsite]; |
|
end |
|
if (intersector2 >= 0 && x2 >= bl(1) && x2 <= tr(1) && lines(lid).C(2) <= tr(2)) |
|
newsite = [x2 tr(2)]; |
|
plot(newsite(1),newsite(2),'dk'); |
|
|
|
cells{lines(lid).points(1)} = [cells{lines(lid).points(1)};newsite]; |
|
cells{lines(lid).points(2)} = [cells{lines(lid).points(2)};newsite]; |
|
end |
|
end |
|
|
|
end |
|
|
|
lid = lid + 1; |
|
end |
|
|
|
for corner = [bl' tr' [bl(1);tr(2)] [tr(1);bl(2)]] |
|
% Find nearest point, add the corner as a (fake) site to the point |
|
closest = []; |
|
r2 = inf; |
|
p = 1; |
|
while p <= length(points) |
|
% plot(points(p,1),points(p,2),'ko'); |
|
|
|
new_r2 = (points(p,1) - corner(1))^2 + (points(p,2) - corner(2))^2; |
|
if (new_r2 < r2) |
|
closest = [p]; |
|
r2 = new_r2; |
|
elseif (new_r2 == r2) |
|
closest = [closest p]; |
|
end |
|
p = p + 1; |
|
end |
|
for p=closest |
|
cells{p} = [cells{p};corner']; |
|
end |
|
end |
|
|
|
axis([bl(1)-50,tr(1)+50,bl(2)-50,tr(2)+50]); |
|
animate = 'var counter = 0;function startup() {animate()}; function animate() {var is;var mult;var cells = document.getElementsByTagName(''polygon'');for (cell in cells) {if (cell >= 0) {is = cells[cell].getAttribute(''rel'');mult = Math.cos((1 - is) * counter * 0.05);cells[cell].setAttribute(''fill-opacity'',1- mult*mult*(1 - is));}}counter++;setTimeout(''animate()'',60)}'; |
|
|
|
fp = fopen('output.svg','w'); |
|
fwrite(fp,sprintf('<?xml version="1.0" standalone="no"?>\n<svg onload="startup()" viewBox = "%.0f %.0f %.0f %.0f" version = "1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">\n<script>%s</script>\n',bl(1),bl(2),tr(1),tr(2),animate)); |
|
i = 1; |
|
while i <= length(cells) |
|
% Sort sites |
|
len=length(cells{i}(:,1)); |
|
av = [sum(cells{i}(:,1)) sum(cells{i}(:,2))]/len; |
|
|
|
angle = atan2(cells{i}(:,2)-av(2),cells{i}(:,1)-av(1)); |
|
|
|
[angle_sorted,perm]=sort(angle); |
|
p_sorted = cells{i}; |
|
p_sorted(:,1) = cells{i}(perm,1); |
|
p_sorted(:,2) = cells{i}(perm,2); |
|
|
|
%patch(p_sorted(:,1),p_sorted(:,2),i); |
|
|
|
p_str = ''; |
|
for p=p_sorted' |
|
p_str = sprintf('%s %.0f,%.0f',p_str,p(1),tr(2) - p(2) + bl(2)); |
|
end |
|
fwrite(fp,sprintf(' <polygon id="cell-%.0f" points = "%s" rel="%.2f" fill-opacity="%.2f" style="fill:rgb(%.0f,%.0f,%.0f);" stroke = "black" stroke-width = "1"/>\n',i,p_str,1 - point_colours(i,1),1 - point_colours(i,1),point_colours(i,2)*255,point_colours(i,3)*255,point_colours(i,4)*255)); |
|
i = i + 1; |
|
end |
|
fwrite(fp,'</svg>'); |
|
fclose(fp); |