find radius of xyz data
5 views (last 30 days)
Show older comments
@Image Analyst
I have a 3d point cloud that contains xyz data that I would like to find the radius of. I would like to use inclircle function to find the diameter that contains all points but it is not giving me my desired output. I dont know if it has to do with the fact that my point cloud is tilted.
Alternatively, I was thinking to find a way to find the length of the axis that would give me the diameter in this example. Thank you
I included zip containing my data
Code:
% Read data.
cloud = pcread('data.ply');
xyz = double(cloud.Location);
xyz(:,3) = [];
%k = convhull(xyz);
x = xyz(:,1);
y = xyz(:,2);
[center,radius] = minboundcircle(x,y)
theta = linspace(0,2*pi,100);
xc = center(1) + radius*cos(theta);
yc = center(2) + radius*sin(theta);
% Sometimes the minimal radius circle may pass
% through only two points.
plot(x,y,'ro',xc,yc,'b-')
set(gcf,'color','white')
% Create ylabel
ylabel({'Y'});
% Create xlabel
xlabel({'X'});
% Create title
title({'Minimum radius enclosing circle'},'Editing','on');
figure
pcshow(cloud);
Answers (3)
Image Analyst
on 28 Mar 2022
Try this:
% Create a set of points in 3-D
xyz = rand(9, 3);
% Find distances between all of them with pdist2() in the stats toolbox.
distances = pdist2(xyz, xyz)
maxDistance = max(distances(:))
[index1, index2] = find(distances == maxDistance)
% Just take one singe they're symmetric.
index1 = index1(1);
index2 = index2(1);
fprintf('Furthest apart points:\n');
fprintf('(x1,y1,z1) = (%f, %f, %f)\n', xyz(index1, 1), xyz(index1, 2), xyz(index1, 3))
fprintf('(x2,y2,z2) = (%f, %f, %f)\n', xyz(index2, 1), xyz(index2, 2), xyz(index2, 3))
% Plot all of them.
plot3(xyz(:, 1), xyz(:, 2), xyz(:, 3), 'b.', 'MarkerSize', 20);
grid on;
xlabel('x');
ylabel('y');
zlabel('z');
% Plot the two that are farthest away and define the diameter.
hold on;
plot3([xyz(index1, 1), xyz(index2, 1)],...
[xyz(index1, 2), xyz(index2, 2)],...
[xyz(index1, 3), xyz(index2, 3)],...
'r-', 'LineWidth', 3);

1 Comment
Image Analyst
on 28 Mar 2022
Edited: Image Analyst
on 28 Mar 2022
On second thought, the two farthest away points in 3-D won't necessarily give you the diameter - imagine 3 equidistant points every 60 degrees along the perimeter.
I suppose if there are not too many points, you cold always brute force it with a triple for loop. John D'Errico (pronounced DEER - ih - coe I think, or maybe der-REE-coe) may know of a better way.
Torsten
on 28 Mar 2022
Edited: Torsten
on 29 Mar 2022
It's an optimization problem:
min: r^2
s.c.
(x_i-x_s)^2 + (y_i-y_s)^2 + (z_i-z_s)^2 <= r^2 (i=1,...,number of points in 3d cloud)
where the unknowns are x_s, y_s, z_s and r and the triples (x_i,y_i,z_i) are your point cloud data.
You can try "fmincon" to solve.
Here is a test case:
xyz = randn(100,3);
X = xyz(:,1);
Y = xyz(:,2);
Z = xyz(:,3);
xyz0(1) = sum(X)/numel(X);
xyz0(2) = sum(Y)/numel(Y);
xyz0(3) = sum(Z)/numel(Z);
xyz0(4) = max(sqrt(((X-xyz(1)).^2+(Y-xyz(2)).^2+(Z-xyz(3)).^2)));
xyz0
%xyz0 = [1 1 1 100];
sol = fmincon(@fun,xyz0,[],[],[],[],[],[],@(p)nonlcon(p,X,Y,Z))
end
function obj = fun(p)
obj = p(4).^2
end
function [c,ceq] = nonlcon(p,X,Y,Z)
ceq = [];
c = (X-p(1)).^2 + (Y-p(2)).^2 + (Z-p(3)).^2 - p(4)^2;
end
Maybe the center of gravity x_s = 1/n *sum_x_i, y_s = 1/n *sum_y_i , z_s = 1/n * sum_z_i is the solution.
I'm not sure.
After the test runs I can say: it's not the center of gravity.
3 Comments
Torsten
on 28 Mar 2022
Edited: Torsten
on 29 Mar 2022
That would be trivial to solve. It's just,
max_{i,j} ( norm([xi,yi,zi]-[xj,yj,zj]))
Maybe you mean max_{i,j} ( norm([xi,yi,zi]-[xj,yj,zj]))/2, but it's not correct.
Consider an equal-sided triangle in 2d with sidelength 1.
The radius of the circumcircle is 1/sqrt(3) > 1/2.
The radius that is really being sought is that of the tightest cylinder that will fit around the data, or in other words the tightest circle radius after projecting the (x,y,z) data onto a 2D plane.
Is it so ? If this is the usual definition of the radius of a point cloud, I didn't know.
Matt J
on 29 Mar 2022
Edited: Matt J
on 29 Mar 2022
I would like to use inclircle [sic.] function to find the diameter
Are you trying to enclose the points in a sphere or a cylinder? If a sphere, how would a function having to do with circles be applicable to you?
And where did you get the 3rd party code routine "incircle"? If you got it here, note that the package also contains a routine called minboundsphere() which might be more applicable.
3 Comments
Torsten
on 29 Mar 2022
But the formulae for all the parameters in the plot command are given in the code - you just have to copy the lines.
See Also
Categories
Find more on Point Cloud Processing in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!