How to check if a figure has z-axis data?

How can I check the number of dimensions of a figure? I want to be able to set custom limits of each axis, supporting both 2D and 3D plots. Of course if I attempt to set zlim for a 2D plot, I get an error.
I thought about counting the number of axis, but I don't think this will work, since other things, such as colorbars, are also condidered axes.

5 Comments

which release are you using? colorbar andllegend used to create axes but if I recall correctly do not anymore.
My tests show that all axes of type numeric and datetime have ZLim that can be queried, so the presense of ZLim cannot be used to distinguish 2D from 3D. The only way I could think of to reliably distinguish a 2D axes from a 3D axes was to look for 3D objects inside the axes.
Polar axes and geoaxes do not have a ZLim, so I deem them to be 2D.
One thing I did not do is look for hgtransform groups: a purely 2D object such as an image can be rotated or translated into Z without there being any object that has explicit Z coordinates. One could potentially examine the Matrix property of an hgtransform object to determine whether it could move anything into 3D.
Note here that the ability to (generally) set ZLim does not mean that you can set it to any particular datatype without checking: you cannot set a Datetime Z Ruler to numeric zlim for example.
fig = gcf;
all_zobj = findobj(fig, '-property','ZData');
all_ax = findobj(fig, 'type', 'axes');
all_other_ax = findobj(fig, 'type', 'polaraxes', '-or', 'type', 'geoaxes');
all_zd = get(all_zobj, 'ZData');
if ~iscell(all_zd); all_zd = {all_zd}; end %no objects or 1 object case.
no_z = cellfun(@isempty, all_zd);
obj_3d = all_zobj(~no_z);
ax_3d = ancestor(obj_3d, 'axes');
if ~iscell(ax_3d); ax_3d = {ax_3d}; end
all_unique_ax3d = unique( [ax_3d{:}] );
all_unique_ax2d = setdiff( [all_ax, all_other_ax], all_unique_ax3d );
Thanks for your thorough response. I think the property 'ZData' ended up being all that I was looking for. I ended up just checking
if ~isempty(findobj(gca,'-property','ZData'))
which seems to work fine.
But that can only tell you whether there are any objects capable of Z, not whether the axes has 3D data inside it.
Also, an empty axes would be the same as an axes incapable of Z for that test.
If you just want to know whether an axes is capable of Z, test whether it is type Axes; as compared to polaraxes or geoaxes. All Axes are capable of Z, but polaraxes and geoaxes are not.

Sign in to comment.

 Accepted Answer

My tests show that all axes of type numeric and datetime have ZLim that can be queried, so the presense of ZLim cannot be used to distinguish 2D from 3D. The only way I could think of to reliably distinguish a 2D axes from a 3D axes was to look for 3D objects inside the axes.
Polar axes and geoaxes do not have a ZLim, so I deem them to be 2D.
One thing I did not do is look for hgtransform groups: a purely 2D object such as an image can be rotated or translated into Z without there being any object that has explicit Z coordinates. One could potentially examine the Matrix property of an hgtransform object to determine whether it could move anything into 3D.
Note here that the ability to (generally) set ZLim does not mean that you can set it to any particular datatype without checking: you cannot set a Datetime Z Ruler to numeric zlim for example.
fig = gcf;
all_zobj = findobj(fig, '-property','ZData');
all_ax = findobj(fig, 'type', 'axes');
all_other_ax = findobj(fig, 'type', 'polaraxes', '-or', 'type', 'geoaxes');
all_zd = get(all_zobj, 'ZData');
if ~iscell(all_zd); all_zd = {all_zd}; end %no objects or 1 object case.
no_z = cellfun(@isempty, all_zd);
obj_3d = all_zobj(~no_z);
ax_3d = ancestor(obj_3d, 'axes');
if ~iscell(ax_3d); ax_3d = {ax_3d}; end
all_unique_ax3d = unique( [ax_3d{:}] );
all_unique_ax2d = setdiff( [all_ax, all_other_ax], all_unique_ax3d );

1 Comment

This has not been thoroughly tested but you can get the axis limits using lim = axis. 2D axes will result in a 1x4 vector. 3D axes will result in a 1x6 vector. So divide by 2 to get the number of axes.
figure()
ax(1) = subplot(1,2,1);
plot(ax(1), rand(1,4),rand(1,4))
grid(ax(1),'on'); title('axis 1')
ax(2) = subplot(1,2,2);
plot3(ax(2),rand(1,4),rand(1,4),rand(1,4))
grid(ax(2),'on'); title('axis 2')
nAxes1 = numel(axis(ax(1)))/2
nAxes1 = 2
nAxes2 = numel(axis(ax(2)))/2
nAxes2 = 3

Sign in to comment.

More Answers (0)

Categories

Find more on Graphics Object Properties in Help Center and File Exchange

Asked:

on 21 May 2020

Commented:

on 30 Mar 2021

Community Treasure Hunt

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

Start Hunting!