function [siz, str] = findGroups3d(ARRAY) % findgroups3d() - Sort array into groups and report the groups % % The findgroups3d function produces a structure in which each element % (row) of the structure is a list array of all the individuals (fish #) % who are together in a single group. The group is defined as being within % d distance from each other. The algorithm treats individuals as being in % the same group if they are within d cm from each other, and chains % the searching together so that if x is d cm from y and y is d cm from z, % then x, y, and z are in one group, even though dist(x,z) > 5 cm. ARRAY = [zeros(size(ARRAY,1),1) ARRAY]; d = sqrt(3.125*pi) * (5/3); % Pick a fish to start with. #1 is as good as any. f = 1; % Individual number g = 1; % group number % Square the straggler distance, d dsq = d*d; % Make a temporary "active matrix" to hold the array of values in, % so that we aren't editing ARRAY. Make sure the ARRAY is sorted % by individual #, and then delete all the parts of the ARRAY that % are not necessary (assuming it's in RANDFISH format...) MTX = sortrows(ARRAY,2); MTX = ARRAY(:,1:5); group(g).members = []; TRIED_PTS = []; sz = size(MTX,1); % Cycle until no fish remain to be categorized into a group while ( sz > 0 ) % Find the coordinates of the focal fish fx = ARRAY(f,3); fy = ARRAY(f,4); fz = ARRAY(f,5); % Cycle over everyone but fish f, and see who is < d distance % from him for i = 1:sz ix = MTX(i,3); iy = MTX(i,4); iz = MTX(i,5); % Find the squared distance and see if it is less than % the squared 'straggler distance'. dist_fi = (fx - ix)^2 + (fy - iy)^2 + (fz - iz)^2; if ( dist_fi < dsq ) TMP = group(g).members; TMP = [TMP, MTX(i,2)]; group(g).members = TMP; end end % We have now found everyone who is within the d distance of individual f. % We can therefore remove individual f from MTX, since it is no longer needed. % Find the row containing individual f: rownum = find(MTX(:,2) == f); MTX(rownum,:) = []; TRIED_PTS = [TRIED_PTS, f]; GRP = setdiff(group(g).members, TRIED_PTS); for j = GRP % Before we can look to see if anyone else in the group is < 5 BL from one of % these guys, these guys can all be eliminated from the MTX % array. rownum = find(MTX(:,2) == j); MTX(rownum,:) = []; end % Now, if there is anyone else left in the group, we pick the first % fish and try this again, seeing if there is anyone else who is within % d distance of him. if ( size(GRP,2) == 0 ) % Pick a new fish -- just take the next one in line, if % there is one If not, we can ignore it. if ( isempty(MTX) == 0 ) f = find(ARRAY(:,2) == MTX(1,2)); % There's no one left in the group, so we need to pick a new group g = g + 1; group(g).members = []; end else % There's still at least 1 fish in the present group, g, so we can % see if he has any neighbors f = find(ARRAY(:,2) == GRP(1)); end sz = size(MTX,1); end siz = g; str = group;