Technique Exchange: Speed up plotting by presetting the axis limits

Many times, plots are generated element by element: a text element here, a line there, a polygon here. If each of them in turn is causing the axes to be grown to accommodate them, then that can be a bottleneck if you have many elements to plot.

A technique is to draw axis limits slightly bigger than you need before you start plotting, and that will prevent axes from being redrawn with every element. This is like a graphic equivalent of matrix preallocation.

Here is some sample code you can try out:

theta = rand(72,1) * 2*pi;
verts = [cos(theta), sin(theta)] * 2/sqrt(3);
offset = [0 0];

tic
figure (1, "Position", [50 50 1800 900])
subplot ("Position", [0.0 0.0 1.0 1.0]);
hold on; axis equal off xy;

pos = 0;
for i = 1:120
  fill(verts(:,1) + offset(1), verts(:,2) + offset(2), "b");
 
  offset(1) += 2.1;
  if (offset(1) >= 40)
    offset(1) = 0;
    offset(2) += 2.5;
  end
end
toc

It gives: Elapsed time is 1.05963 seconds.

You can mouse over the figure to get the axis limits (or use the command foo = axis). In this case, the axis limits are: [-1.1536 41.0546 -4.3032 16.8009] in xmin xmax ymin ymax order.

Add the line axis ([-1.5 41.5 -4.5 17.0]); to the figure setup code, before the main plotting begins. The new code reads:

theta = rand(72,1) * 2*pi;
verts = [cos(theta), sin(theta)] * 2/sqrt(3);
offset = [0 0];

tic
figure (1, "Position", [50 50 1800 900])
subplot ("Position", [0.0 0.0 1.0 1.0]);
hold on; axis equal off xy;

axis ([-1.5 41.5 -4.5 17.0]);  ## <<<=== This is the only new line.

pos = 0;
for i = 1:120
  fill(verts(:,1) + offset(1), verts(:,2) + offset(2), "b");
 
  offset(1) += 2.1;
  if (offset(1) >= 40)
    offset(1) = 0;
    offset(2) += 2.5;
  end
end
toc

The time now reads: Elapsed time is 0.496915 seconds.

Reducing it from ~1.06 seconds to 0.497 seconds = roughly twice as fast. Use this technique if plotting is your bottleneck.

1 Like