# Why do my 3D plot axis tick marks keep repeating?

11 views (last 30 days)
Jeeven Hugh on 17 Nov 2020
Commented: Jeeven Hugh on 18 Nov 2020
I am trying to create a 3D plot video, but my X axis tick marks keep repeating. The X axis tick marks should be increasing linearly. How can I fix this?
IMAGE OF PROBLEM (SEE X AXIS HAS REPEATING VALUES): MATLAB CODE:
%% INIT WORKSPACE
clear
clc
close all
%% TEST INPUTS
x = 1:50:10^5;
y = zeros(1,length(x));
z = y;
%% INIT VIDEO
myVideo = VideoWriter('test.avi');
open(myVideo);
myFigure = figure(111);
set(myFigure, 'Position', [50 50 1000 500]);
axis 'equal'
set(gca,'ZDir','reverse')
hold on
%% ANIMATE
F = {};
for j = 1:length(x)
% Initialize Axes
cla
view(0,90); % Top (XY) View
xlim([x(1,j)-2000 x(1,j)+2000]); ylim([-100 100]); zlim([-100 100]);
xticks(0:1000:10^6); ax = gca; ax.XRuler.Exponent = 0;
grid on;
xlabel('X (ft)', 'fontweight', 'bold', 'fontsize', 13); ylabel('Y (ft)', 'fontweight', 'bold', 'fontsize', 13); zlabel('Z (ft)', 'fontweight', 'bold', 'fontsize', 13);
set(gca, 'XTickLabel',get(gca,'XTickLabel'), 'fontsize',13);
% Plot
plot3(x(1,j),y(1,j),z(1,j), 'x');
% Save Video
F{end+1} = getframe(gcf);
writeVideo(myVideo, getframe(gcf));
end
close(myVideo); % Close Video

xticklabels(0:1000:10^6);
right after xticks(0:1000:10^6);
Cris LaPierre on 17 Nov 2020
Agreed. Also, move all the settings that only need to be set once outside your for loop.
%% TEST INPUTS
x = 1:50:10^5;
y = zeros(1,length(x));
z = y;
%% INIT VIDEO
myVideo = VideoWriter('test.avi');
open(myVideo);
myFigure = figure(111);
set(myFigure, 'Position', [50 50 1000 500]);
ax = gca;
axis(gca,'equal')
set(ax,'ZDir','reverse')
view(ax,0,90)
grid on;
ax.XTick=0:1000:10^6;
ax.XRuler.Exponent = 0;
xlim(ax,[x(1)-2000 x(1)+2000]);
ylim(ax,[-100 100]);
zlim(ax,[-100 100]);
xlabel(ax,'X (ft)', 'fontweight', 'bold', 'fontsize', 13);
ylabel(ax,'Y (ft)', 'fontweight', 'bold', 'fontsize', 13);
zlabel(ax,'Z (ft)', 'fontweight', 'bold', 'fontsize', 13);
set(ax, 'XTickLabel',0:1000:10^6, 'fontsize',13);
hold on
%% ANIMATE
F = {};
for j = 1:100%length(x)
% Initialize Axes
cla
xlim(ax,[x(1,j)-2000 x(1,j)+2000]);
% Plot
plot3(ax,x(1,j),y(1,j),z(1,j), 'x');
% Save Video
F{end+1} = getframe(gcf);
writeVideo(myVideo, getframe(gcf));
end
close(myVideo); % Close Video

Benjamin Kraus on 17 Nov 2020
What you are running into are two quirks of how axes behaves.
First, when applying the tick labels, MATLAB starts at the first tick and uses the first label, at the second tick it uses the second label, etc. If it runs out of tick labels but has more ticks that need labels, it starts back at the first label. For example, if you have 5 ticks and 3 tick labels, the first and second tick label will be reused for the 4th and 5th ticks.
In this case, you are using the following code to set the x-ticks:
xticks(0:1000:10^6);
This is setting 1001 ticks on the axes, and by setting the ticks manually, you are preventing an automatic calculation which may move the ticks to a new location (or change the number of ticks).
The second quirk you are encountering is that when the tick labels are being automatically generated, MATLAB only generates labels for ticks that are on the screen. The code you are using to set the tick labels is:
set(gca, 'XTickLabel',get(gca,'XTickLabel'))
The first time that command is called, there are only three ticks within the x-limits, so the value of XTickLabel has only three elements. Then you are setting the XTickLabel property, effectivelty locking-in the three tick labels and disabling automatic label calculation for all subsequent loops.
At this point, you have 1001 ticks and three labels, so MATLAB assigns the first label to the first tick, the second label to the second tick, the third label to the third tick, the first label to the fourth tick, the second label to the fifth tick, etc. Hence the repeating labels.
One more thing to note is that calling cla does not reset the tick values or labels, so the settings from the previous loop are being reused for the second and subsequent loops.
There are a couple solutions to this:
1. One option is to make sure to specifically set one label per tick. You can do this either by setting the XTickLabel property with the labels you want explicitly (you can use numeric values, which will be converted to strings). Better yet, as Aaron suggested, is to use the xticklabels command (instead of setting the XTickLabels property). The command will check if there are more ticks than tick labels, and will pad the labels with empty labels if needed, to avoid the problem of repeating tick labels.
2. It is not clear why you are setting the XTickLabel property to be equal to itself, so you could remove that line entirely. This will maintain automatic tick labeling, and will also resolve this issue.
3. Set XTickLabelMode back to 'auto' at the beginning of your loop (you can also call xticklabel('auto')). This will reset the automatically calculated tick labels based on the new axes limits.
4. If your goal is to change the formatting used for the tick labels, you may consider setting the XAxis.TickLabelFormat property to control the formatting of the tick labels, rather than hard-coding the labels themselves. You can also use the shortcut xtickformat command.
Jeeven Hugh on 18 Nov 2020
Thank you.