MATLAB Answers

K E
0

How can I add a patch which lies underneath an existing line?

Asked by K E
on 3 May 2016
Latest activity Edited by K E
on 4 May 2016
If I have a plot containing a line, I would like to add a patch but have it appear under the line so the line remains visible. (Not possible to plot the patch first in my real application). How can I do this using the example below?
figure;
h = plot(rand(1,10), rand(1,10)); % Make a line plot
hold on;
% Get coordinates for a patch in the lower quarter of the figure
xd = get(gca, 'xlim'); xd = [xd(1) xd(2)/2];
yd = get(gca, 'ylim'); yd = [yd(1) yd(2)/2];
x = [xd(1) xd(2) xd(2) xd(1) xd(1)];
y = [yd(1) yd(1) yd(2) yd(2) yd(1)];
% The following patch lies over the line
p = patch(x, y, 'g');

  1 Comment

You can change the coordinates of the patch.

Sign in to comment.

Tags

2 Answers

Answer by Walter Roberson
on 3 May 2016
 Accepted Answer

The method of doing this depends upon which release you are using.
In R2014b and later, provided the new Axes property 'SortOrder' is set to 'childorder', you can re-arrange the order of the children. Robert showed how to do that using the Children property, but the recommended way to do it is with uistack(). I recommend reading http://blogs.mathworks.com/graphics/2014/11/04/sortmethod/
In R2014a or earlier, SortOrder did not exist and the underlying renders had different code. In those versions if you used the painters renderer, the child order would be respected, and it could be manipulated by using uistack(). However if you were using OpenGL renderer (which can get triggered automatically if you have transparency anywhere in the figure), then you were at the mercy of the way OpenGL is defined. In OpenGL, when there is a line and a surface at the same z depth, the line is to be drawn on top of the surface, no matter what the child order. However, it has been common for there to be bugs in OpenGL renderers that get this exactly reversed; if you had such a buggy driver and are using R2014a or earlier, you cannot get the patch under the line without modifying the patch.
In any of the versions, this all is an issue only when the patch and the line are in the same plane. For both of them, a 2D specification will be equivalent to z = 0. You can fix the problem by giving z coordinates for the patch that are "behind" the line relative to the viewing angle. This is not exactly the same as negative coordinates, because the viewing angle might be from negative z: if you rotate the object, do you need the line to stay "in front of" the patch or do you want the line to go "behind" the patch when you look from below? Using R2014b and SortOrder 'childorder' and setting the patch to draw first in the order would keep the line "on top of" the patch, which is not the case if you deal with the issue by giving negative z coordinates for the patch.

  1 Comment

Yes, I had forgotten the z-coordinate trick which I used in the past (example below for those looking to implement it). But I am glad to know about the SortOrder option.
figure;
x = rand(1,10);
y = rand(1,10);
z = ones(size(x))*1e10; % A high value in 3D
h = plot3(rand(1,10), rand(1,10), z); % 3D line plot
hold on;
% Get coordinates for a patch in the lower quarter of the figure
xd = get(gca, 'xlim'); xd = [xd(1) xd(2)/2];
yd = get(gca, 'ylim'); yd = [yd(1) yd(2)/2];
x = [xd(1) xd(2) xd(2) xd(1) xd(1)];
y = [yd(1) yd(1) yd(2) yd(2) yd(1)];
z = ones(size(x))*1e-10; % A low value in 3D
% The following 3D patch lies under the line
p = patch(x,y,z,'g');
view(2); % Force 2D view

Sign in to comment.


Answer by Robert
on 3 May 2016

You can reorder the Children property of the axes on which you have drawn you line and patch. For example, in my application I use a variation on the following:
ax = gca;
set(ax,'Children',circshift(get(ax,'Children'),1))
If you have only the two children, your code would be as effective and more readable if you simply use
set(gca,'Children',[h,p])

  0 Comments

Sign in to comment.