Find closest sphere in a cluster with random spheres having different diameters-2
Afficher commentaires plus anciens
Hi,
I posted this question before and i got good help in how to find closest sphere in a cluster with random spheres having different diameters. I am making clusters of spheres using random number generator. Some of the spheres are connected and some of them are not connected. I want to exclude the not connected ones, so I only get the clusters/connected spheres .I have random spheres having random diameters between 0.1 and 0.5.
here is my code till now:
%% Data for Agglomerates
N = 15; % number of spheres
a = 0.1 ; % lowest diameter of sphere
b = 0.5 ; % highest diameter of sphere
Diam = a + (b-a).*rand(N,1);
aaa= 0; % minimum center x and y coordinate limit for spheres
bbb= 1.5 ; % maximum center x and y coordinat limit for sphere
M=3 ;
Axes= zeros(N,M);
Axes(:,1)=aaa+(bbb-aaa)*rand(N,1);
for k=2:M
aaa=randperm(N);
Axes(:,k)=Axes(aaa,1);
end
Axes_Label ={'X axis','Y axis','Z axis'};
Data_agglo = [Diam Axes];
Data_Label ={'Diameter','X axis','Y axis','Z axis'};
R = Diam ./2;
%% Algorithm to find connected spheres and eliminate outliers
distances = zeros(size(Data_agglo,1));
active_spheres = zeros(size(Data_agglo,1));
delta = 1e-4;
for p =1:1:size(Data_agglo,1)
for q = 1:1:size(Data_agglo,1)
if size(Data_agglo,1)==1
distances(p,q) = sqrt((Data_agglo(q,2)-Data_agglo(p,2)).^2 + (Data_agglo(q,3)-Data_agglo(p,3)).^2 + (Data_agglo(q,4)-Data_agglo(p,4)).^2);
active_spheres(p,q) = (distances(p,q) <= (Data_agglo(p,1)/2)+(Data_agglo(q,1)/2) - delta );
else
if p ~= q
distances(p,q) = sqrt((Data_agglo(q,2)-Data_agglo(p,2)).^2 + (Data_agglo(q,3)-Data_agglo(p,3)).^2 + (Data_agglo(q,4)-Data_agglo(p,4)).^2);
active_spheres(p,q) = (distances(p,q) <= (Data_agglo(p,1)/2)+(Data_agglo(q,1)/2) - delta );
end
end
end
end
rem_particle = sum(active_spheres);
rem_particle = find(rem_particle == 0);
Data_agglo2 = Data_agglo;
Data_agglo(rem_particle,:) = [];
R(rem_particle) = [];
if isempty(R)
error('No spheres are connected!\n');
end
%% generate mesh
dipS = 0.01;
xmin = min(Data_agglo(:,2)-R);
xmax = max(Data_agglo(:,2)+R);
ymin = min(Data_agglo(:,3)-R);
ymax = max(Data_agglo(:,3)+R);
zmin = min(Data_agglo(:,4)-R);
zmax = max(Data_agglo(:,4)+R);
[Xgrid,Ygrid,Zgrid]= ndgrid((xmin:dipS:xmax)-(xmin+xmax)/2,(ymin:dipS:ymax)-(ymin+ymax)/2,(zmin:dipS:zmax)-(zmin+zmax)/2);
Data_agglo(:,2:4) = Data_agglo(:,2:4) - [(xmin+xmax)/2,(ymin+ymax)/2,(zmin+zmax)/2];
% plot3(Xgrid(:),Ygrid(:), Zgrid(:),'.','MarkerFaceColor','blue');
% hold all
%% get active dipoles
tic
active = false(size(Xgrid));
for i =1:1:size(Data_agglo,1)
active = active | (((Xgrid - Data_agglo(i,2)).^2 + (Ygrid - Data_agglo(i,3)).^2 + (Zgrid - Data_agglo(i,4)).^2) <= R(i).^2);
end
plot3(Xgrid(active),Ygrid(active),Zgrid(active),'o','MarkerFaceColor','red');
axis equal
grid on
toc
The problem I am getting is :

I eliminate the spheres, but I am left with two sets of connected spheres. I want to choose one of them and delete the other one. there is no pirority which one to use.
I am attaching the figure file as well. Other problem I get is that when i give the number of spheres =1, my program doesnt work. Also if it is possible to find the largest set of connected spheres as shown in the picture and keep them?
Does anyone knows how it can be done?
4 commentaires
Walter Roberson
le 3 Mai 2022
Modifié(e) : Walter Roberson
le 4 Mai 2022
https://en.m.wikipedia.org/wiki/Equivalence_class build Equivalence_class relationships between the spheres according to whether they intersect. Afterwards, look for the largest equivalence class.
Chris Dan
le 4 Mai 2022
Walter Roberson
le 4 Mai 2022
Untested.
equivalence_class_numbers = (1:number_of_spheres).';
equivalence_class_members = num2cell(equilvance_class_numbers);
for idx = 2 : number_of_spheres
sp = Index_of_conflicting_spheres(idx, sphere_coordinates, sphere_radii);
if isempty(sp); continue; end
sp = [sp; idx];
new_class = min(sp);
new_members = unique(cell2mat(equivalence_class_members(sp)));
equivalance_class_members(new_class) = new_members;
equivalance_class_numbers(sp) = new_class;
equivalance_class_members(setdiff(sp, new_class)) = {};
end
At the end of this, equivalance_class_numbers will be a vector of length number_of_spheres that gives the cluster number each sphere belongs to. The numbers will likely have gaps -- for example if sphere #3 is connected to sphere #1 then the class number (1) and at (3) would both be 1, and 3 would not appear in any class number. For some purposes you would want to renumber without gaps (findgroups() would help for that), but for the purpose of your particular need, you do not care about the cluster number in absolute terms, you just want to know what is joined to what.
At the end of the code, equivalance_class_members is a cell, and for any cluster number that does not exist (like the 3 in the above example, because sphere 3 is part of cluster 1), the entry in equivalance_class_members will be empty. For each cluster number that is populated, equivalance_class_members will be a list of all the sphere numbers that belong to the same cluster.
If you see a equivalance_class_members entry that is a scalar (but not empty), that means that the sphere is isolated, and in such a case equivalance_class_numbers(K) == K .
You can cellfun(@length, equivalance_class_members) and use max() to find the largest cluster (at least in terms of numbers of members -- not in terms of volume !)
Chris Dan
le 5 Mai 2022
Réponse acceptée
Plus de réponses (0)
Catégories
En savoir plus sur Surface and Mesh Plots dans Centre d'aide et File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!
