# A 2D circle divided into 10 sectors in the 3D plot.

2 views (last 30 days)

Show older comments

##### 0 Comments

### Accepted Answer

Star Strider
on 15 Feb 2024

I am not exactly certain what you want.

One approach —

r = 7.5;

ac = linspace(0, 2*pi, 500).';

xc = r*cos(ac);

yc = r*sin(ac);

zc = zeros(size(ac));

as = linspace(0, 2*pi, 11).';

xs = r*cos(as);

ys = r*sin(as);

zs = zeros(size(as));

data = rand(50,3).*[2*pi r 150]; % 'Data': [Angle, Radius, Z-Value]

[X,Y,Z] = pol2cart(data(:,1), data(:,2), data(:,3)); % Convert To Cartesian For Plot

figure

plot3(xc, yc, zc, '-k');

hold on

plot3([zs xs].', [zs ys].', [zs zs].', '-k');

scatter3(X, Y, Z, 25, Z, 'filled')

hold off

grid on

colormap(turbo)

daspect([1 1 15]) % Sets Axes Aspect Ratio

figure

plot3(xc, yc, zc, '-k');

hold on

plot3([zs xs].', [zs ys].', [zs zs].', '-k');

plot3(xc, yc, zc+150, '-k');

plot3([zs xs].', [zs ys].', [zs zs].'+150, '-k');

scatter3(X, Y, Z, 25, Z, 'filled')

hold off

grid on

colormap(turbo)

daspect([1 1 15])

To assign them to specific segments in the plot, consider using stem3 as well, with 'Marker','none'. This will connect each data point to the ‘Z’ surface with a line, and can make the plot easier to understand.

.

##### 6 Comments

### More Answers (1)

Adam Danz
on 16 Feb 2024

Edited: Adam Danz
on 16 Feb 2024

Creating a polar heatmap within Cartesian coordinates

The basic idea is to create a polar grid centered under the data, plotted as a surface. The color in the surface is defined by the density of points that fall within each sector of the polar grid. To compute density, the 3D points are convered to 2D polar coordinates, ignoring z-coordinates. Then, each point is assigned to a section of the grid using logical conditions. Then the polar grid is converted back to Cartesian units and centered under the data.

Important caveat: The polar grid cells do not have the same area. This means that larger cells will contain more data points than smaller cells in a uniform distribution. This biases the interpretation of the colored regions. This could be corrected by normalizing the color values to the area of each segment in which case the colors would not indicate number of points but instead, number of points per unit of area.

Please also see a limitation to this visualization at the end of the answer.

Demo

Create data

data is an nx3 matrix of [x,y,z] coordinates.

rng default

data = pearsrnd(0,1,.6,4,500,3); % requires stats toolbox

% data = randn(200,3).*[1.2,1,1]+[2,-1,0]; % Alternative

Convert data to polar coordinates

% Shift data to be centered on (0,0) and convert to polar

center = mean(data(:,1:2)); % (x,y) center of the data

[xTheta, yRad] = cart2pol(data(:,1)-center(1),data(:,2)-center(2));

Create a polar grid

nThetaSectors determines the number of sections around the circle, starting and ending at -pi, pi.

nRadiiSectors determines the number of sections between the center and outer edge of the circle.

% Compute polar grid

nThetaSectors = 10; % parameter

thetaGrid = linspace(-pi,pi,nThetaSectors+1);

nRadiiSectors = 5; % parameter

maxRadius = max(yRad);

radiiGrid = linspace(0,maxRadius,nRadiiSectors+1);

Compute the density of data points within each polar grid cell

% Assign each point to a grid cell

% This only works when there is a border at -pi and pi

[radiusGroup, ~] = find((yRad(:)>radiiGrid(1:nRadiiSectors) & yRad(:)<=radiiGrid(2:end))');

[thetaGroup, ~] = find((xTheta(:)>thetaGrid(1:nThetaSectors) & xTheta(:)<=thetaGrid(2:end))');

% Create density grid

[gcounts,gvecs] = groupcounts([thetaGroup,radiusGroup]);

gidx = sub2ind([nThetaSectors, nRadiiSectors],gvecs{1},gvecs{2});

density = zeros(nThetaSectors, nRadiiSectors);

density(gidx) = gcounts;

Convert the polar grid to Cartesian coordinates

Here, we also shift the polar grid to the center of the data.

The grid is located under the data along the z-axis by finding the minimum z value and shifting downward by 5 % of the range of z-data.

% Create the polar grid in cartesian coordinates

[tg,rg] = ndgrid(thetaGrid,radiiGrid); % meshgrid requires transpose

[px, py] = pol2cart(tg,rg);

px = px + center(1);

py = py + center(2);

[minZ,maxZ] = bounds(data(:,3));

pFloor = minZ*(0.05*(maxZ-minZ));

pz = zeros(size(px)) + pFloor;

Plot the 3D scatter points

scatter3(data(:,1),data(:,2),data(:,3),'ko')

grid on

axis equal

Add the polar density surface

zlim([pFloor,inf])

hold on

h = surf(px,py,pz,density,'FaceAlpha',.5,'EdgeAlpha',.3);

cb = colorbar();

cb.Label.String = 'Density';

axis vis3d

View from the bottom

view(0,-90)

Limitations

Points are assigned to the segments assuming the segments are circular. The segments aren't plotted circularly, they are plotted as trapazoids. This means in some cases a point will appear outside of a segment when it was, in fact, counted as a member of that segment.

This is illustrated in the image below where a yellow segment indicates that it contains 1 data point. The yellow segement on the left counts the point just outside of the segment because it is within the circular zone (dotted line). This could lead to some confusing results.

One way to improve that is to compute density using inpolygon so belongingness is defined by the plotted trapezoidal segments.

Another way to improve this is to plot circular zones instead of trapezoidal zone.

Neither of these improvements would be quick and easy so I'll leave that to the next person.

##### 0 Comments

### See Also

### Categories

### Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!