1########################################################################
2##
3## Copyright (C) 2008-2021 The Octave Project Developers
4##
5## See the file COPYRIGHT.md in the top-level directory of this
6## distribution or <https://octave.org/copyright/>.
7##
8## This file is part of Octave.
9##
10## Octave is free software: you can redistribute it and/or modify it
11## under the terms of the GNU General Public License as published by
12## the Free Software Foundation, either version 3 of the License, or
13## (at your option) any later version.
14##
15## Octave is distributed in the hope that it will be useful, but
16## WITHOUT ANY WARRANTY; without even the implied warranty of
17## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18## GNU General Public License for more details.
19##
20## You should have received a copy of the GNU General Public License
21## along with Octave; see the file COPYING.  If not, see
22## <https://www.gnu.org/licenses/>.
23##
24########################################################################
25
26## -*- texinfo -*-
27## @deftypefn  {} {} clabel (@var{c}, @var{h})
28## @deftypefnx {} {} clabel (@var{c}, @var{h}, @var{v})
29## @deftypefnx {} {} clabel (@var{c}, @var{h}, "manual")
30## @deftypefnx {} {} clabel (@var{c})
31## @deftypefnx {} {} clabel (@dots{}, @var{prop}, @var{val}, @dots{})
32## @deftypefnx {} {@var{h} =} clabel (@dots{})
33## Add labels to the contours of a contour plot.
34##
35## The contour levels are specified by the contour matrix @var{c} which is
36## returned by @code{contour}, @code{contourc}, @code{contourf}, and
37## @code{contour3}.  Contour labels are rotated to match the local line
38## orientation and centered on the line.  The position of labels along the
39## contour line is chosen randomly.
40##
41## If the argument @var{h} is a handle to a contour group object, then label
42## this plot rather than the one in the current axes returned by @code{gca}.
43##
44## By default, all contours are labeled.  However, the contours to label can be
45## specified by the vector @var{v}.  If the @qcode{"manual"} argument is
46## given then the contours to label can be selected with the mouse.
47##
48## Additional property/value pairs that are valid properties of text objects
49## can be given and are passed to the underlying text objects.  Moreover,
50## the contour group property @qcode{"LabelSpacing"} is available which
51## determines the spacing between labels on a contour to be specified.  The
52## default is 144 points, or 2 inches.
53##
54## The optional return value @var{h} is a vector of graphics handles to
55## the text objects representing each label.
56## The @qcode{"userdata"} property of the text objects contains the numerical
57## value of the contour label.
58##
59## The full list of text object properties is documented at
60## @ref{Text Properties}.
61##
62## @example
63## @group
64## [c, h] = contour (peaks (), -4 : 6);
65## clabel (c, h, -4:2:6, "fontsize", 12);
66## @end group
67## @end example
68##
69## @seealso{contour, contourf, contour3, meshc, surfc, text}
70## @end deftypefn
71
72function h = clabel (c, varargin)
73
74  have_hg = false;
75  have_labelspacing = false;
76  label_spacing = 144;  # 2 inches in points
77
78  if (nargin < 1)
79    print_usage ();
80  elseif (nargin == 1)
81    hparent = gca ();
82  else
83    arg = varargin{1};
84    if (isscalar (arg) && isgraphics (arg, "hggroup"))
85      try
86        get (arg, "contourmatrix");
87      catch
88        error ("clabel: H must be a handle to a contour group");
89      end_try_catch
90      have_hg = true;
91      hg = arg;
92      varargin(1) = [];
93    else
94      hparent = gca ();
95    endif
96  endif
97
98  if (length (varargin) > 0 && isnumeric (varargin{1}))
99    v = varargin{1}(:);
100    varargin(1) = [];
101  else
102    v = [];
103  endif
104
105  idx = strcmpi (varargin(1:2:end), "manual");
106  if (any (idx))
107    error ('clabel: "manual" contour mode is not supported');
108  endif
109
110  idx = find (strcmpi (varargin(1:2:end), "labelspacing"), 1);
111  if (! isempty (idx))
112    have_labelspacing = true;
113    label_spacing = varargin{2*idx};
114    varargin(2*idx+(-1:0)) = [];
115  endif
116
117  if (have_hg)
118    if (! isempty (v))
119      if (have_labelspacing)
120        set (hg, "textlistmode", "manual", "textlist", v,
121                 "labelspacing", label_spacing, "showtext", "on");
122      else
123        set (hg, "textlistmode", "manual", "textlist", v, "showtext", "on");
124      endif
125    else
126      if (have_labelspacing)
127        set (hg, "showtext", "on", "labelspacing", label_spacing);
128      else
129        set (hg, "showtext", "on");
130      endif
131    endif
132    htmp = findobj (hg, "type", "text");
133    if (! isempty (varargin))
134      set (htmp, varargin{:});
135    endif
136  else
137    htmp = __clabel__ (c, v, hparent, label_spacing, [], varargin{:});
138  endif
139
140  if (nargout > 0)
141    h = htmp;
142  endif
143
144endfunction
145
146
147%!demo
148%! clf;
149%! colormap ("default");
150%! [c, h] = contour (peaks (), -4:6);
151%! clabel (c, h, -4:2:6, "fontsize", 12);
152%! title ("clabel() labeling every other contour");
153
154%!demo
155%! clf;
156%! colormap ("default");
157%! [c, h] = contourf (peaks (), -7:6);
158%! clabel (c, h, -6:2:6, "fontsize", 12);
159%! title ("clabel() labeling every other contour");
160