Mike on MATLAB Graphics

Graphics & Data Visualization

Note

Mike on MATLAB Graphics has been archived and will not be updated.

SortMethod

SortMethod

Today we're going to talk about the SortMethod property which was added to the Axes object in R2014b. It's actually been around for a long time, but it wasn't supported by all renderers, and it had the confusing name 'DrawMode'. We renamed it because it's a very important property and we want to make sure that everyone understands what it is for.

First we'll create a very simple scene. This is just 3 patch objects. I've set they're DisplayName properties so that we'll recognize them when we see them at the command line.

Also note that they are coplanar. In other words, they all have the same Z coordinates. That's going to be important later.

figure
patch([1 3 3 1],[1 1 3 3],[0 0 0 0],'r', 'DisplayName','red')
patch([2 4 4 2],[2 2 4 4],[0 0 0 0],'g', 'DisplayName','green')
patch([3 5 5 3],[3 3 5 5],[0 0 0 0],'b', 'DisplayName','blue')

As we can see here, the last patch we created is the first one in the Children list of the Axes.

ax = gca;
ax.Children
ans = 

  3x1 Patch array:

  Patch    (blue)
  Patch    (green)
  Patch    (red)

The last patch added is also the one we see in the areas where they overlap. The blue patch covers the green one, and the green patch covers the red one.

That's because the SortMethod property of the axes is set to 'childorder'.

ax.SortMethod
ans =

childorder

I can change the order of the children by setting the Children property to a permutation of it's current value. Notice what happens to the picture.

ax.Children = ax.Children([2 3 1]);
ax.Children
ans = 

  3x1 Patch array:

  Patch    (green)
  Patch    (red)
  Patch    (blue)

Now the green patch is first, so it covers both the red one and the blue one. The rule with childorder is pretty simple. An object which is near the beginning of the Children list always covers an object which is later in the Children list.

So what happens if we set SortMethod to the other option?

ax.SortMethod = 'depth';

Eww! That's a mess, isn't it? Why would we ever want that? To answer that question, we'll have to take a trip to "the third dimension" (I don't know the markup for adding scifi echo sound effects to that last phrase).

So let's start over. We'll create a new figure so we can come back to that example later.

Next we'll create a simple 3D scene out of patches. In this case the Z coordinates are not the same. Instead of being coplanar, these patches are arranged around the outside of a cube.

figure(2)
patch([1 2 2 1],[1 1 2 2],[1 1 1 1],'r', 'DisplayName','red')
patch([2 2 2 2],[1 1 2 2],[1 2 2 1],'g', 'DisplayName','green')
patch([2 1 1 2],[1 1 2 2],[2 2 2 2],'b', 'DisplayName','blue')
patch([1 1 1 1],[1 1 2 2],[2 1 1 2],'c', 'DisplayName','cyan')
view(3)
ax = gca;
ax.Children
ans = 

  4x1 Patch array:

  Patch    (cyan)
  Patch    (blue)
  Patch    (green)
  Patch    (red)

At first it looks like the same rules apply here. The cyan patch is first, and it covers the red one. Same with the blue and green patches.

But if we permute the children in this case, the picture doesn't change.

ax.Children = ax.Children([4 1 3 2]);
ax.Children
ans = 

  4x1 Patch array:

  Patch    (red)
  Patch    (cyan)
  Patch    (green)
  Patch    (blue)

That's because the SortMethod property has changed.

ax.SortMethod
ans =

depth

The axes has noticed that we have a 3D scene and it has chosen depth instead of childorder. In most cases the axes will choose the correct value and we won't have to worry about our SortMethod. But the property allows us to override the choice that axes makes.

So lets try setting it to childorder for this scene.

ax.SortMethod = 'childorder';

Wow, it turned inside out! Now permuting the children does change the picture.

ax.Children = ax.Children([3 2 1 4]);
ax.Children
ans = 

  4x1 Patch array:

  Patch    (green)
  Patch    (cyan)
  Patch    (red)
  Patch    (blue)

What's happening is that when we use 'depth' for the SortMethod, the graphics system sorts all of the objects in "depth" order. This means that it ensures that the objects which are closer to the viewer cover the objects which are farther from the viewer.

ax.SortMethod = 'depth';

But that still doesn't explain this picture, does it?

figure(1)
ax = gca;
ax.SortMethod = 'depth';

What's going on here is that the technique that the graphics system uses to sort the objects struggles when it encounters coplanar objects. When it finds coplanar objects, it tries to draw them in child order, but it has a number of limitations. Most notably, the default renderer (OpenGL) tends to let lines win over faces in coplanar situations. It does this to make sure that you can always see the edges of a patch, even when that patch is drawn at a funny angle. It actually works pretty well in most cases, but here it is making the edges of the red and blue patches poke through the green patch.

Depth sorting techniques is one of oldest and richest corners of computer graphics programming. Many different techniques have been developed over the years. They all have different combinations of strengths and weaknesses, and they all have different performance characteristics.

Different graphics cards can actually get different results in these coplanar cases. And different renderers can too. The painters renderer, which is used for generating vector file formats like PDF, uses a different sorting technique which has different limitations in this coplanar case.

set(1,'Renderer','painters');

But the depth sort that the painters renderer uses works fine on our scene that doesn't have coplanar patches.

figure(2)
set(2,'Renderer','painters');

I hope that you've learned a little more about an important, but underappreciated axes property.




Published with MATLAB® R2014b


  • print