Quantcast
Channel: Undocumented Matlab
Viewing all articles
Browse latest Browse all 219

Customizing axes part 3

$
0
0

In the past two weeks I explained how HG2 (in R2014b) enables us to customize the axes rulers, baselines, box and grid-lines in ways that were previously impossible in HG1 (R2014a or earlier). Today I will describe other useful undocumented customizations of the HG2 axes:

Backdrop

The axes’ Backdrop (a matlab.graphics.axis.decorator.Backdrop object) controls the background color of the axes’ content area. This is normally white, but can be set to any color, including translucency:

% Create the plot
x = -10:0.1:10;
y = 1e7*sin(x)./x; 
hLine = plot(x,y);
hAxes = gca;
box('off');
 
% Set a light-yellow backdrop
hAxes.Backdrop.FaceColor = [1, 1, 0, 0.4];

HG2 axes Backdrop

HG2 axes Backdrop

By default, Backdrop spans the entire (rectangular) axes content area. But we can customize its vertex points using the Face.VertexData property, which accepts an array of 3xN singles:

HG2 axes Backdrop with custom vertex points

HG2 axes Backdrop with custom vertex points

% Note: VertexData is specified in normalized (0-1) units, not data units
hAxes.Backdrop.Face.VertexData = single([0,1,0.8,0; 0,0.43,0.75,1; 0,0,0,0]);  % default: [0,1,1,0; 0,0,1,1; 0,0,0,0]
 
>> hAxes.Backdrop.Face.get
             AmbientStrength: 0.3
             BackFaceCulling: 'none'
                ColorBinding: 'object'
                   ColorData: [4x1 uint8]
                   ColorType: 'truecoloralpha'
             DiffuseStrength: 0.6
            HandleVisibility: 'off'
                     HitTest: 'off'
                       Layer: 'back'
               NormalBinding: 'none'
                  NormalData: []
                      Parent: [1x1 Backdrop]
               PickableParts: 'all'
    SpecularColorReflectance: 1
            SpecularExponent: 10
            SpecularStrength: 0.9
                   StripData: []
                     Texture: []
            TwoSidedLighting: 'off'
                  VertexData: [3x4 single]
               VertexIndices: []
                     Visible: 'on'

The down side is that whenever we modify anything in the axes (or even get some axes property values), Face.VertexData is reset back to its default value of [0,1,1,0; 0,0,1,1; 0,0,0,0], so we need to either update it in a timer and/or in a property listener.

We can create a tint (gradient color) effect by setting the Face.ColorData property to match the vertex points and modifying Face.ColorBinding from the default ‘object’ to ‘interpolated’ (other alternative values are ‘discrete’ and ‘none’):

colorData = uint8([255, 150, 200, 100; ...  % instead of [255;255;0;102] = light-yellow
                   255, 100,  50, 200; ...
                     0,  50, 100, 150; ...
                   102, 150, 200,  50]);
set(hAxes.Backdrop.Face, 'ColorBinding','interpolated', 'ColorData',colorData);

HG2 axes Backdrop with custom vertex, tint

HG2 axes Backdrop with custom vertex, tint

The tint effect does not rely on the vertex – we can set a tinted background for the entire content area by modifying Face.ColorData without modifying the vertexes:

HG2 axes Backdrop with custom tint

HG2 axes Backdrop with custom tint

Of course, one could say that this is not much better than creating a patch that has the specified vertex points and colors. For example:

% Create a patch to replace the backdrop
cdata = [255, 150, 200, 100; ...
         255, 100,  50, 200; ...
           0,  50, 100, 150 ...
        ]' / 255;  % alpha values are not directly accepted by patch CData
vertexData = [0,1,0.8,0; 0,0.43,0.75,1];  % in normalized units
xdata = hAxes.XLim(1) + diff(hAxes.XLim)*vertexData(1,:);  % in data units
ydata = hAxes.YLim(1) + diff(hAxes.YLim)*vertexData(2,:);  % in data units
hPatch = patch(xdata, ydata, 'k', 'Parent',hAxes, 'EdgeColor','none', ...
               'FaceVertexCData',cdata, 'FaceColor','interp', ...
               'FaceVertexAlpha',[102;150;200;50]/255, 'FaceAlpha','interp');

This results in a gradient very similar to the BackDrop, although not exactly the same. Perhaps the color interpolation for BackDrop is different than for patches, or maybe I just made a mistake somewhere above…

Standard patch with custom tint

Standard patch with custom tint

I don’t have a good answer as to why MathWorks chose to add the BackDrop property to HG2 axes and what advantage it might have over a separate patch. If anyone has an idea, please post a comment below. We can be pretty sure that this was discussed at MathWorks, since Michelle Hirsch, who heads Matlab product development at MathWorks, posted a utility that implements a patch-based gradient backdrop back in 2010 and has recently rehosted it on GitHub:

Michelle Hirsch's patch-based gradient backdrop utility

Michelle Hirsch's patch-based gradient backdrop utility

SortMethod

SortMethod is a newly-supported axes property in R2014b. It is new only in the sense that it became documented: It has existed in its present form also in previous Matlab releases, as a hidden axes property (I’m not sure exactly from which release). This is yet another example of an undocumented Matlab functionality that existed for many years before MathWorks decided to make it official (other examples in R2014b are the set of uitab/uitabgroup functions).

SortMethod is important due to its impact on graphic rendering performance: By default, Matlab draws objects in a back-to-front order based on the current view. This means that objects (lines, patches etc.) which should appear “on top” of other objects are drawn last, overlapping the objects “beneath” them. Calculating the order of the objects, especially in complex plots having multiple overlapping segments, can take noticeable time. We can improve performance by telling the renderer to draw objects in the order of the Children property, which is typically the order in which the objects were created. This can be done by setting the axes’ SortMethod property to ‘childorder’ (default=’depth’). Since SortOrder existed in past Matlab releases as well, we can use this technique on the older MATLAB releases just as for R2014b or newer.

In a related matter, we should note that transparent/translucent patches and lines (having a 4th Color element (alpha) value between 0.0 and 1.0) are slower to render for much the same reasons. Reducing the number of transparent/translucent objects will improve graphics rendering performance. Note that specifying a 4th Color element is again an undocumented feature: Matlab officially only supports RGB triplets and named color strings, not RGBA quadruplets. I’ll discuss this aspect next week.

WarpToFill

WarpToFill (default=’on’) is a simple flag that controls whether or not the axes should fill its container (panel or figure), leaving minimal margins. We can consider this as another variant to the documented alternatives of the axis function:

surf(peaks);
set(gca,'WarpToFill','off');

HG2 axes WarpToFill on HG2 axes WarpToFill off

HG2 axes WarpToFill (on, off)

Note that WarpToFill is not new in R2014b – it has existed in its present form also in previous Matlab releases, as a hidden axes property. One would hope that it will finally become officially supported, as SortMethod above has.

Camera

The Camera object (matlab.graphics.axis.camera.Camera3D) controls the 3D camera/lighting of the axes. This is normally controlled via the 3D figure toolbar and related functions (view, camup, campos etc.). We can have better granularity by discretely customizing the internal hidden properties:

>> hAxes.Camera.get
               AspectRatio: 1
                  Children: []
      DepthCalculationHint: 'careful'
                 DepthSort: 'on'
          HandleVisibility: 'off'
                    Parent: [1x1 Axes]
        PlotBoxAspectRatio: [1 1 1]
    PlotBoxAspectRatioMode: 'auto'
                  Position: [-4.06571071756541 -5.45015005218426 4.83012701892219]
                Projection: 'orthographic'
                    Target: [0.5 0.5 0.5]
    TransparencyMethodHint: 'depthpeel'
                  UpVector: [0 0 1]
                 ViewAngle: 10.339584907202
                  Viewport: [1x1 matlab.graphics.general.UnitPosition]
                   Visible: 'on'
                WarpToFill: 'vertical'

This concludes my series on undocumented HG2 axes customizations (at least for now). Next week, I will describe undocumented HG2 plot-line customizations.

 
Related posts:
  1. Customizing axes part 2 Matlab HG2 axes can be customized in many different ways. This article explains some of the undocumented aspects. ...
  2. Customizing axes rulers HG2 axes can be customized in numerous useful ways. This article explains how to customize the rulers. ...
  3. Determining axes zoom state The information of whether or not an axes is zoomed or panned can easily be inferred from an internal undocumented object....
  4. Axes LooseInset property Matlab plot axes have an undocumented LooseInset property that sets empty margins around the axes, and can be set to provide a tighter fit of the axes to their surroundings....
 

Viewing all articles
Browse latest Browse all 219

Trending Articles