The fourth argument to scatter3
defines the marker area in units of square points (1 point = 1/72 inch), which is relative to the figure/screen size and therefore not related to the axes data units. If you want to define the radius of your particles relative to the positional data (such that a particle with radius 1 at the origin will span [-1 1]
in the x, y, and z directions) then scatter3
isn't going to work.
One option is to plot each particle as a sphere using surf
, as illustrated here. Here's how you can do this, using your sample data:
% Data and unit sphere surface coordinates:
x = [0 1 1 0 0 1 1 0].';
y = [0 0 1 1 0 0 1 1].';
z = [0 0 0 0 1 1 1 1].';
radius = [0.1 0.5 0.1 1 1 0.4 0.6 0.2].';
[xS, yS, zS] = sphere;
% Plot spheres:
for pt = 1:numel(x)
surf(x(pt)+xS.*radius(pt), ... % Shift and scale x data
y(pt)+yS.*radius(pt), ... % Shift and scale y data
z(pt)+zS.*radius(pt), ... % Shift and scale z data
'EdgeColor', 'none');
hold on;
end
% Modify figure and axes:
axis equal
set(gcf, 'Color', 'k');
set(gca, 'Color', 'k', 'Box', 'on', 'BoxStyle', 'full', ...
'XColor', 'w', 'YColor', 'w', 'ZColor', 'w', 'GridColor', 'none');
And here's the plot this produces:

Notice that the surfaces are colored by default based on height. If you want to color them differently, you can modify the CData
and FaceColor
properties of the surfaces. For example, you can give each surface a flat color based on its radius value (which will be mapped to the current colormap) by modifying the surf
call above to this:
surf(x(pt)+xS.*radius(pt), ...
y(pt)+yS.*radius(pt), ...
z(pt)+zS.*radius(pt), ...
radius(pt).*ones(size(xS)), ...
'FaceColor', 'flat', 'EdgeColor', 'none');