How to change the style of the plot box outline without affecting axis style?

I'm trying to reproduce the template of my institute. We are forced to thicken the main axis (xyz) and frame the plot similar to the "box on" command. However, the box and the axis need to have different thicknesses, and its getting worse, the grid can't be used as we have different thicknesses here as well.
Drawing lines on top of the axis is no solution as the axis flip over when I rotate my viewport.
So I need 2 pt main axis, 1 pt borders and 0.5 pt grid. I already tried to find the lines via "findobj", however I was not successful. In theory the lines are there somewhere in "gca", but it depends on the actual viewport which line is what as far as I understood. I need a general solution for this.
Any help is much appreciated :)

 Accepted Answer

I can't seem to find a way to change the axes line color individually... Workaround would be to draw 3 axes and adjust the line thickness for grid, axes, box. See this function and adjust accordingly to your usage / default:
%Example usage
% x = 1:10;
% y = x.^2;
% z = y;
% plot3(x, y, z, 'r')
%
% setDefaultAxes(gca, 'AxesLineWidth', 2, 'BoxLineWidth', 1, 'GridLineWidth', 0.5)
%
% setDefaultAxes(gca, 'AxesLineWidth', 3, 'BoxLineWidth', 2, 'BoxLineColor', [0 1 0], 'GridLineWidth', 1, 'GridLineColor', [1 0 1])
function Cx = setDefaultAxes(Ax, varargin)
P = inputParser;
P.addParameter('AxesLineWidth', 2, @(x) isnumeric(x) && x > 0);
P.addParameter('BoxLineWidth', 1, @(x) isnumeric(x) && x > 0);
P.addParameter('BoxLineColor', [0 0 0], @(x) isnumeric(x) && numel(x) == 3);
P.addParameter('GridLineWidth', 0.5, @(x) isnumeric(x) && x > 0);
P.addParameter('GridLineColor', [0 0 0], @(x) isnumeric(x) && numel(x) == 3);
parse(P, varargin{:});
P = P.Results;
%OPTIONAL: Delete prior axes that have no data in them (in case you want to
%change line thickness on an already-formatted plot with 3 overlayed axes.
Cx = findobj(get(Ax, 'parent'), 'type', 'axes');
EmptyCx = arrayfun(@(x) isempty(allchild(x)), Cx);
delete(Cx(EmptyCx));
if ~isvalid(Ax)
Ax = Cx(~EmptyCx);
Ax = Ax(1);
end
%Create the new axes.
hold(Ax, 'on');
Cx = gobjects(2, 1);
for k = 1:2
Cx(k) = axes;
set(Cx(k), 'TickLength', [0 0], 'XTickLabel', '', 'YTickLabel', '', 'ZTickLabel', '', 'view', get(Ax, 'view'));
end
hold(Ax, 'off');
%Apply the axes-specific formats
set(Ax, 'LineWidth', P.AxesLineWidth, 'Box', 'off', 'XGrid', 'off', 'YGrid', 'off', 'ZGrid', 'off');
set(Cx(1), 'LineWidth', P.BoxLineWidth, 'XColor', P.BoxLineColor, 'YColor', P.BoxLineColor, 'ZColor', P.BoxLineColor, 'Box', 'on');
set(Cx(2), 'LineWidth', P.GridLineWidth, 'GridColor', P.GridLineColor, 'XGrid', 'on', 'YGrid', 'on', 'ZGrid', 'on');
%Reorder axes, recolor background
Cx = [Ax; Cx]; %Need to make sure Ax is top
[Cx(1:end-1).Color] = deal('none'); %set all but last axes to transparent
Cx(end).Color = [1 1 1]; %The last axes will have the white background
set(get(Ax, 'Parent'), 'Children', Cx); %Ensures the the axes with data is always on top

2 Comments

Hey Donald,
thanks for your code. I had to adapt it a little bit as I use daspect for my 3D plots.
To that, there was an issue when rotating the plot after generating it. I was able to solve the problem by linking the axis. For all interested, here is the final solution (although it is really bulky ;) shouldn't be that complicated...) I'm looking forward to easier solutions Mathworks ;)
function [Cx] = setDefaultAxes(Ax, varargin)
P = inputParser;
P.addParameter('AxesLineWidth', 2, @(x) isnumeric(x) && x > 0);
P.addParameter('BoxLineWidth', 1, @(x) isnumeric(x) && x > 0);
P.addParameter('BoxLineColor', [0 0 0], @(x) isnumeric(x) && numel(x) == 3);
P.addParameter('GridLineWidth', 0.5, @(x) isnumeric(x) && x > 0);
P.addParameter('GridLineColor', [0 0 0], @(x) isnumeric(x) && numel(x) == 3);
P.addParameter('daspect', [0 0 0], @(x) isnumeric(x) && numel(x) == 3);
parse(P, varargin{:});
P = P.Results;
%OPTIONAL: Delete prior axes that have no data in them (in case you want to
%change line thickness on an already-formatted plot with 3 overlayed axes.
% Cx = findobj(get(Ax, 'parent'), 'type', 'axes');
% EmptyCx = arrayfun(@(x) isempty(allchild(x)), Cx);
% delete(Cx(EmptyCx));
% if ~isvalid(Ax)
% Ax = Cx(~EmptyCx);
% Ax = Ax(1);
% end
%Create the new axes.
hold(Ax, 'on');
Cx = gobjects(2, 1);
for k = 1:2
Cx(k) = axes;
set(Cx(k), 'TickLength', [0 0], 'XTickLabel', '', 'YTickLabel', '', 'ZTickLabel', '', 'view', get(Ax, 'view'));
if P.daspect
daspect(P.daspect);
end
end
hold(Ax, 'off');
%Apply the axes-specific formats
set(Ax, 'LineWidth', P.AxesLineWidth, 'Box', 'off', 'XGrid', 'off', 'YGrid', 'off', 'ZGrid', 'off');
set(Cx(1), 'LineWidth', P.BoxLineWidth, 'XColor', P.BoxLineColor, 'YColor', P.BoxLineColor, 'ZColor', P.BoxLineColor, 'Box', 'on');
set(Cx(2), 'LineWidth', P.GridLineWidth, 'GridColor', P.GridLineColor, 'XGrid', 'on', 'YGrid', 'on', 'ZGrid', 'on');
%Reorder axes, recolor background
Cx = [Ax; Cx]; %Need to make sure Ax is top
[Cx(1:end-1).Color] = deal('none'); %set all but last axes to transparent
Cx(end).Color = [1 1 1]; %The last axes will have the white background
set(get(Ax, 'Parent'), 'Children', Cx); %Ensures the the axes with data is always on top
l(1) = linkprop([Ax; Cx],'YLim');
l(2) = linkprop([Ax; Cx],'XLim');
l(3) = linkprop([Ax; Cx],'ZLim');
l(4) = linkprop([Ax; Cx],'CameraPosition');
global l;
end
Once more, thank you very much, Donald!
You're welcome - and nice use of linkprop!
Yeah, I hope MathWork adds the feature to adjust grid, axes, and border lines separately... They seem to be slowly adding similar features (such as GridColor and GridAlpha in 2014b) but stopped before adding GridLineWidth, AxesLineWidth, BoxLineWidth...
Here's a place where you can suggest changes in the Answer section:

Sign in to comment.

More Answers (0)

Categories

Products

Asked:

on 5 Oct 2017

Edited:

on 6 Oct 2017

Community Treasure Hunt

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

Start Hunting!