Difference between revisions of "User:Zeracles/Starmap/Minimal Spanning Tree"
< User:Zeracles | Starmap
Jump to navigation
Jump to search
m (link) |
(added comments) |
||
Line 3: | Line 3: | ||
It definitely needs some improvement, but for now - | It definitely needs some improvement, but for now - | ||
% minimal spannng tree in matlab | % minimal spannng tree in matlab | ||
+ | % see http://www.star-control.com/forum/index.php/topic,1660.msg33938.html#msg33938 | ||
% by Anthony Smith (Zeracles) | % by Anthony Smith (Zeracles) | ||
% astroant@hotmail.com | % astroant@hotmail.com | ||
Line 67: | Line 68: | ||
branches=[]; | branches=[]; | ||
− | while lengthremainingpositions>0 | + | while lengthremainingpositions>0 % keep going until nothing remains unlinked to the tree (the ``remainingpositions") |
mindistances=[]; | mindistances=[]; | ||
− | for i=linspace(1,lengthtreepositions,lengthtreepositions) | + | for i=linspace(1,lengthtreepositions,lengthtreepositions) % search around each of the tree positions for remainingpositions |
+ | % retrieve coordinates of a tree position | ||
treepositionx=inputpositions(treeindices(i),1); | treepositionx=inputpositions(treeindices(i),1); | ||
treepositiony=inputpositions(treeindices(i),2); | treepositiony=inputpositions(treeindices(i),2); | ||
Line 79: | Line 81: | ||
occupiedbox=0; | occupiedbox=0; | ||
searchfactor=1; | searchfactor=1; | ||
− | while occupiedbox==0 | + | while occupiedbox==0 % search for remainingpositions inside a box that grows until some are found |
boxradius=searchfactor*searchincrement; | boxradius=searchfactor*searchincrement; | ||
Line 100: | Line 102: | ||
mindistancecandidates=[]; | mindistancecandidates=[]; | ||
mindistancecandidateindices=[]; | mindistancecandidateindices=[]; | ||
− | if sum(closerremainingmask)>0 | + | if sum(closerremainingmask)>0 % if there are remainingpositions inside the box, calculate the actual distances to them |
for k=find(closerremainingmask==1) | for k=find(closerremainingmask==1) | ||
branchcandidatex=remainingpositionxs(k); | branchcandidatex=remainingpositionxs(k); | ||
Line 107: | Line 109: | ||
branchcandidatez=remainingpositionzs(k); | branchcandidatez=remainingpositionzs(k); | ||
end | end | ||
− | branchcandidateindex=remainingpositionindices(k); | + | branchcandidateindex=remainingpositionindices(k); % set up to remember the index of each prospective link destination |
if dimensions==2 | if dimensions==2 | ||
Line 122: | Line 124: | ||
end | end | ||
if numel(mindistancecandidates)>0 | if numel(mindistancecandidates)>0 | ||
− | mindistance=[min(mindistancecandidates),treeindex,mindistancecandidateindices(find(mindistancecandidates==min(mindistancecandidates)))]; | + | mindistance=[min(mindistancecandidates),treeindex,mindistancecandidateindices(find(mindistancecandidates==min(mindistancecandidates)))]; % minimum distances carry the indices of the prospective link destination |
mindistances=[mindistances;mindistance]; | mindistances=[mindistances;mindistance]; | ||
occupiedbox=1; | occupiedbox=1; | ||
end | end | ||
− | searchfactor=searchfactor+1; | + | searchfactor=searchfactor+1; % make the search box bigger |
end | end | ||
end | end | ||
Line 133: | Line 135: | ||
branchindex=find(branchdistance==mindistances(:,1)); | branchindex=find(branchdistance==mindistances(:,1)); | ||
numberbranchcandidates=numel(branchindex); | numberbranchcandidates=numel(branchindex); | ||
− | if numberbranchcandidates>1 | + | if numberbranchcandidates>1 % if there's a tie for minimum length |
branchindex=branchindex(ceil(numberbranchcandidates*rand(1))); | branchindex=branchindex(ceil(numberbranchcandidates*rand(1))); | ||
end | end | ||
+ | |||
+ | % add this branch to the tree | ||
branch=mindistances(branchindex,:); | branch=mindistances(branchindex,:); | ||
branches=[branches;branch]; | branches=[branches;branch]; | ||
+ | % add that location to the tree | ||
treeindices=[treeindices;branch(3)]; | treeindices=[treeindices;branch(3)]; | ||
lengthtreepositions=lengthtreepositions+1; | lengthtreepositions=lengthtreepositions+1; | ||
+ | % remove that location from the remainingpositions | ||
remainingmask=ones(lengthremainingpositions,1); | remainingmask=ones(lengthremainingpositions,1); | ||
removed=find(remainingpositionindices==branch(3)); | removed=find(remainingpositionindices==branch(3)); | ||
Line 158: | Line 164: | ||
save('branches','branches') | save('branches','branches') | ||
+ | % for plotting | ||
sizebranches=size(branches); | sizebranches=size(branches); | ||
numberofbranches=sizebranches(1); | numberofbranches=sizebranches(1); |
Revision as of 09:04, 18 December 2009
Also downloadable here
It definitely needs some improvement, but for now -
% minimal spannng tree in matlab % see http://www.star-control.com/forum/index.php/topic,1660.msg33938.html#msg33938 % by Anthony Smith (Zeracles) % astroant@hotmail.com load('inputpositions') remainingpositions=inputpositions; % detect input properties and set up index sizeremainingpositions=size(remainingpositions); lengthremainingpositions=sizeremainingpositions(1); dimensions=sizeremainingpositions(2); index=transpose(linspace(1,lengthremainingpositions,lengthremainingpositions)); remainingpositionxs=remainingpositions(:,1); remainingpositionys=remainingpositions(:,2); if dimensions>2 remainingpositionzs=remainingpositions(:,3); end % initialise search parameters minx=min(remainingpositionxs); maxx=max(remainingpositionxs); xextent=minx*maxx; miny=min(remainingpositionys); maxy=max(remainingpositionys); yextent=miny*maxy; if dimensions>2 minz=min(remainingpositionzs); maxz=max(remainingpositionzs); zextent=minz*maxz; end if dimensions==2 measure=xextent*yextent; localmeasure=measure/lengthremainingpositions; searchincrement=((10*localmeasure)/pi)^(1/2); end if dimensions==3 measure=xextent*yextent*zextent; localmeasure=measure/lengthremainingpositions; searchincrement=((10*localmeasure)/(4/3)/pi)^(1/3); end % initialise with a seed point seedindex=1; maskvector=zeros(lengthremainingpositions,1); maskvector(seedindex)=1; remainingpositionxs=remainingpositionxs(find(maskvector==0)); remainingpositionys=remainingpositionys(find(maskvector==0)); if dimensions>2 remainingpositionzs=remainingpositionzs(find(maskvector==0)); end remainingpositionindices=index(find(maskvector==0)); lengthremainingpositions=lengthremainingpositions-1; treeindices=index(seedindex,:); lengthtreepositions=1; branches=[]; while lengthremainingpositions>0 % keep going until nothing remains unlinked to the tree (the ``remainingpositions") mindistances=[]; for i=linspace(1,lengthtreepositions,lengthtreepositions) % search around each of the tree positions for remainingpositions % retrieve coordinates of a tree position treepositionx=inputpositions(treeindices(i),1); treepositiony=inputpositions(treeindices(i),2); if dimensions>2 treepositionz=inputpositions(treeindices(i),3); end treeindex=treeindices(i); occupiedbox=0; searchfactor=1; while occupiedbox==0 % search for remainingpositions inside a box that grows until some are found boxradius=searchfactor*searchincrement; boxminx=treepositionx-boxradius; boxmaxx=treepositionx+boxradius; boxminy=treepositiony-boxradius; boxmaxy=treepositiony+boxradius; if dimensions>2 boxminz=treepositionz-boxradius; boxmaxz=treepositionz+boxradius; end if dimensions==2 closerremainingmask=(boxminx<=remainingpositionxs).*(remainingpositionxs<=boxmaxx).*(boxminy<=remainingpositionys).*(remainingpositionys<=boxmaxy); end if dimensions==3 closerremainingmask=(boxminx<=remainingpositionxs).*(remainingpositionxs<=boxmaxx).*(boxminy<=remainingpositionys).*(remainingpositionys<=boxmaxy).*(boxminz<=remainingpositionzs).*(remainingpositionzs<=boxmaxz); end mindistancecandidates=[]; mindistancecandidateindices=[]; if sum(closerremainingmask)>0 % if there are remainingpositions inside the box, calculate the actual distances to them for k=find(closerremainingmask==1) branchcandidatex=remainingpositionxs(k); branchcandidatey=remainingpositionys(k); if dimensions>2 branchcandidatez=remainingpositionzs(k); end branchcandidateindex=remainingpositionindices(k); % set up to remember the index of each prospective link destination if dimensions==2 mindistancecandidate=((branchcandidatex-treepositionx).^2+(branchcandidatey-treepositiony).^2).^(1/2); end if dimensions==3 mindistancecandidate=((branchcandidatex-treepositionx).^2+(branchcandidatey-treepositiony).^2+(branchcandidatez-treepositionz).^2).^(1/2); end if mindistancecandidate<=boxradius mindistancecandidates=[mindistancecandidates;mindistancecandidate]; mindistancecandidateindices=[mindistancecandidateindices;branchcandidateindex]; end end end if numel(mindistancecandidates)>0 mindistance=[min(mindistancecandidates),treeindex,mindistancecandidateindices(find(mindistancecandidates==min(mindistancecandidates)))]; % minimum distances carry the indices of the prospective link destination mindistances=[mindistances;mindistance]; occupiedbox=1; end searchfactor=searchfactor+1; % make the search box bigger end end branchdistance=min(mindistances(:,1)); branchindex=find(branchdistance==mindistances(:,1)); numberbranchcandidates=numel(branchindex); if numberbranchcandidates>1 % if there's a tie for minimum length branchindex=branchindex(ceil(numberbranchcandidates*rand(1))); end % add this branch to the tree branch=mindistances(branchindex,:); branches=[branches;branch]; % add that location to the tree treeindices=[treeindices;branch(3)]; lengthtreepositions=lengthtreepositions+1; % remove that location from the remainingpositions remainingmask=ones(lengthremainingpositions,1); removed=find(remainingpositionindices==branch(3)); remainingmask(removed)=0; remainingpositionindices=remainingpositionindices(find(remainingmask)); remainingpositionxs=remainingpositionxs(find(remainingmask)); remainingpositionys=remainingpositionys(find(remainingmask)); if dimensions>2 remainingpositionzs=remainingpositionzs(find(remainingmask)); end lengthremainingpositions=lengthremainingpositions-1; end save('branches','branches') % for plotting sizebranches=size(branches); numberofbranches=sizebranches(1); figure hold on box on plot(inputpositions(:,1),inputpositions(:,2),'k.') for i=linspace(1,numberofbranches,numberofbranches) startindex=branches(i,2); finishindex=branches(i,3); startx=inputpositions(startindex,1); starty=inputpositions(startindex,2); finishx=inputpositions(finishindex,1); finishy=inputpositions(finishindex,2); line([startx;finishx],[starty;finishy],'Color','k') end