scripts/plot/axis.m
author Ben Abbott <bpabbott@mac.com>
Tue Jun 09 06:33:10 2009 +0200 (9 months ago)
changeset 9319 d6052da689e2
parent 9277be84e9654feb
child 9341f58cf8c3c63c
permissions -rw-r--r--
axis.m: Fix bug for 'axis tight' with multiple lines, modify demo.
     1 ## Copyright (C) 1994, 1995, 1996, 1997, 1999, 2000, 2002, 2003, 2004,
     2 ##               2005, 2006, 2007, 2008, 2009 John W. Eaton
     3 ##
     4 ## This file is part of Octave.
     5 ##
     6 ## Octave is free software; you can redistribute it and/or modify it
     7 ## under the terms of the GNU General Public License as published by
     8 ## the Free Software Foundation; either version 3 of the License, or (at
     9 ## your option) any later version.
    10 ##
    11 ## Octave is distributed in the hope that it will be useful, but
    12 ## WITHOUT ANY WARRANTY; without even the implied warranty of
    13 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    14 ## General Public License for more details.
    15 ##
    16 ## You should have received a copy of the GNU General Public License
    17 ## along with Octave; see the file COPYING.  If not, see
    18 ## <http://www.gnu.org/licenses/>.
    19 
    20 ## -*- texinfo -*-
    21 ## @deftypefn {Function File} {} axis (@var{limits})
    22 ## Set axis limits for plots.
    23 ##
    24 ## The argument @var{limits} should be a 2, 4, or 6 element vector.  The
    25 ## first and second elements specify the lower and upper limits for the x
    26 ## axis.  The third and fourth specify the limits for the y-axis, and the
    27 ## fifth and sixth specify the limits for the z-axis.
    28 ##
    29 ## Without any arguments, @code{axis} turns autoscaling on.  
    30 ##
    31 ## With one output argument, @code{x = axis} returns the current axes 
    32 ##
    33 ## The vector argument specifying limits is optional, and additional
    34 ## string arguments may be used to specify various axis properties.  For
    35 ## example,
    36 ##
    37 ## @example
    38 ## axis ([1, 2, 3, 4], "square");
    39 ## @end example
    40 ##
    41 ## @noindent
    42 ## forces a square aspect ratio, and
    43 ##
    44 ## @example
    45 ## axis ("labely", "tic");
    46 ## @end example
    47 ##
    48 ## @noindent
    49 ## turns tic marks on for all axes and tic mark labels on for the y-axis
    50 ## only.
    51 ##
    52 ## @noindent
    53 ## The following options control the aspect ratio of the axes.
    54 ##
    55 ## @table @code
    56 ## @item "square"
    57 ## Force a square aspect ratio.
    58 ## @item "equal"
    59 ## Force x distance to equal y-distance.
    60 ## @item "normal"
    61 ## Restore the balance.
    62 ## @end table
    63 ##
    64 ## @noindent
    65 ## The following options control the way axis limits are interpreted.
    66 ##
    67 ## @table @code
    68 ## @item "auto" 
    69 ## Set the specified axes to have nice limits around the data
    70 ## or all if no axes are specified.
    71 ## @item "manual" 
    72 ## Fix the current axes limits.
    73 ## @item "tight"
    74 ## Fix axes to the limits of the data.
    75 ## @end table
    76 ##
    77 ## @noindent
    78 ## The option @code{"image"} is equivalent to @code{"tight"} and
    79 ## @code{"equal"}.
    80 ##
    81 ## @noindent
    82 ## The following options affect the appearance of tic marks.
    83 ##
    84 ## @table @code
    85 ## @item "on" 
    86 ## Turn tic marks and labels on for all axes.
    87 ## @item "off"
    88 ## Turn tic marks off for all axes.
    89 ## @item "tic[xyz]"
    90 ## Turn tic marks on for all axes, or turn them on for the
    91 ## specified axes and off for the remainder.
    92 ## @item "label[xyz]"
    93 ## Turn tic labels on for all axes, or turn them on for the 
    94 ## specified axes and off for the remainder.
    95 ## @item "nolabel"
    96 ## Turn tic labels off for all axes.
    97 ## @end table
    98 ## Note, if there are no tic marks for an axis, there can be no labels.
    99 ##
   100 ## @noindent
   101 ## The following options affect the direction of increasing values on
   102 ## the axes.
   103 ##
   104 ## @table @code
   105 ## @item "ij"
   106 ## Reverse y-axis, so lower values are nearer the top.
   107 ## @item "xy" 
   108 ## Restore y-axis, so higher values are nearer the top. 
   109 ## @end table
   110 ## 
   111 ## If an axes handle is passed as the first argument, then operate on
   112 ## this axes rather than the current axes.
   113 ## @end deftypefn
   114 
   115 ## Author: jwe
   116 
   117 function varargout = axis (varargin)
   118 
   119   [h, varargin, nargin] = __plt_get_axis_arg__ ("axis", varargin{:});
   120 
   121   oldh = gca ();
   122   unwind_protect
   123     axes (h);
   124     varargout = cell (max (nargin == 0, nargout), 1);
   125     if (isempty (varargout))
   126       __axis__ (h, varargin{:});
   127     else
   128       [varargout{:}] = __axis__ (h, varargin{:});
   129     endif
   130   unwind_protect_cleanup
   131     axes (oldh);
   132   end_unwind_protect
   133 
   134 endfunction
   135 
   136 function curr_axis = __axis__ (ca, ax, varargin)
   137 
   138   if (nargin == 1)
   139     if (nargout == 0)
   140       set (ca, "xlimmode", "auto", "ylimmode", "auto", "zlimmode", "auto");
   141     else
   142       xlim = get (ca, "xlim");
   143       ylim = get (ca, "ylim");
   144       zlim = get (ca, "zlim");
   145       curr_axis = [xlim, ylim, zlim];
   146     endif
   147 
   148   elseif (ischar (ax))
   149     len = length (ax);
   150 
   151     ## 'matrix mode' to reverse the y-axis
   152     if (strcmpi (ax, "ij"))
   153       set (ca, "ydir", "reverse");
   154     elseif (strcmpi (ax, "xy"))
   155       set (ca, "ydir", "normal");
   156 
   157       ## aspect ratio
   158     elseif (strcmpi (ax, "image"))
   159       __axis__ (ca, "equal")
   160       __do_tight_option__ (ca);
   161     elseif (strcmpi (ax, "square"))
   162       if (__gnuplot_has_feature__ ("screen_coordinates_for_{lrtb}margin"))
   163         set (ca, "dataaspectratio", [1, 1, 1]);
   164       else
   165         x = xlim;
   166         y = ylim;
   167         set (ca, "dataaspectratio", [(y(2)-y(1)), (x(2)-x(1)), 1]);
   168       endif
   169     elseif  (strcmp (ax, "equal"))
   170       if (__gnuplot_has_feature__ ("screen_coordinates_for_{lrtb}margin"))
   171         x = xlim;
   172         y = ylim;
   173         set (ca, "dataaspectratio", [(x(2)-x(1)), (y(2)-y(1)), 1]);
   174       else
   175         set (ca, "dataaspectratio", [1, 1, 1]);
   176       endif
   177     elseif (strcmpi (ax, "normal"))
   178       set (ca, "dataaspectratiomode", "auto");
   179 
   180       ## axis limits
   181     elseif (len >= 4 && strcmpi (ax(1:4), "auto"))
   182       if (len > 4)
   183 	if (any (ax == "x"))
   184 	  set (ca, "xlimmode", "auto");
   185 	endif
   186 	if (any (ax == "y"))
   187 	  set (ca, "ylimmode", "auto");
   188 	endif
   189 	if (any (ax == "z"))
   190 	  set (ca, "zlimmode", "auto");
   191 	endif
   192       else
   193 	set (ca, "xlimmode", "auto", "ylimmode", "auto", "zlimmode", "auto");
   194       endif
   195     elseif (strcmpi (ax, "manual"))
   196       ## fixes the axis limits, like axis(axis) should;
   197       set (ca, "xlimmode", "manual", "ylimmode", "manual", "zlimmode", "manual");
   198     elseif (strcmpi (ax, "tight"))
   199       ## sets the axis limits to the min and max of all data.
   200       __do_tight_option__ (ca);
   201       ## tic marks
   202     elseif (strcmpi (ax, "on") || strcmpi (ax, "tic"))
   203       set (ca, "xtickmode", "auto", "ytickmode", "auto", "ztickmode", "auto");
   204       if (strcmpi (ax, "on"))
   205         set (ca, "xticklabelmode", "auto", "yticklabelmode", "auto",
   206 	   "zticklabelmode", "auto");
   207       endif
   208       set (ca, "visible", "on");
   209     elseif (strcmpi (ax, "off"))
   210       set (ca, "xtick", [], "ytick", [], "ztick", []);
   211       set (ca, "visible", "off");
   212     elseif (len > 3 && strcmpi (ax(1:3), "tic"))
   213       if (any (ax == "x"))
   214 	set (ca, "xtickmode", "auto");
   215       else
   216 	set (ca, "xtick", []);
   217       endif
   218       if (any (ax == "y"))
   219 	set (ca, "ytickmode", "auto");
   220       else
   221 	set (ca, "ytick", []);
   222       endif
   223       if (any (ax == "z"))
   224 	set (ca, "ztickmode", "auto");
   225       else
   226 	set (ca, "ztick", []);
   227       endif
   228     elseif (strcmpi (ax, "label"))
   229       set (ca, "xticklabelmode", "auto", "yticklabelmode", "auto",
   230 	   "zticklabelmode", "auto");
   231     elseif (strcmpi (ax, "nolabel"))
   232       set (ca, "xticklabel", "", "yticklabel", "", "zticklabel", "");
   233     elseif (len > 5 && strcmpi (ax(1:5), "label"))
   234       if (any (ax == "x"))
   235 	set (ca, "xticklabelmode", "auto");
   236       else
   237 	set (ca, "xticklabel", "");
   238       endif
   239       if (any (ax == "y"))
   240 	set (ca, "yticklabelmode", "auto");
   241       else
   242 	set (ca, "yticklabel", "");
   243       endif
   244       if (any (ax == "z"))
   245 	set (ca, "zticklabelmode", "auto");
   246       else
   247 	set (ca, "zticklabel", "");
   248       endif
   249 
   250     else
   251       warning ("unknown axis option '%s'", ax);
   252     endif
   253 
   254   elseif (isvector (ax))
   255 
   256     len = length (ax);
   257 
   258     if (len != 2 && len != 4 && len != 6)
   259       error ("axis: expecting vector with 2, 4, or 6 elements");
   260     endif
   261 
   262     for i = 1:2:len
   263       if (ax(i) == ax(i+1))
   264 	error ("axis: limits(%d) cannot equal limits(%d)", i, i+1);
   265       endif
   266     endfor
   267 
   268     if (len > 1)
   269       set (ca, "xlim", [ax(1), ax(2)]);
   270     endif
   271 
   272     if (len > 3)
   273       set (ca, "ylim", [ax(3), ax(4)]);
   274     endif
   275 
   276     if (len > 5)
   277       set (ca, "zlim", [ax(5), ax(6)]);
   278     endif
   279 
   280   else
   281     error ("axis: expecting no args, or a vector with 2, 4, or 6 elements");
   282   endif
   283 
   284   if (! isempty (varargin))
   285     __axis__ (ca, varargin{:});
   286   endif
   287 
   288 endfunction
   289 
   290 function lims = __get_tight_lims__ (ca, ax)
   291 
   292   ## Get the limits for axis ("tight").
   293   ## AX should be one of "x", "y", or "z".
   294   kids = findobj (ca, "-property", strcat (ax, "data"));
   295   if (isempty (kids))
   296     ## Return the current limits.
   297     lims = get (ca, strcat (ax, "lim"));
   298   else
   299     data = get (kids, strcat (ax, "data"));
   300     if (iscell (data))
   301       data = data (find (! cellfun (@isempty, data)));
   302       if (! isempty (data))
   303         lims(1) = min (cellfun (@min, data)(:));
   304         lims(2) = max (cellfun (@max, data)(:));
   305       else
   306         lims = [0, 1];
   307       endif
   308     else
   309       lims = [min(data(:)), max(data(:))];
   310     endif
   311   endif
   312 endfunction
   313 
   314 function __do_tight_option__ (ca)
   315 
   316   set (ca,
   317        "xlim", __get_tight_lims__ (ca, "x"),
   318        "ylim", __get_tight_lims__ (ca, "y"),
   319        "zlim", __get_tight_lims__ (ca, "z"));
   320 
   321 endfunction
   322 
   323 %!demo
   324 %! t=0:0.01:2*pi; x=sin(t);
   325 %!
   326 %! subplot(221);
   327 %! plot(t, x);
   328 %! title("normal plot");
   329 %!
   330 %! subplot(222);
   331 %! plot(t, x);
   332 %! title("square plot");
   333 %! axis("square");
   334 %!
   335 %! subplot(223);
   336 %! plot(t, x);
   337 %! title("equal plot");
   338 %! axis("equal");
   339 %! 
   340 %! subplot(224);
   341 %! plot(t, x);
   342 %! title("normal plot again");
   343 %! axis("normal");
   344 
   345 %!demo
   346 %! t=0:0.01:2*pi; x=sin(t);
   347 %!
   348 %! subplot(121);
   349 %! plot(t, x);
   350 %! title("ij plot");
   351 %! axis("ij");
   352 %!
   353 %! subplot(122);
   354 %! plot(t, x);
   355 %! title("xy plot");
   356 %! axis("xy");
   357 
   358 %!demo
   359 %! t=0:0.01:2*pi; x=sin(t);
   360 %!
   361 %! subplot(331);
   362 %! plot(t, x);
   363 %! title("x tics and labels");
   364 %! axis("ticx");
   365 %!
   366 %! subplot(332);
   367 %! plot(t, x);
   368 %! title("y tics and labels");
   369 %! axis("ticy");
   370 %!
   371 %! subplot(333);
   372 %! plot(t, x);
   373 %! title("axis off");
   374 %! axis("off");
   375 %!
   376 %! subplot(334);
   377 %! plot(t, x);
   378 %! title("x and y tics, x labels");
   379 %! axis("labelx","tic");
   380 %!
   381 %! subplot(335);
   382 %! plot(t, x);
   383 %! title("x and y tics, y labels");
   384 %! axis("labely","tic");
   385 %!
   386 %! subplot(336);
   387 %! plot(t, x);
   388 %! title("all tics but no labels");
   389 %! axis("nolabel","tic");
   390 %!
   391 %! subplot(337);
   392 %! plot(t, x);
   393 %! title("x tics, no labels");
   394 %! axis("nolabel","ticx");
   395 %!
   396 %! subplot(338);
   397 %! plot(t, x);
   398 %! title("y tics, no labels");
   399 %! axis("nolabel","ticy");
   400 %!
   401 %! subplot(339);
   402 %! plot(t, x);
   403 %! title("all tics and labels");
   404 %! axis("on");
   405 
   406 %!demo
   407 %! t=0:0.01:2*pi; x=sin(t);
   408 %!
   409 %! subplot(321);
   410 %! plot(t, x);
   411 %! title("axes at [0 3 0 1]")
   412 %! axis([0,3,0,1]);
   413 %!
   414 %! subplot(322);
   415 %! plot(t, x);
   416 %! title("auto");
   417 %! axis("auto");
   418 %!
   419 %! subplot(323);
   420 %! plot(t, x, ";sine [0:2pi];"); hold on;
   421 %! plot(-3:3,-3:3, ";line (-3,-3)->(3,3);"); hold off;
   422 %! title("manual");
   423 %! axis("manual");
   424 %!
   425 %! subplot(324);
   426 %! plot(t, x, ";sine [0:2pi];");
   427 %! title("axes at [0 3 0 1], then autox");
   428 %! axis([0,3,0,1]); axis("autox");
   429 %!
   430 %! subplot(325);
   431 %! plot(t, x, ";sine [0:2p];");
   432 %! axis([3,6,0,1]); axis("autoy");
   433 %! title("axes at [3 6 0 1], then autoy");
   434 %!
   435 %! subplot(326);
   436 %! plot(t, sin(t), t, -2*sin(t/2))
   437 %! axis("tight");
   438 %! title("tight");
   439 
   440 %!demo
   441 %! clf
   442 %! axis image
   443 %! x=0:0.1:10;
   444 %! plot(x,sin(x))
   445 %! axis image
   446 %! title("image")
   447 
   448