How can I draw a 2D filled contour onto an arbitrary surface in 3D space?
11 次查看(过去 30 天)
显示 更早的评论
I am drawing a 3D box and would like to have one of the surfaces of the box be a filled contour plot. I can draw the box like this:
figure;hold all;
vertices = [-2.5 0 0;2.5 0 0;2.5 13 0;-2.5 13 0;-2.5 0 2;2.5 0 2;2.5 13 2;-2.5 13 2];
faces = [1 2 6 5;2 3 7 6;3 4 8 7;4 1 5 8;1 2 3 4;5 6 7 8]; % draw all faces
% faces = [2 3 7 6;3 4 8 7;4 1 5 8;1 2 3 4;5 6 7 8]; % don't draw the front face
patch('Vertices',vertices,'Faces',faces,'FaceVertexCData',hsv(size(faces,1)),'FaceColor','flat');
axis equal; xlim([-6 6]); ylim([-2 14]); zlim([0 6]); view(37.5,30);
That will produce the box I want:
I can create the filled contour plot I want like this:
acrossPorts = -2:0.5:2;
verticalPorts = 0.25:0.5:1.75;
[AP,VP] = meshgrid(acrossPorts,verticalPorts);
portPressures = [
1 2 3 4 5 4 3 2 1
11 22 33 44 55 44 33 22 11
10 20 30 40 50 60 70 30 10
1 2 3 4 5 8 6 4 1];
figure;hold all;
contourf(AP,VP,portPressures,100,'linestyle','none');
plot(AP,VP,'ok');
axis equal; xlim([-2.5 2.5]); ylim([0 2]);
What I want to do is essentially replace the solid red surface on the first figure with the contour of the second figure. I'd like to have the circles, but if I lose those it's not a big problem. I'd also like to extrapolate the contour to the boundary of my 5x2 box for visual purposes, but again, if I have to sacrifice that it's OK.
I have not been able to find a function that lets me do what I want directly, so what I tried was to transform the contour after drawing it. I did this by drawing the box with the "don't draw the front face" line instead and then did this for the contour:
ax=gca; HG=hgtransform(ax);
contourf(AP,VP,portPressures,100,'linestyle','none','parent',HG);
HG.Matrix = makehgtform('xrotate',pi/2);
This stuck the contour in the right place, but it isn't being drawn correcly or something:
I can change the view using view(10,7); and it looks like this:
So the whole contour really is there and in the correct spot, but I can't get it to reliably be visible at arbitrary orientations. And I suspect that if I try to draw other surfaces like this with more complicated transformations, they certainly aren't going to work any better.
If someone can offer a better/more reliable way to draw the filled contour where I want it to be, I'd greatly appreciate it.
0 个评论
采纳的回答
Voss
2022-2-11
编辑:Voss
2022-2-11
Since the contour has LineStyle 'none' you can use a surface object and specify the XData, YData, ZData directly (no need for a transform). But the reason the patches underneath show up is just because the contour/surface doesn't span the entire region that the front patch face does in the X and Z dimensions. I added some values all around to fix that (equal to the minimum value of portPressures).
Removing that front patch face changes the colors of some of the other faces, so you may want to deal with that differently, e.g., I've set the first patch face to be colored with NaN's so the other faces' colors don't change.
You can also set the axes 'SortMethod' to 'ChildOrder' to get the line with marker 'o' to show up on top of the surface/contour without the markers being partially obscured, but then that reorders how the patch faces are drawn, so you probably want to adjust the patch accordingly. I don't know if there's going to be a way to do it so that everything looks good from any angle.
figure;hold all;
vertices = [-2.5 0 0;2.5 0 0;2.5 13 0;-2.5 13 0;-2.5 0 2;2.5 0 2;2.5 13 2;-2.5 13 2];
faces = [1 2 6 5;2 3 7 6;3 4 8 7;4 1 5 8;1 2 3 4;5 6 7 8]; % draw all faces
% faces = [2 3 7 6;3 4 8 7;4 1 5 8;1 2 3 4;5 6 7 8]; % don't draw the front face
colors = hsv(size(faces,1));
colors(1,:) = NaN; % don't draw the front face
p = patch('Vertices',vertices,'Faces',faces,'FaceVertexCData',colors,'FaceColor','flat');
axis equal; xlim([-6 6]); ylim([-2 14]); zlim([0 6]); view(37.5,30);
acrossPorts = -2:0.5:2;
verticalPorts = 0.25:0.5:1.75;
portPressures = [
1 2 3 4 5 4 3 2 1
11 22 33 44 55 44 33 22 11
10 20 30 40 50 60 70 30 10
1 2 3 4 5 8 6 4 1];
[AP,VP] = meshgrid([-2.5 acrossPorts 2.5],[0 verticalPorts 2]);
PP_plot = min(portPressures(:))*ones(size(AP));
PP_plot(2:end-1,2:end-1) = portPressures;
surf(AP,zeros(size(AP)),VP,PP_plot,'FaceColor','interp','linestyle','none');
line(AP(2:end-1,2:end-1),zeros(size(AP)-2),VP(2:end-1,2:end-1),'Color','k','Marker','o','LineStyle','none');
axis equal; xlim([-2.5 2.5]); ylim([0 2]);
Same thing but with the axes 'SortMethod' set to 'ChildOrder':
figure;hold all;
vertices = [-2.5 0 0;2.5 0 0;2.5 13 0;-2.5 13 0;-2.5 0 2;2.5 0 2;2.5 13 2;-2.5 13 2];
faces = [1 2 6 5;2 3 7 6;3 4 8 7;4 1 5 8;1 2 3 4;5 6 7 8]; % draw all faces
% faces = [2 3 7 6;3 4 8 7;4 1 5 8;1 2 3 4;5 6 7 8]; % don't draw the front face
colors = hsv(size(faces,1));
colors(1,:) = NaN; % don't draw the front face
p = patch('Vertices',vertices,'Faces',faces,'FaceVertexCData',colors,'FaceColor','flat');
axis equal; xlim([-6 6]); ylim([-2 14]); zlim([0 6]); view(37.5,30);
acrossPorts = -2:0.5:2;
verticalPorts = 0.25:0.5:1.75;
portPressures = [
1 2 3 4 5 4 3 2 1
11 22 33 44 55 44 33 22 11
10 20 30 40 50 60 70 30 10
1 2 3 4 5 8 6 4 1];
[AP,VP] = meshgrid([-2.5 acrossPorts 2.5],[0 verticalPorts 2]);
PP_plot = min(portPressures(:))*ones(size(AP));
PP_plot(2:end-1,2:end-1) = portPressures;
surf(AP,zeros(size(AP)),VP,PP_plot,'FaceColor','interp','linestyle','none');
line(AP(2:end-1,2:end-1),zeros(size(AP)-2),VP(2:end-1,2:end-1),'Color','k','Marker','o','LineStyle','none');
axis equal; xlim([-2.5 2.5]); ylim([0 2]);
set(gca(),'SortMethod','ChildOrder')
2 个评论
更多回答(0 个)
另请参阅
类别
在 Help Center 和 File Exchange 中查找有关 Surface and Mesh Plots 的更多信息
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!