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

조회 수: 2 (최근 30일)
Dmitriy
Dmitriy 2024년 2월 15일
댓글: Star Strider 2024년 2월 28일
Hello, for the visualization of my research results, I would like to create a 3D chart with a circle split in sectors, similar to the one attached. But I need a circle divided into 10 sectors, and I would like to assign concentrations for each sector, for example like in the chart where circle is separated in squares. How can I do it?

채택된 답변

Star Strider
Star Strider 2024년 2월 15일
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
Dmitriy
Dmitriy 2024년 2월 28일
I got it! Now I understand, have succesfully made charts for my work, thank You very much for your help!
Star Strider
Star Strider 2024년 2월 28일
As always, my pleasure!

댓글을 달려면 로그인하십시오.

추가 답변 (1개)

Adam Danz
Adam Danz 2024년 2월 16일
편집: Adam Danz 2024년 2월 16일
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.

카테고리

Help CenterFile Exchange에서 Line Plots에 대해 자세히 알아보기

태그

Community Treasure Hunt

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

Start Hunting!

Translated by