changeset 32108:d806017abdcb

[xyz]lim.m: Add ability to query/set limit calculation method. * NEWS.9.md: Announce change in Matlab Compatibility section. * __axis_limits__.m: Add functionality to query/set "[xyz]limitmethod" graphics property. Improve input validation to throw an error if an unrecognized string is given. xlim.m, ylim.m, zlim.m: Add documentation about new feature. Expand BIST tests to test new feature.
author Rik <rik@octave.org>
date Fri, 09 Jun 2023 19:57:20 -0700
parents 4ae5e5b62481
children 40b7b2316d2d
files etc/NEWS.9.md scripts/plot/appearance/private/__axis_limits__.m scripts/plot/appearance/xlim.m scripts/plot/appearance/ylim.m scripts/plot/appearance/zlim.m
diffstat 5 files changed, 132 insertions(+), 23 deletions(-) [+]
line wrap: on
line diff
--- a/etc/NEWS.9.md	Thu Jun 08 20:25:35 2023 -0400
+++ b/etc/NEWS.9.md	Fri Jun 09 19:57:20 2023 -0700
@@ -96,6 +96,9 @@
 - `pcolor` now sets the axes limits to be just large enough to display the
 plotted data (equivalent of `axis tight`).
 
+- `xlim`, `ylim`, `zlim` functions can now query or set the limit calculation
+method which is one of "tickaligned", "tight", or "padded".
+
 ### Alphabetical list of new functions added in Octave 9
 
 * `isuniform`
--- a/scripts/plot/appearance/private/__axis_limits__.m	Thu Jun 08 20:25:35 2023 -0400
+++ b/scripts/plot/appearance/private/__axis_limits__.m	Fri Jun 09 19:57:20 2023 -0700
@@ -26,9 +26,13 @@
 ## -*- texinfo -*-
 ## @deftypefn  {} {@var{limits} =} __axis_limits__ (@var{fcn})
 ## @deftypefnx {} {@var{xmode} =} __axis_limits__ (@var{fcn}, "mode")
+## @deftypefnx {} {@var{xmethod} =} __axis_limits__ (@var{fcn}, "method")
 ## @deftypefnx {} {} __axis_limits__ (@var{fcn}, [@var{x_lo} @var{x_hi}])
 ## @deftypefnx {} {} __axis_limits__ (@var{fcn}, "auto")
 ## @deftypefnx {} {} __axis_limits__ (@var{fcn}, "manual")
+## @deftypefnx {} {} __axis_limits__ (@var{fcn}, "tickaligned")
+## @deftypefnx {} {} __axis_limits__ (@var{fcn}, "tight")
+## @deftypefnx {} {} __axis_limits__ (@var{fcn}, "padded")
 ## @deftypefnx {} {} __axis_limits__ (@var{fcn}, @var{hax}, @dots{})
 ## @deftypefn {} {@var{old_limits} =} __axis_limits__ (@var{fcn}, @dots{})
 ## Internal function that implements common code to query or set the axis
@@ -48,13 +52,18 @@
     retval = get (hax, fcn);
   else
     retval = [];
-    fcnmode = [fcn "mode"];
     arg = varargin{1};
     if (ischar (arg))
       if (strcmpi (arg, "mode"))
-        retval = get (hax, fcnmode);
+        retval = get (hax, [fcn "mode"]);
+      elseif (strcmpi (arg, "method"))
+        retval = get (hax, [fcn "itmethod"]);
       elseif (any (strcmpi (arg, {"auto", "manual"})))
-        set (hax, fcnmode, arg);
+        set (hax, [fcn "mode"], arg);
+      elseif (any (strcmpi (arg, {"tickaligned", "tight", "padded"})))
+        set (hax, [fcn "itmethod"], arg);
+      else
+        error ('%s: unrecognized argument "%s"', fcn, arg);
       endif
     else
       if (! isnumeric (arg) || any (size (arg(:)) != [2, 1]))
--- a/scripts/plot/appearance/xlim.m	Thu Jun 08 20:25:35 2023 -0400
+++ b/scripts/plot/appearance/xlim.m	Fri Jun 09 19:57:20 2023 -0700
@@ -26,9 +26,10 @@
 ## -*- texinfo -*-
 ## @deftypefn  {} {@var{xlimits} =} xlim ()
 ## @deftypefnx {} {@var{xmode} =} xlim ("mode")
+## @deftypefnx {} {@var{xmethod} =} xlim ("method")
 ## @deftypefnx {} {} xlim ([@var{x_lo} @var{x_hi}])
-## @deftypefnx {} {} xlim ("auto")
-## @deftypefnx {} {} xlim ("manual")
+## @deftypefnx {} {} xlim ("mode")
+## @deftypefnx {} {} xlim ("method")
 ## @deftypefnx {} {} xlim (@var{hax}, @dots{})
 ## Query or set the limits of the x-axis for the current plot.
 ##
@@ -38,20 +39,48 @@
 ## With the input query @qcode{"mode"}, return the current x-limit calculation
 ## mode which is either @qcode{"auto"} or @qcode{"manual"}.
 ##
+## With the input query @qcode{"method"}, return the current x-limit
+## calculation method which is either @qcode{"tickaligned"}, @qcode{"tight"},
+## or @qcode{"padded"}.
+##
 ## If passed a 2-element vector [@var{x_lo} @var{x_hi}], the limits of the
 ## x-axis are set to these values and the mode is set to @qcode{"manual"}.
 ## The special values -Inf and Inf can be used to indicate that either
 ## the lower axis limit or upper axis limit should be automatically calculated.
 ##
-## The current plotting mode can be changed by using either @qcode{"auto"}
-## or @qcode{"manual"} as the argument.
+## The current limit calculation "mode" may be one of
+##
+## @table @asis
+## @item @qcode{"auto"} (default)
+## Automatically calculate limits based on the plot data and the currently
+## specified limit calculation method.
+## 
+## @item @qcode{"manual"}
+## Fix axis limits at current values.
+## @end table
+##
+## The current limit calculation method may be one of
+##
+## @table @asis
+## @item @qcode{"tickaligned"} (default)
+## Calculate limits that encompass all of the data and extend outwards to the
+## nearest tick mark.
+## 
+## @item @qcode{"tight"}
+## Calculate limits that exactly fit the data range.
+##
+## @item @qcode{"padded"}
+## Calculate limits that leave a margin around the data of approximately 7% of
+## the data range.
+## @end table
 ##
 ## If the first argument @var{hax} is an axes handle, then operate on
 ## this axes rather than the current axes returned by @code{gca}.
 ##
 ## Programming Note: The @code{xlim} function operates by modifying the
-## @qcode{"xlim"} and @qcode{"xlimmode"} properties of an axes object.  These
-## properties can be directly inspected and altered with @code{get}/@code{set}.
+## @qcode{"xlim"}, @qcode{"xlimmode"}, and @qcode{"xlimitmethod"} properties of
+## an axes object.  These properties can be directly inspected and altered with
+## @code{get}/@code{set}.
 ## @seealso{ylim, zlim, axis, set, get, gca}
 ## @end deftypefn
 
@@ -97,6 +126,8 @@
 %!   xlim ([0, 1.1]);
 %!   assert (get (gca, "xlim"), [0, 1.1], eps);
 %!   assert (xlim ("mode"), "manual");
+%!   xlim ('padded');
+%!   assert (get (gca, "xlimitmethod"), 'padded');
 %! unwind_protect_cleanup
 %!   close (hf);
 %! end_unwind_protect
@@ -107,6 +138,7 @@
 %!   h = plot3 ([0,1.1], [0,1], [0, 1]);
 %!   assert (get (gca, "xlim"), [0, 1.4], eps);
 %!   assert (xlim ("mode"), "auto");
+%!   assert (xlim ("method"), "tickaligned");
 %! unwind_protect_cleanup
 %!   close (hf);
 %! end_unwind_protect
@@ -116,6 +148,7 @@
 %! hf = figure ("visible", "off");
 %! unwind_protect
 %!   h = plot3 ([0,1.1], [0,1], [0, 1]);
+%!   fail ("xlim ('foobar')", 'unrecognized argument "foobar"');
 %!   fail ("xlim ({1, 2})", "LIMITS must be a 2-element vector");
 %!   fail ("xlim ([1, 2, 3])", "LIMITS must be a 2-element vector");
 %!   fail ("xlim ([2, 1])", "axis limits must be increasing");
--- a/scripts/plot/appearance/ylim.m	Thu Jun 08 20:25:35 2023 -0400
+++ b/scripts/plot/appearance/ylim.m	Fri Jun 09 19:57:20 2023 -0700
@@ -25,10 +25,11 @@
 
 ## -*- texinfo -*-
 ## @deftypefn  {} {@var{ylimits} =} ylim ()
-## @deftypefnx {} {@var{xmode} =} ylim ("mode")
+## @deftypefnx {} {@var{ymode} =} ylim ("mode")
+## @deftypefnx {} {@var{ymethod} =} ylim ("method")
 ## @deftypefnx {} {} ylim ([@var{y_lo} @var{y_hi}])
-## @deftypefnx {} {} ylim ("auto")
-## @deftypefnx {} {} ylim ("manual")
+## @deftypefnx {} {} ylim ("mode")
+## @deftypefnx {} {} ylim ("method")
 ## @deftypefnx {} {} ylim (@var{hax}, @dots{})
 ## Query or set the limits of the y-axis for the current plot.
 ##
@@ -38,20 +39,48 @@
 ## With the input query @qcode{"mode"}, return the current y-limit calculation
 ## mode which is either @qcode{"auto"} or @qcode{"manual"}.
 ##
+## With the input query @qcode{"method"}, return the current y-limit
+## calculation method which is either @qcode{"tickaligned"}, @qcode{"tight"},
+## or @qcode{"padded"}.
+##
 ## If passed a 2-element vector [@var{y_lo} @var{y_hi}], the limits of the
 ## y-axis are set to these values and the mode is set to @qcode{"manual"}.
 ## The special values -Inf and Inf can be used to indicate that either
 ## the lower axis limit or upper axis limit should be automatically calculated.
 ##
-## The current plotting mode can be changed by using either @qcode{"auto"}
-## or @qcode{"manual"} as the argument.
+## The current limit calculation "mode" may be one of
+##
+## @table @asis
+## @item @qcode{"auto"} (default)
+## Automatically calculate limits based on the plot data and the currently
+## specified limit calculation method.
+## 
+## @item @qcode{"manual"}
+## Fix axis limits at current values.
+## @end table
+##
+## The current limit calculation method may be one of
+##
+## @table @asis
+## @item @qcode{"tickaligned"} (default)
+## Calculate limits that encompass all of the data and extend outwards to the
+## nearest tick mark.
+## 
+## @item @qcode{"tight"}
+## Calculate limits that exactly fit the data range.
+##
+## @item @qcode{"padded"}
+## Calculate limits that leave a margin around the data of approximately 7% of
+## the data range.
+## @end table
 ##
 ## If the first argument @var{hax} is an axes handle, then operate on
 ## this axes rather than the current axes returned by @code{gca}.
 ##
 ## Programming Note: The @code{ylim} function operates by modifying the
-## @qcode{"ylim"} and @qcode{"ylimmode"} properties of an axes object.  These
-## properties can be directly inspected and altered with @code{get}/@code{set}.
+## @qcode{"ylim"}, @qcode{"ylimmode"}, and @qcode{"ylimitmethod"} properties of
+## an axes object.  These properties can be directly inspected and altered with
+## @code{get}/@code{set}.
 ## @seealso{xlim, zlim, axis, set, get, gca}
 ## @end deftypefn
 
@@ -98,6 +127,8 @@
 %!   ylim (limy);
 %!   assert (get (gca, "ylim"), limy, eps);
 %!   assert (ylim ("mode"), "manual");
+%!   ylim ('padded');
+%!   assert (get (gca, "ylimitmethod"), 'padded');
 %! unwind_protect_cleanup
 %!   close (hf);
 %! end_unwind_protect
@@ -108,6 +139,7 @@
 %!   plot3 ([0,1], [0,1.1], [0, 1]);
 %!   assert (get (gca, "ylim"), [0, 1.4], eps);
 %!   assert (ylim ("mode"), "auto");
+%!   assert (ylim ("method"), "tickaligned");
 %! unwind_protect_cleanup
 %!   close (hf);
 %! end_unwind_protect
--- a/scripts/plot/appearance/zlim.m	Thu Jun 08 20:25:35 2023 -0400
+++ b/scripts/plot/appearance/zlim.m	Fri Jun 09 19:57:20 2023 -0700
@@ -25,10 +25,11 @@
 
 ## -*- texinfo -*-
 ## @deftypefn  {} {@var{zlimits} =} zlim ()
-## @deftypefnx {} {@var{xmode} =} zlim ("mode")
+## @deftypefnx {} {@var{zmode} =} zlim ("mode")
+## @deftypefnx {} {@var{zmethod} =} zlim ("method")
 ## @deftypefnx {} {} zlim ([@var{z_lo} @var{z_hi}])
-## @deftypefnx {} {} zlim ("auto")
-## @deftypefnx {} {} zlim ("manual")
+## @deftypefnx {} {} zlim ("mode")
+## @deftypefnx {} {} zlim ("method")
 ## @deftypefnx {} {} zlim (@var{hax}, @dots{})
 ## Query or set the limits of the z-axis for the current plot.
 ##
@@ -38,20 +39,48 @@
 ## With the input query @qcode{"mode"}, return the current z-limit calculation
 ## mode which is either @qcode{"auto"} or @qcode{"manual"}.
 ##
+## With the input query @qcode{"method"}, return the current z-limit
+## calculation method which is either @qcode{"tickaligned"}, @qcode{"tight"},
+## or @qcode{"padded"}.
+##
 ## If passed a 2-element vector [@var{z_lo} @var{z_hi}], the limits of the
 ## z-axis are set to these values and the mode is set to @qcode{"manual"}.
 ## The special values -Inf and Inf can be used to indicate that either
 ## the lower axis limit or upper axis limit should be automatically calculated.
 ##
-## The current plotting mode can be changed by using either @qcode{"auto"}
-## or @qcode{"manual"} as the argument.
+## The current limit calculation "mode" may be one of
+##
+## @table @asis
+## @item @qcode{"auto"} (default)
+## Automatically calculate limits based on the plot data and the currently
+## specified limit calculation method.
+## 
+## @item @qcode{"manual"}
+## Fix axis limits at current values.
+## @end table
+##
+## The current limit calculation method may be one of
+##
+## @table @asis
+## @item @qcode{"tickaligned"} (default)
+## Calculate limits that encompass all of the data and extend outwards to the
+## nearest tick mark.
+## 
+## @item @qcode{"tight"}
+## Calculate limits that exactly fit the data range.
+##
+## @item @qcode{"padded"}
+## Calculate limits that leave a margin around the data of approximately 7% of
+## the data range.
+## @end table
 ##
 ## If the first argument @var{hax} is an axes handle, then operate on
 ## this axes rather than the current axes returned by @code{gca}.
 ##
 ## Programming Note: The @code{zlim} function operates by modifying the
-## @qcode{"zlim"} and @qcode{"zlimmode"} properties of an axes object.  These
-## properties can be directly inspected and altered with @code{get}/@code{set}.
+## @qcode{"zlim"}, @qcode{"zlimmode"}, and @qcode{"zlimitmethod"} properties of
+## an axes object.  These properties can be directly inspected and altered with
+## @code{get}/@code{set}.
 ## @seealso{xlim, ylim, axis, set, get, gca}
 ## @end deftypefn
 
@@ -98,6 +127,8 @@
 %!   zlim (limz);
 %!   assert (get (gca, "zlim"), limz, eps);
 %!   assert (zlim ("mode"), "manual");
+%!   zlim ('padded');
+%!   assert (get (gca, "zlimitmethod"), 'padded');
 %! unwind_protect_cleanup
 %!   close (hf);
 %! end_unwind_protect
@@ -108,6 +139,7 @@
 %!   plot3 ([0,1], [0,1], [0, 1.1]);
 %!   assert (get (gca, "zlim"), [0, 1.4], eps);
 %!   assert (zlim ("mode"), "auto");
+%!   assert (zlim ("method"), "tickaligned");
 %! unwind_protect_cleanup
 %!   close (hf);
 %! end_unwind_protect