Code covered by the BSD License  

Highlights from
oaxes - central axis lines through an origin

4.9

4.9 | 10 ratings Rate this file 87 Downloads (last 30 days) File Size: 42.1 KB File ID: #30018
image thumbnail

oaxes - central axis lines through an origin

by

 

13 Jan 2011 (Updated )

Draw central axis lines through an origin point.

| Watch this File

File Information
Description

Oaxes creates a set of axis lines through a specified origin point. Oaxes supports both 2D and 3D views, ticks and tick labels, axis labels, log-scaled axes, and has a plethora of properties, analogous to normal axes properties, that give control over the oaxes object's appearance. In addition, various oaxes-specific properties give the user control over features such as arrows at the axis ends and the extent of the axis lines.

By default, the origin is set at the center of the axes limits, and will remain centered if the parent axes limits change. If a fixed origin point is specified, the axis lines will be drawn using that point as the origin. Additionally, the oaxes object will automatically update in response to changes to many of the parent axes' properties.

See the help text in oaxes.m for more information, including examples.

Oaxes uses a number of undocumented MATLAB features which may cause problems in older versions of MATLAB. If there are workarounds that do not require significant changes, I will add them to the code. MATLAB version 7.10.0 (R2010a) was used to develop and test Oaxes.

Installation: Unpack the contents of the .zip file, then add the top-level folder ("customplots") to the MATLAB path.

Acknowledgements

Axescenter inspired this file.

MATLAB release MATLAB 7.10 (R2010a)
Tags for This File   Please login to tag files.
Please login to add a comment or rating.
Comments and Ratings (27)
21 Aug 2014 Paul de Haas  
31 May 2014 John Barber

@Giuseppe:
1) See my answer and suggested workaround to Felix's question about multiple OAXES. It is not currently possible to have more than one OAXES exist in a given axes. I will consider it for a future release.

2) There is not a way to specify an offset. If you want to show a translated coordinate system, you could simply set the tick labels of the OAXES object to custom values representing the translated coordinates. Be sure to set the tick labels and not the ticks themselves. This trick also works on the standard MATLAB axes object - the tick labels can be independent of the values of the ticks. The drawback is that if the tick locations change (due to limit changes, etc.), the manual tick labels will be incorrect. I'll consider adding an 'offset' property in a future release.

31 May 2014 John Barber

@Sebastian:
Like many of the low-level MATLAB graphics functions, OAXES does not redraw until the MATLAB event queue is processed, which doesn't necessarily happen when you would like it to during function execution. Instead of using the PAUSE command, you can call the MATLAB function DRAWNOW() (see the help file for DRAWNOW for more information). Alternately, you can force the OAXES object to redraw by calling its DRAW() method. If you have a handle OA to the OAXES, simply call OA.draw(). If you don't have the handle, calling oaxes('draw') should also work as long as it can find the OAXES object.

I'm not sure what you mean by "rotate the axis". In 3D views, the axis lines rotate along with all other drawing objects as the camera location is moved. Trying to keep the displayed axis lines fixed on camera moves means that the lines would no longer correspond to the coordinate system. Although it would be interesting to create a camera-independent display mode for a given object (e.g. apply a transform to the object that undoes the effects of the camera location change), that is not in line with the motivation for writing OAXES.

31 May 2014 John Barber

@Felix:
(1) I'm not sure what you mean by inside vs. outside the axis. If you are referring to which side of the axis line the labels are drawn on, then there is currently no way to specify this, but I'll consider adding one in the next release. If you are referring to inside and outside of the plot box/cube, OAXES always draws the labels next to the axis lines, which are always inside of the box.

(2) No, it is not currently possible to define minor ticks. They are calculated automatically for log-scale axes, and not shown for linear scaling. This capability might be added in a future release.

(3) It is not possible for more than one OAXES to exist inside of a given axes. If you want to show more than one OAXES on a given plot, you could try overlaying additional axes objects with transparent backgrounds, and limits linked to the original axes, each containing an OAXES object. See the MATLAB functions linkaxes() and linkprop() for more information.

13 May 2014 Sebastian

Also, a suggestion; it would be nice to be able to rotate the axis. Maybe even have an option to keep it aligned with the current camera direction.

12 May 2014 Sebastian

This is really great. One weird thing, if I use this in a script and I try to set h(X|Y|Z)Label, it does not work correctly. But if I insert a pause(1) immediately before, it does work.

03 Apr 2014 Giuseppe Crescenzio

Hi, I have a problem. I'm making a GUI to show easy roto-translation. Therefore I have to print more reference system on the same plot.
1) oaxes seems to ignore the hold on command. I cannot plot 2 coordinate system on the same plot.
2) can I reset the origin? I mean image I have a point with coordinates (1,2,3) if I translate a reference system form (0,0,0) to i.e. the point (2,2,2)the new coordinates for the point with respect to the new reference system centered in (2,2,2) are (-1,0,1). thus if I give the command oaxes([2 2 2]) what I get is a new reference sys in the point (2,2,2)but the scale reading is wrong(1,2,3) r better is correct wrt the previous ref system.
Is it possible to give an offset to the scale in order to fix it?
I wish to shoe you an image...
thanks
Giuseppe

13 Jun 2013 Felix

I am missing a few functions or can't find them:
-How can I make the ticklabels appear on the outisde of the axis instead inside?
-Is it possible to define the minor ticks separately?
-Is it possible to set multiple axis limits (to make it appear like multiple small axis instead of one long axisLine)

22 May 2013 John Barber

@Mikael: Thank you for the kind feedback. You can try Christian's modification to not display negative arrows. See his comment from 05 Jan 2013 for a link. (Disclaimer: I have not tested this code). I'll think about adding this functionality in my next update, but I'll have to put some thought into the best way to implement it.

Adding grid lines has been on my todo list for a while. Hopefully I'll have some time in the next month or two to work on it. Right now, if you want grid lines, you have to un-hide the parent axes (oa.HideParentAxes = 'off') and turn the grid on as usual. Unfortunately, you end up with the parent axes' axis lines, ticks and tick labels as well - it gets kind of cluttered.

@Christian: Thanks for the kind feedback. I'll take a look at your modified code and consider adding it as an option in my next update.

@cpas1940: If you want to change the label rotation, you can access the handles of the labels in oa.hXLabel, oa.hYLabel, etc. Then you can set the 'Rotation' property as well as any other text properties directly. I'm not sure what you mean by 'having the ylabel centered at (0,0)'. If one of the ylabels were located at (0,0) it would no longer be a label on the end of the axis (assuming oaxes is centered at (0,0) and the limits are [-a +b]). If you are talking about having a rotated label be centered around the y axis line, you can play with the 'HorizontalAlignment' and 'VerticalAlignment' text properties of the labels. Here is an example:

oa = oaxes;
set(oa.hYLabel(1),'Rotation',90)
% (The negative-axis label is now rotated by 90 degrees, but not centered correctly)
set(oa.hYLabel(1),'HorizontalAlignment','right','VerticalAlignment','middle')
% (Now it is centered and no longer overlapping the end of the axis line)

-John

16 May 2013 cpas1940

Another question..is it possible to rotate y-axis label 90-degree and have it centered at (0,0)?

02 May 2013 Mikael Olofsson

Second question: Is it possible to get grid working?

02 May 2013 Mikael Olofsson

Excellent job! Question, though: I would like to get rid of the negative arrows. How can I do that? There doesn't seem to be any property that can be set to achieve that. I am not fluent enough in Matlab to identify where in the code they are actually generated.

02 May 2013 Jawahir  
30 Apr 2013 John Barber

Heather,

The 'HideParentAxes' property controls the visibility of the box around the figure. The default value of 'on' will hide the box, ticks/ticklabels and other features of the parent axes object. You can set this property to 'off', either in the call to generate the oaxes object, or on an existing oaxes object using a function call, set(), or dot notation:
oaxes('HideParentAxes','off');
set(OA,'HideParentAxes','off');
OA.HideParentAxes = 'off';

As you already discovered, the labels for each axis come in pairs (unlike a normal MATLAB axes). The labels should be specified as a <2x1 cell> containing the negative and positive labels, and simply setting the negative label to the empty string will hide it. For example:
OA.XLabel = {'';'+X'};

-John

08 Apr 2013 Heather Moreland

Nevermind...I figured that out. Now is there a way to keep the box around the outside of the figure?

08 Apr 2013 Heather Moreland

This is great! I am wondering if there is a way to remove the axes labels and use the xlabel and ylabel in the property editor. Specfically, I do not want the "negative" axis labels. The code is

function z=graph(x)
a=0.5;
%
xmin=-0.4;
xmax=1.4;
dx=0.01;
%
x=[xmin:dx:xmax];
%
z=x.*(1-x).*(x-a);
%
plot(x,z)
oaxes([0,0,0],'Arrow','off')

Thanks.
-Heather

02 Mar 2013 Michael Karampasis

Great file!It really did the job for me!
Gongats to the creator John Barber!

05 Jan 2013 Christian

Oaxis worked very well for me - thanks for sharing, John.

I just wanted 2 arrow heads though (one to the top and one to the right), and modified the customplots/@customplots/@oaxes/methods.m as follows: https://www.dropbox.com/s/kswquujnal82elx/methods.m

It would be nice to have a documented option instead of my hack.

25 Jul 2012 John Barber

Mukilan,

Thanks for the feedback. I could not reproduce your problem exactly, but here is some information that might be helpful:

Your example code is setting the 'XTickLabel', 'FontName', etc. properties of the parent MATLAB axes (the handle returned by gca), not the properties of the oaxes object. (However, your code does directly set the oaxes object's 'XLabel', 'XColor', etc. properties, and you do not indicate any problem with this part of your code). As documented in the oaxes help, upon initialization, the various text properties of the parent axes are copied to the oaxes, but are then independent. Your code will have no effect on the oaxes tick label font properties. To set the oaxes object's tick label font properties, use the following syntax:

set(oa,'TickLabelFontName','Times New Roman','TickLabelFontSize',14,...)

Note that the pertinent property names for the oaxes object all start with 'TickLabel', unlike the MATLAB axes object. See the oaxes help for a complete list of property names. (I'm not sure why I named them that way - if it bugs enough people, I'll change the names to correspond to the MATLAB axes properties). For both oaxes and MATLAB axes objects, you cannot set different text properties for the x and y axis tick labels - the properties affect each axis.

There is a bug in oaxes that in some cases (including the default case) results in the tick labels not being redrawn when the tick label text properties are changed. I will release an update shortly to fix this. For now, the workaround is to force a redraw after changing the tick label text properties using any of the following (where oa is the handle of the oaxes object):

oa.draw
oaxes('draw')
oaxes draw

Your code sets the 'XTickLabel' property of the parent axes, but not the 'XTick' property. I strongly recommend not doing this because it can lead to incorrect tick labels. For example, type xlim([-1 5]) after setting the 'XTickLabel' property as you specified in your example code. Note that the displayed tick labels do not correspond to the values of the ticks. To avoid this, always set both the 'XTick' and 'XTickLabel' properties together, and when changing back to 'auto' mode for tick placement and labeling, make sure both the 'XTicKMode' and 'XTickLabelMode' are 'auto'. See the MATLAB documentation for 'Axes Properties' for more information.
The behavior of oaxes is identical to the MATLAB axes object in this regard. So if you want to put tick labels at specified locations, set both the 'XTick' and 'XTickLabel' properties of the oaxes object, or just set the 'XTick' property and make sure 'XTickLabelMode' is set to 'auto' (the default). Note that the default behavior of oaxes ticks is to mirror the parent axes tick values ('XTickMode' is set to 'parent' by default). So, unlike the tick label text properties, any changes you make to the parent axes tick values are copied to the oaxes ticks. If you set the 'XTick' property to your own values, 'XTickMode' changes to 'manual'. You can also set it to 'auto' to have oaxes calculate the tick placement rather than copy the parent axes. See the oaxes documentation for more information.

Also note that your example code has errors in the final two 'set' statements - where it reads:

set(gca('XTickLabel'),...

it should say:

set(gca,'XTickLabel',...

01 Jul 2012 Mukilan D

Very good code and also it would be very useful to me. It gave me what I expected. But I could not change the XTicks and YTicks and their labels and also particularly could not change the fontname and fontsize. I have tried with a simple example which is as follows.
x = -pi:0.01:pi
X = x';
y = sin(x);
Y = y'

figure(1)
plot(X,Y,'Linewidth',2);grid on;
oa = oaxes;
oaxes('YColor',[0 0.5 0],'LineWidth',2)
oaxes('XColor',[0 0.5 0],'LineWidth',2)
set(oa,'XLabel',{'-X','X'});
set(oa,'YLabel',{'-Y','Y'});
set(get(oa,'hXLabel'),'fontname','Times New Roman','fontweight','bold','FontSize',12);
set(get(oa,'hYLabel'),'fontname','Times New Roman','fontweight','bold','FontSize',12);
set(gca('XTickLabel'),{'-5','-4','-3','-2','-1','0','1','2','3','4','5'},'fontname','Times New Roman','fontweight','bold','FontSize',20)
set(gca('YTickLabel'),{'1','-0.8','-0.6','-0.4','-0.2','0','0.2','0.4','0.6','0.8','1'},'fontname','Times New Roman','fontweight','bold','FontSize',20)
legend('Sine Wave',2)

04 May 2012 Joachim  
31 Jan 2012 John Barber

Nam,

Thanks for the feedback - I'll take a look at it. For presentation-quality graphics, you might want to try using export_fig to save your figures (link: http://www.mathworks.com/matlabcentral/fileexchange/23629 ).

-John

27 Jan 2012 Namgyun

It seems that arrows dispear when a figure is saved as a pdf file with the "print" function in MATLAB.
Could you check this?

Thank you.

Nam

21 Jun 2011 Dan Knudsen

Thank you very much for this code! Works well on a variety of applications in 2009b (v7.9.0.529), though I haven't tested all features.

21 Jun 2011 Dan Knudsen  
16 May 2011 John Barber

Christian,

Thanks for the feedback. I'll have a new version posted shortly to address the bug.

The axis labels are implemented similarly to the labels for a normal axes. There are two methods to control the display of the axis labels:

1) Set the 'XLabel', etc. property of the oaxes object. This property is a dummy property that is copied to the 'String' properties of the actual label objects. Because there are labels for both the positive and negative sides of each axis, the 'XLabel' property should be specified as a 2x1 cell array. Use the empty string to suppress display of a particular label.

2) Access the label objects directly using their handles. The handles can be found in the 'hXLabel', etc. properties of the oaxes object. As with the 'XLabel' property, 'hXLabel' contains two handles, one for the positive and one for the negative axis label. Using the handles, you can set text size, font, or any other text object property of each label. Note that the labels will be re-created if you delete the label objects. Set the label to the empty string to hide it.

I'll consider adding an 'off' option to the 'AxisLabelLocation' property in a future update.

Thanks,
John

14 May 2011 Christian

I got an error message when trying 'arrow' 'off', simply by typing in:

>> oaxes('arrow','off')
??? Index exceeds matrix dimensions.

Error in ==> oaxes at 643
OA = customplots.oaxes(hAx,pvPairs);

My Matlab version is 7.6.0.324.

Also, I miss an option to switch off end axis notation. I can set AxisLabelLocation to end or side, but not to off. It would also be great to be able to set the tags that are written to the ends of the axes, something like XAxisLabel etc., and to determine whether they should come on both sides or only on the positive side.

- Christian

Updates
19 Jan 2011

Several bug fixes, improved text alignment, added new properties, improved help text. See the release notes in the help text for a full description.

10 Mar 2011

- Properties can be accessed using set/get
- Oaxes responds automatically to property changes
- See the release notes for more details

29 Mar 2011

- Full object-oriented version
- 'Extend' limits mode, internal tick calculation, other new features
- Improved graphics refresh speed

01 Apr 2011

- Several minor bug fixes
- Removed unneeded code from constructor method

02 Apr 2011

- Minor bug fix

06 Jun 2011

- Bug fixes
- Improved redraw speed
- Improved appearance of minor ticks

07 Aug 2012

- Fixed bug when parent axes and figure have different background colors
- Fixed error when deleting an oaxes with 'HideParentAxesMode' set to 'color'
- Fixed tick label text properties bugs

Contact us