changeset 32603:1af4c4b05ec6 bytecode-interpreter

maint: Merge default to bytecode-interpreter.
author Nicholas R. Jankowski <jankowski.nicholas@gmail.com>
date Thu, 14 Dec 2023 23:51:45 -0500
parents 0532fdb2a3d2 (current diff) 65084aa09317 (diff)
children 4fd9c68e4c7a
files
diffstat 5 files changed, 509 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/etc/NEWS.10.md	Wed Dec 13 18:19:37 2023 -0500
+++ b/etc/NEWS.10.md	Thu Dec 14 23:51:45 2023 -0500
@@ -12,12 +12,17 @@
 to 'rtick' by the function `rticks` will only include the center tick mark
 value if it is specified.
 
+- `
+
 ### Matlab compatibility
 
 - `height` and `width` are now aliases for the `rows` and `columns` functions.
 
 ### Alphabetical list of new functions added in Octave 10
 
+* `rticklabels`
+* `tticklabels`
+
 ### Deprecated functions, properties, and operators
 
 The following functions and properties have been deprecated in Octave 10
--- a/scripts/plot/appearance/module.mk	Wed Dec 13 18:19:37 2023 -0500
+++ b/scripts/plot/appearance/module.mk	Thu Dec 14 23:51:45 2023 -0500
@@ -38,10 +38,12 @@
   %reldir%/orient.m \
   %reldir%/pbaspect.m \
   %reldir%/rticks.m \
+  %reldir%/rticklabels.m \
   %reldir%/shading.m \
   %reldir%/specular.m \
   %reldir%/text.m \
   %reldir%/thetaticks.m \
+  %reldir%/tticklabels.m \
   %reldir%/title.m \
   %reldir%/view.m \
   %reldir%/whitebg.m \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/plot/appearance/rticklabels.m	Thu Dec 14 23:51:45 2023 -0500
@@ -0,0 +1,255 @@
+########################################################################
+##
+## Copyright (C) 2017-2023 The Octave Project Developers
+##
+## See the file COPYRIGHT.md in the top-level directory of this
+## distribution or <https://octave.org/copyright/>.
+##
+## This file is part of Octave.
+##
+## Octave is free software: you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## Octave is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with Octave; see the file COPYING.  If not, see
+## <https://www.gnu.org/licenses/>.
+##
+########################################################################
+
+## -*- texinfo -*-
+## @deftypefn  {} {@var{labels} =} rticklabels
+## @deftypefnx {} {} rticklabels (@var{tickval})
+## @deftypefnx {} {@dots{} =} rticklabels (@var{hax}, @dots{})
+## Query or set the tick labels on the r-axis of a polar plot.
+##
+## When called without an argument, return a cell array of strings of the
+## current rtick labels.
+##
+## When called with the argument @var{tickval} being a cell array of strings
+## or a vector of numbers, the labels will change to match these values.
+## Note that the center point of the plots made by @code{polar }are never
+## labeled, so the first specified label will be applied to the second rtick
+## location.  If fewer labels are specified than the current number of ticks,
+## those labels will be applied to the innermost tick labels, and blank labels
+## will be appended to the remainder.  If the specified label count exceeds the
+## number of tick labels, excess labels are ignored.
+##
+## If the first argument @var{hax} is an axes handle, then operate on
+## this axis rather than the current axes returned by @code{gca}.
+##
+## Requesting a return value when calling @code{rticklabels} to set a property
+## value will result in an error.
+##
+## Compatability Note:  The 'mode' property for rticklabels has not yet been
+##                      implemented.
+##
+## @seealso{polar, rticks, tticklabels, xticklabels, yticklabels, zticklabels,
+## get, set}
+## @end deftypefn
+
+## FIXME:  Octave's polar plot implementation does not currently create the
+##         properties rticklabel, rticklabelmode, and rtickmode.  Fully
+##         implemented versions of those proporties could simplify much of the
+##         code below, which could then mimick much the behavior of the
+##         equivalent Cartesian functions.
+
+function labels = rticklabels (varargin)
+  [hax, varargin, nargs] = __plt_get_axis_arg__ ("rticklabels", varargin{:});
+
+  if (nargs > 1)
+    print_usage;
+  endif
+
+  returnlabels = true;
+
+  ## Check first input for axes handle and remove from argument list.
+  if (nargs > 0)
+    ## Single remaining input must be tick labels and should be a numeric
+    ## vector or a cell vector of numbers and strings.
+
+    ## error if trying to request and set values simultaneously
+    if (nargout > 0)
+      error ("rticklabels: cannot set and return labels simultaneously");
+    endif
+
+    returnlabels = false;
+    arg = varargin{1};
+
+    if isnumeric (arg)
+      ## All inputs handled the same way as cells. (:) permits nonvectors.
+      cellarg_num = ones (1, numel (arg));
+      cellarg_char = zeros (1, numel (arg));
+      arg = num2cell (arg(:));
+
+    elseif (iscell (arg))
+
+      if (! all ((cellarg_num = cellfun ('isnumeric', arg))
+                           | (cellarg_char = cellfun ('ischar', arg))))
+        error ("rticklabels: TICKVAL cell must contain numbers or strings");
+      endif
+
+    else
+      error (["rticklabels: TICKVAL must be numeric or a cell ", ...
+              "containing numbers and strings"]);
+    endif
+
+  ## Finish converting TICVAL into a cellstr
+
+  ## Convert numeric elements to characters and make it a 1-D cell array.
+  arg(cellarg_num) = cellfun (@num2str, arg(cellarg_num), ...
+                                "UniformOutput", false);
+  arg = arg(:);
+  endif
+
+  if (isempty (hax))
+    hax = gca ();
+  endif
+
+  ## Error if the remaining input
+  polarhandle = findall (hax, "tag", "polar_grid");
+
+  ## Error if hax does not point to a polar plot with r elements.
+  if (isempty (polarhandle))
+    error ("rticklabels: rticklabels can only be used on a polar plot");
+  elseif (! isfield (get (hax), "rtick") )
+    error ("rticklabels: rtick property not defined for current axes");
+  endif
+
+  ## Get count of radius and theta curves.
+  nr = numel (get (hax, "rtick")); # Must check if it includes unlabeled center.
+  nt = numel (get (hax, "ttick"));
+  rt_label_handles = get (polarhandle, "children");
+
+  ## Center is never labeled in polar plots.
+  ## If rtick does not include unlabled center, label_count = 2*nr+2*nt-1,
+  ## otherwise label_count = 2*nr+2*nt+1 and nr should be reduced by 1
+  ## to prevent attempts to get label value from nonlabel handle.
+  if (2 * (nr + nt) + 1 > numel (rt_label_handles))
+    nr--;
+  endif
+
+  ## rtick and ttick object ordering
+  ##  1:nt = text handles containing theta labels (reverse order)
+  ##  nt+1:2*nt = line object handles for ttick radial grid lines
+  ##  2*nt+1:2*nt+nr = text handles containing nr rtick labels (reverse order)
+  ##  2*nt+nr+1:2*nt+2*nr = line object handles for rtick circles
+  ##  end = patch object handle for darker outside border
+
+  rlabelrange = 2*nt + [nr:-1:1]; # Flip back to increasing order.
+
+  if (nargs == 0)
+    ## Get radius labels.
+    labels = get (rt_label_handles(rlabelrange), "string");
+
+  else
+    ## Set new label values.
+
+    if isempty (arg)
+      ## If an empty cell or array is set, set all labels to "".
+      arg = cell (nr, 1);
+      arg(:) = {""};
+
+    else
+      ## Pad and trim arg as needed to match number of labels.
+      if (nr < numel (arg))
+        arg (nr + 1 : end) = [];
+      else
+        arg(end + 1 : nr) = {""};
+      endif
+    endif
+
+    ## Replace labels with values from arg, ensure column vector.
+    set (rt_label_handles(rlabelrange), {"string"}, arg(:));
+  endif
+
+endfunction
+
+%!test
+%! t = [0:15:180] * pi / 180;
+%! r = sin (t);
+%! hf = figure ("visible", "off");
+%! unwind_protect
+%!   hp = polar (t, r);
+%!   hax = gca ();
+%!   rticks (hax, [0, 0.5, 1]);
+%!   assert (rticklabels (hax), {"0.5"; "1"});
+%!   rticklabels (hax, [1 2]);
+%!   assert (rticklabels (hax), {"1"; "2"});
+%!   rticklabels (hax, [3 4]');
+%!   assert (rticklabels (hax), {"3"; "4"});
+%!   rticklabels (hax, {5, 6});
+%!   assert (rticklabels (hax), {"5"; "6"});
+%!   rticklabels (hax, {"a", "bee"});
+%!   assert (rticklabels (hax), {"a"; "bee"});
+%!   rticklabels (hax, {1, "two"});
+%!   assert (rticklabels (hax), {"1"; "two"});
+%!   rticklabels (hax, {1, 2, 3, 4});
+%!   assert (rticklabels (hax), {"1"; "2"});
+%!   rticklabels (hax, [5, 6, 7, 8]);
+%!   assert (rticklabels (hax), {"5"; "6"});
+%!   rticklabels (hax, {1});
+%!   assert (rticklabels (hax), {"1"; ""});
+%!   rticklabels (hax, {1,2});
+%!   assert (rticklabels (hax), {"1"; "2"});
+%!   rticklabels (hax, []);
+%!   assert (rticklabels (hax), {""; ""});
+%!   rticklabels (hax, {1,2});
+%!   assert (rticklabels (hax), {"1"; "2"});
+%!   rticklabels (hax, {});
+%!   assert (rticklabels (hax), {""; ""});
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
+
+
+## Test input validation
+%!test
+%! hf = figure ("visible", "off");
+%! unwind_protect
+%!   hax = gca ();
+%!   fail ("rticklabels (1,2,3)", "Invalid call");
+%!   fail ("rticklabels (-1, 2)", "Invalid call");
+%!   fail ("rticklabels (hax, 2, 3)", "Invalid call");
+%!   fail ("rticklabels (hf, 2)", "Invalid call");
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
+
+%!test
+%! hf = figure ("visible", "off");
+%! unwind_protect
+%!   hax = gca ();
+%!   fail ("tmp = rticklabels ([1, 2, 3])", "cannot set and return labels simultaneously");
+%!   fail ("tmp = rticklabels (hax, [1, 2, 3])", "cannot set and return labels simultaneously");
+%!   fail ("rticklabels (hax, {{1}, 'two', 3})", "TICKVAL cell must contain numbers or strings");
+%!   fail ("rticklabels (hax, {1, 'two', false})", "TICKVAL cell must contain numbers or strings");
+%!   fail ("rticklabels (hax, {1, struct()})", "TICKVAL cell must contain numbers or strings");
+%!   fail ("rticklabels (hax, struct())", "TICKVAL must be numeric or a cell containing");
+%!   fail ("rticklabels (hax, [true false])", "TICKVAL must be numeric or a cell containing");
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
+
+%!test
+%! t = [0:45:180] * pi / 180;
+%! r = sin (t);
+%! hf = figure ("visible", "off");
+%! unwind_protect
+%!   hp = plot (t, r);
+%!   hax = gca ();
+%!   fail ("rticklabels (hax, 1)", "rticklabels can only be used on a polar plot");
+%!   fail ("rticklabels ({1})", "rticklabels can only be used on a polar plot");
+%!   hp = polar (t, r);
+%!   hax = gca ();
+%!   delete (findall (hax, "tag", "polar_grid"));
+%!   fail ("rticklabels (hax, 1)", "rticklabels can only be used on a polar plot");
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/plot/appearance/tticklabels.m	Thu Dec 14 23:51:45 2023 -0500
@@ -0,0 +1,245 @@
+########################################################################
+##
+## Copyright (C) 2017-2023 The Octave Project Developers
+##
+## See the file COPYRIGHT.md in the top-level directory of this
+## distribution or <https://octave.org/copyright/>.
+##
+## This file is part of Octave.
+##
+## Octave is free software: you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## Octave is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with Octave; see the file COPYING.  If not, see
+## <https://www.gnu.org/licenses/>.
+##
+########################################################################
+
+## -*- texinfo -*-
+## @deftypefn  {} {@var{labels} =} tticklabels
+## @deftypefnx {} {} tticklabels (@var{tickval})
+## @deftypefnx {} {@dots{} =} tticklabels (@var{hax}, @dots{})
+## Query or set the tick labels on the theta-axis of a polar plot.
+##
+## When called without an argument, return a cell array of strings of the
+## current ttick labels.
+##
+## When called with the argument @var{tickval} being a cell array of strings
+## or a vector of numbers, the labels will change to match these values.
+##
+## If fewer labels are specified than the current number of ticks,
+## those labels will be applied to the innermost tick labels, and blank labels
+## will be appended to the remainder.  If the specified label count exceeds the
+## number of tick labels, excess labels are ignored.
+##
+## If the first argument @var{hax} is an axes handle, then operate on
+## this axis rather than the current axes returned by @code{gca}.
+##
+## Requesting a return value when calling @code{tticklabels} to set a property
+## value will result in an error.
+##
+## Compatability Note:  The 'mode' property for tticklabels has not yet been
+##                      implemented.
+##
+## @seealso{polar, thetaticks, rticklabels, xticklabels, yticklabels,
+## zticklabels, get, set}
+## @end deftypefn
+
+## FIXME:  Octave's polar plot implementation does not currently create the
+##         properties rticklabel, rticklabelmode, and rtickmode.  Fully
+##         implemented versions of those proporties could simplify much of the
+##         code below, which could then mimick much the behavior of the
+##         equivalent Cartesian functions.
+
+function labels = tticklabels (varargin)
+  [hax, varargin, nargs] = __plt_get_axis_arg__ ("tticklabels", varargin{:});
+
+  if (nargs > 1)
+    print_usage;
+  endif
+
+  returnlabels = true;
+
+  ## Check first input for axes handle and remove from argument list.
+  if (nargs > 0)
+    ## Single remaining input must be tick labels and should be a numeric
+    ## vector or a cell vector of numbers and strings.
+
+    ## error if trying to request and set values simultaneously
+    if (nargout > 0)
+      error ("tticklabels: cannot set and return labels simultaneously");
+    endif
+
+    returnlabels = false;
+    arg = varargin{1};
+
+    if isnumeric (arg)
+      ## All inputs handled the same way as cells. (:) permits nonvectors.
+      cellarg_num = ones (1, numel (arg));
+      cellarg_char = zeros (1, numel (arg));
+      arg = num2cell (arg(:));
+
+    elseif (iscell (arg))
+
+      if (! all ((cellarg_num = cellfun ('isnumeric', arg))
+                           | (cellarg_char = cellfun ('ischar', arg))))
+        error ("tticklabels: TICKVAL cell must contain numbers or strings");
+      endif
+
+    else
+      error (["tticklabels: TICKVAL must be numeric or a cell ", ...
+              "containing numbers and strings"]);
+    endif
+
+  ## Finish converting TICVAL into a cellstr
+
+  ## Convert numeric elements to characters and make it a 1-D cell array.
+  arg(cellarg_num) = cellfun (@num2str, arg(cellarg_num), ...
+                                "UniformOutput", false);
+  arg = arg(:);
+  endif
+
+  if (isempty (hax))
+    hax = gca ();
+  endif
+
+  ## Error if the remaining input
+  polarhandle = findall (hax, "tag", "polar_grid");
+
+  ## Error if hax does not point to a polar plot with theta elements.
+  if (isempty (polarhandle))
+    error ("tticklabels: tticklabels can only be used on a polar plot");
+  elseif (! isfield (get (hax), "rtick") )
+    error ("tticklabels: ttick property not defined for current axes");
+  endif
+
+  ## Get theta curves count.
+  nt = numel (get (hax, "ttick"));
+
+  ## rtick and ttick object ordering
+  ##  1:nt = text handles containing theta labels (reverse order)
+  ##  nt+1:2*nt = line object handles for ttick radial grid lines
+  ##  2*nt+1:2*nt+nr = text handles containing nr rtick labels (reverse order)
+  ##  2*nt+nr+1:2*nt+2*nr = line object handles for rtick circles
+  ##  end = patch object handle for darker outside border
+
+  ## Get theta label handles, reverse order so output is in increasing.
+  tlabel_handles = get (polarhandle, "children")(nt:-1:1);
+
+  if (nargs == 0)
+    ## Just return theta labels.
+    labels = get (tlabel_handles, "string");
+
+  else
+    ## Set new label values.
+
+    if isempty (arg)
+      ## If an empty cell or array is set, set all labels to "".
+      arg = cell (nt, 1);
+      arg(:) = {""};
+
+    else
+      ## Pad and trim arg as needed to match number of labels.
+      if (nt < numel (arg))
+        arg (nt + 1 : end) = [];
+      else
+        arg(end + 1 : nt) = {""};
+      endif
+    endif
+
+    ## Replace labels with values from arg, ensure column vector.
+    set (tlabel_handles, {"string"}, arg(:));
+  endif
+
+endfunction
+
+%!test
+%! t = [0:15:180] * pi / 180;
+%! r = sin (t);
+%! hf = figure ("visible", "off");
+%! unwind_protect
+%!   hp = polar (t, r);
+%!   hax = gca ();
+%!   thetaticks (hax, [0:60:300]);
+%!   assert (tticklabels (hax), {"0"; "60"; "120"; "180"; "240"; "300"});
+%!   tticklabels (hax, [0:20:100]);
+%!   assert (tticklabels (hax), {"0"; "20"; "40"; "60"; "80"; "100"});
+%!   tticklabels (hax, [0:-20:-100]');
+%!   assert (tticklabels (hax), {"0"; "-20"; "-40"; "-60"; "-80"; "-100"});
+%!   tticklabels (hax, {1, 2, 3, 4, 5 ,6});
+%!   assert (tticklabels (hax), {"1"; "2"; "3"; "4"; "5"; "6"});
+%!   tticklabels (hax, {"a", "bee", "c", "d", "eeee", "f"});
+%!   assert (tticklabels (hax), {"a"; "bee"; "c"; "d"; "eeee"; "f"});
+%!   tticklabels (hax, {1, "two", 3, "4", 5, "six"}');
+%!   assert (tticklabels (hax), {"1"; "two"; "3"; "4"; "5"; "six"});
+%!   tticklabels (hax, {1, 2, 3, 4, 5 ,6, 7});
+%!   assert (tticklabels (hax), {"1"; "2"; "3"; "4"; "5"; "6"});
+%!   tticklabels (hax, [5, 6, 7, 8, 9, 10, 11]);
+%!   assert (tticklabels (hax), {"5"; "6"; "7"; "8"; "9"; "10"});
+%!   tticklabels (hax, {1});
+%!   assert (tticklabels (hax), {"1"; ""; ""; ""; ""; ""});
+%!   tticklabels (hax, {1, 2, 3, 4, 5 ,6});
+%!   assert (tticklabels (hax), {"1"; "2"; "3"; "4"; "5"; "6"});
+%!   tticklabels (hax, []);
+%!   assert (tticklabels (hax), {""; ""; ""; ""; ""; ""});
+%!   tticklabels (hax, {1, 2, 3, 4, 5 ,6});
+%!   assert (tticklabels (hax), {"1"; "2"; "3"; "4"; "5"; "6"});
+%!   tticklabels (hax, {});
+%!   assert (tticklabels (hax), {""; ""; ""; ""; ""; ""});
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
+
+
+## Test input validation
+%!test
+%! hf = figure ("visible", "off");
+%! unwind_protect
+%!   hax = gca ();
+%!   fail ("tticklabels (1,2,3)", "Invalid call");
+%!   fail ("tticklabels (-1, 2)", "Invalid call");
+%!   fail ("tticklabels (hax, 2, 3)", "Invalid call");
+%!   fail ("tticklabels (hf, 2)", "Invalid call");
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
+
+%!test
+%! hf = figure ("visible", "off");
+%! unwind_protect
+%!   hax = gca ();
+%!   fail ("tmp = tticklabels ([1, 2, 3])", "cannot set and return labels simultaneously");
+%!   fail ("tmp = tticklabels (hax, [1, 2, 3])", "cannot set and return labels simultaneously");
+%!   fail ("tticklabels (hax, {{1}, 'two', 3})", "TICKVAL cell must contain numbers or strings");
+%!   fail ("tticklabels (hax, {1, 'two', false})", "TICKVAL cell must contain numbers or strings");
+%!   fail ("tticklabels (hax, {1, struct()})", "TICKVAL cell must contain numbers or strings");
+%!   fail ("tticklabels (hax, struct())", "TICKVAL must be numeric or a cell containing");
+%!   fail ("tticklabels (hax, [true false])", "TICKVAL must be numeric or a cell containing");
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
+
+%!test
+%! t = [0:45:180] * pi / 180;
+%! r = sin (t);
+%! hf = figure ("visible", "off");
+%! unwind_protect
+%!   hp = plot (t, r);
+%!   hax = gca ();
+%!   fail ("tticklabels (hax, 1)", "tticklabels can only be used on a polar plot");
+%!   fail ("tticklabels ({1})", "tticklabels can only be used on a polar plot");
+%!   hp = polar (t, r);
+%!   hax = gca ();
+%!   delete (findall (hax, "tag", "polar_grid"));
+%!   fail ("tticklabels (hax, 1)", "tticklabels can only be used on a polar plot");
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
--- a/scripts/plot/draw/polar.m	Wed Dec 13 18:19:37 2023 -0500
+++ b/scripts/plot/draw/polar.m	Thu Dec 14 23:51:45 2023 -0500
@@ -333,9 +333,9 @@
   delete (get (hg, "children"));
 
   rtick = unique (get (hax, "rtick")(:)');
-  rtick = rtick(rtick >= 0);
+  rtick = rtick(rtick > 0);
   if (isempty (rtick))
-    rtick = [0, 0.5, 1];
+    rtick = [0.5, 1];
   endif
 
   ttick = unique (get (hax, "ttick")(:)');