Create the 3 shapes at first:
warning('off', 'MATLAB:alphaShape:DupPointsBasicWarnId');
Shape = cell(1, 3);
[x, y, z] = sphere;
Alpha = 2;
Shape{1} = alphaShape(x(:), y(:), z(:) + 9, Alpha);
r = 1.0;
h = 9.0;
m = h/r;
[R,A] = meshgrid(linspace(0,r,11), linspace(0,2*pi,41));
X2 = R .* cos(A);
Y2 = R .* sin(A);
Z2 = m * R;
Shape{2} = alphaShape(X2(:), Y2(:), Z2(:), Alpha);
Shape{3} = alphaShape(x(:) * 0.6, y(:) * 0.6, z(:) * 0.6, Alpha);
warning('on', 'MATLAB:alphaShape:DupPointsBasicWarnId');
coorMin = [-1, -1, -0.6];
coorRange = [2, 2, 10.4];
Now choose random points inside the surrounding cuboid and collect the points, which are in any of the shapes:
maxIter = 1e6;
iter = 0;
n = 100;
P = zeros(n, 3);
iP = 0;
while iP < n && iter <= maxIter
Q = rand(1, 3) .* coorRange + coorMin;
if inShape(Shape{1}, Q) || inShape(Shape{2}, Q) || inShape(Shape{3}, Q)
iP = iP + 1;
P(iP, :) = Q;
end
iter = iter + 1;
end
if iter == maxIter
error('Cannot find enough points.');
end
This approach is simpler than creating one shape only, because you do not have to consider the overlap or know anything about the geometry or relative position of the objects. Even the sharp kink between the lower sphere and the cone is not problem here.
The smaller the volume of the shape containing the accepted points compared to the surrounding cuboid, the higher is the number of rejected points. Set maxIter accordingly.
Display the shape and the points:
figure;
subplot(1,2,1, 'NextPlot', 'add');
for k = 1:3
plot(Shape{k});
end
axis([-1,1, -1,1, -1,10], 'equal')
view(3)
subplot(1,2,2, 'NextPlot', 'add', 'XLim', [-1,1], 'YLim', [-1,1]);
plot3(P(:,1), P(:,2), P(:,3), '.');
axis([-1,1, -1,1, -1,10], 'equal')
view(3)
Here with n=1000 points:
Best Answer