Adjusting the transparency of a contour plot using a gradient of alpha values
51 次查看(过去 30 天)
显示 更早的评论
Hi,
I'm drawing a contourplot .
hLines = 5;
[~,h] = contour(X, Y, Z,hLines,'Fill','on');
For the plot I would like to adjust the alpha values decreasingly. Meaning, the face of the lower Z-Values is almost transparent, whereas the peak should be completely opaque.
If found a possible solution here submitted. And so far it works fine. But here comes the problem. If I run the code, everythings looks fine, but if I adjust the contour plot e.g. by moving it etc. it goes back to it's default alpha values! It seems as if matlab sort of 'overwrites' my changes the second it refreshes the plot.
Does anyone know any way to adjust the alpha values of the faces and make them keep the transparencies?
Here is the entire section that I'm using.
hLines = 5;
[~,h] = contour(X, Y, Z,hLines,'Fill','on');
drawnow;
title('Inverse 2D Laplace Spectrum','FontSize',20,'FontWeight','bold','Interpreter','none');
ylh = ylabel('T1-Values [s]','FontSize',12,'FontWeight','bold');
xlh = xlabel('T2-Values [s]','FontSize',12,'FontWeight','bold');
set(gca,'XScale', 'log');
set(gca,'YScale', 'log');
grid on;
grid minor;
colorbar;
hFills = h.FacePrims;
[hFills.ColorType] = deal('truecoloralpha');
AlphaGradient=exp(linspace(log(10),log(200),hLines)); %The actual values that I want to use for the alpha values
for idx = 1:numel(hFills)
hFills(idx).ColorData(4) = AlphaGradient(idx);
end
So this is how it looks like directely after the adjustments and the way it actually want it to look...
![Transparent plot](https://www.mathworks.com/matlabcentral/answers/uploaded_files/281415/Transparent%20plot.png)
And this is how it looks like if I move it just a little bit...
![](https://www.mathworks.com/matlabcentral/answers/uploaded_files/281416/image.png)
2 个评论
Will Grant
2021-8-18
编辑:Will Grant
2021-8-31
Just wanted to say THANK YOU!! This undocumented solution worked perfectly for me!
回答(2 个)
Will Grant
2021-8-31
编辑:Will Grant
2021-8-31
Here is a simplified version of what works for me in R2020a to keep the transparency you want even after moving / zooming / etc.
% Create the contour object.
ax = uiaxes();
[~, contourObj] = contourf(ax, peaks);
% This is the secret that 'keeps' the transparency.
eventFcn = @(srcObj, e) updateTransparency(srcObj);
addlistener(contourObj, 'MarkedClean', eventFcn);
% Elsewhere in script, a separate file, or another method of your class.
function updateTransparency(contourObj)
contourFillObjs = contourObj.FacePrims;
for i = 1:length(contourFillObjs)
% Have to set this. The default is 'truecolor' which ignores alpha.
contourFillObjs(i).ColorType = 'truecoloralpha';
% The 4th element is the 'alpha' value. First 3 are RGB. Note, the
% values expected are in range 0-255.
contourFillObjs(i).ColorData(4) = 180;
end
end
It appears that matlab always sets the ColorType property of those FacePrims back to truecolor whenever it updates the object. So the trick to keeping the transparency as you want is to put the transparency adjusting code in a function, and set that function as a callback to the MarkedClean event on the contour object.
The beauty of this is that the addlistener() version of creating a listener bundles the function handle and listener object into the contour itself. So you don't need to worry about the lifetime of the listener object (which can be a pain). Whenever you call a cla() or close the axes, the axes, contour, and all children are deleted, including the listener object.
Note that my eventFcn sends in the srcObj to updateTransparency(). Matlab graphics events always pass in the originating object of the event. Since we added the event right to the contour object, the contour is the object the event handler will get. It just ignores the 'event object' property. Event callbacks are required to accept those two parameters, or else you'll get a "not enough input arguments" error.
1 个评论
darova
2020-4-2
Here is my today achievement
clc,clear
opengl software
n = 1000;
[X,Y,Z] = peaks(20);
% surf(X,Y,Z,'facecolor','none')
hold on
for lev = 1:2:7
[~,h] = contourf(X,Y,Z,[1 1]*lev); % create contour at some level
h1 = get(h,'children');
h2 = copyobj(h1,gca); % create copy for white surface
set(h2,'facecolor','w') % copy object - white
set(h1,'facealpha',lev/7) % facealpha
set(h1,'zdata',lev*ones(n,1)) % assign some height for surface
set(h2,'zdata',lev*ones(n,1)-0.5) % bottom white surface
end
hold off
axis vis3d
![](https://www.mathworks.com/matlabcentral/answers/uploaded_files/281482/image.png)
12 个评论
Alan Meier
2020-7-16
I'm using R2018 a and when I run your answer code snippet, I get the same result as TheoBoveri. When I change the code as in the second comment I get the same error as TheoBoveri again.
Using the code from the next comment and the provided .fig file I get the following result because the length(h1) is empty for me as well:
![](https://www.mathworks.com/matlabcentral/answers/uploaded_files/332495/image.jpeg)
f1 =
Figure (1) with properties:
Number: 1
Name: ''
Color: [0.9400 0.9400 0.9400]
Position: [704 518 560 420]
Units: 'pixels'
Show all properties
ans =
'figure'
h0 =
Axes with properties:
XLim: [-3 3]
YLim: [-3 3]
XScale: 'linear'
YScale: 'linear'
GridLineStyle: '-'
Position: [0.1300 0.1100 0.7750 0.8150]
Units: 'normalized'
Show all properties
ans =
'axes'
h0 =
Contour with properties:
LineColor: 'flat'
LineStyle: '-'
LineWidth: 0.5000
Fill: 'off'
LevelList: [-6 -4 -2 0 2 4 6]
XData: [20×20 double]
YData: [20×20 double]
ZData: [20×20 double]
Show all properties
ans =
'contour'
h1 =
0×0 empty GraphicsPlaceholder array.
ans =
[]
DGM
2021-8-18
编辑:DGM
2021-8-19
I'm pretty sure this hasn't worked since R2014b. It works in R2009b and not in R2015b. Contour objects don't have patch children anymore, and consequently, they don't have FaceAlpha.
You could use the x,y data encoded in the 'ContourMatrix' property to build a legacy-style contour using patch objects, but you'll have to bear in mind that 'ContourMatrix' is a sequential description of all the regions in the object. You'd have to loop through the vertex lists in ContourMatrix and create patch objects for each list of vertices.
EDIT:
okay here. This should work for R2014b+ (tested in R2015b and R2019b):
n = 1000;
[X,Y,Z] = peaks(20);
L = 1:2:7;
ct = jet(numel(L));
hold on
for k = 1:numel(L)
[~,h1] = contourf(X,Y,Z,[1 1]*L(k)); % create contour at some level
cm = get(h1,'contourmatrix').';
delete(h1);
while ~isempty(cm)
numvertx = cm(1,2);
vtx = cm(2:numvertx+1,:);
cm = cm((numvertx+2):end,:);
p1 = patch(vtx(:,1),vtx(:,2),ct(k,:),'facealpha',L(k)/7);
p2 = patch(vtx(:,1),vtx(:,2),'w');
set(p1,'zdata',L(k)*ones(n,1)) % assign some height for surface
set(p2,'zdata',L(k)*ones(n,1)-0.5) % bottom white surface
end
end
hold off
view(3)
grid on
axis equal
xlim([-3 3])
ylim([-3 3])
zlim([0 8])
You can of course get a 2D view by doing view(2)
That said, I don't know that this really answers the question. The end result is a gradient, but the white padding means it's not transparent overall. The same result can be had without the white padding, by simply doing a weighted average of each patch color and [1 1 1].
Simply omitting the white padding and stacking the transparent patches doesn't really work, as they occlude each other. The effective color and transparency of each region would be affected by all the patches below it.
It might be possible to do it with polyshape by making holes in the objects, but it might not be fun determining which objects need to be inset into which.
另请参阅
类别
在 Help Center 和 File Exchange 中查找有关 Lighting, Transparency, and Shading 的更多信息
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!