How can I draw a 2D filled contour onto an arbitrary surface in 3D space?

15 views (last 30 days)
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.

Accepted Answer

Voss
Voss on 11 Feb 2022
Edited: Voss on 11 Feb 2022
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 Comments
Michael
Michael on 11 Feb 2022
Even not adding the additional data to the edge of the panel, the surf rather than a transform on a contourf seemed to make all the difference for being able to actually see it. And by changing the 'o' markers to '.' I can keep the order SortMethod so the box surfaces look right too. I was on the right track but making things harder than they needed to be with the transform stuff. Fantastic solution, many thanks!

Sign in to comment.

More Answers (0)

Products


Release

R2021a

Community Treasure Hunt

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

Start Hunting!