1########################################################################
2##
3## Copyright (C) 2007-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  {} {} fill (@var{x}, @var{y}, @var{c})
28## @deftypefnx {} {} fill (@var{x1}, @var{y1}, @var{c1}, @var{x2}, @var{y2}, @var{c2})
29## @deftypefnx {} {} fill (@dots{}, @var{prop}, @var{val})
30## @deftypefnx {} {} fill (@var{hax}, @dots{})
31## @deftypefnx {} {@var{h} =} fill (@dots{})
32## Create one or more filled 2-D polygons.
33##
34## The inputs @var{x} and @var{y} are the coordinates of the polygon vertices.
35## If the inputs are matrices then the rows represent different vertices and
36## each column produces a different polygon.  @code{fill} will close any open
37## polygons before plotting.
38##
39## The input @var{c} determines the color of the polygon.  The simplest form
40## is a single color specification such as a @code{plot} format or an
41## RGB-triple.  In this case the polygon(s) will have one unique color.  If
42## @var{c} is a vector or matrix then the color data is first scaled using
43## @code{caxis} and then indexed into the current colormap.  A row vector will
44## color each polygon (a column from matrices @var{x} and @var{y}) with a
45## single computed color.  A matrix @var{c} of the same size as @var{x} and
46## @var{y} will compute the color of each vertex and then interpolate the face
47## color between the vertices.
48##
49## Multiple property/value pairs for the underlying patch object may be
50## specified, but they must appear in pairs.  The full list of properties is
51## documented at @ref{Patch Properties}.
52##
53## If the first argument @var{hax} is an axes handle, then plot into this axes,
54## rather than the current axes returned by @code{gca}.
55##
56## The optional return value @var{h} is a vector of graphics handles to
57## the created patch objects.
58##
59## Example: red square
60##
61## @example
62## @group
63## vertices = [0 0
64##             1 0
65##             1 1
66##             0 1];
67## fill (vertices(:,1), vertices(:,2), "r");
68## axis ([-0.5 1.5, -0.5 1.5])
69## axis equal
70## @end group
71## @end example
72##
73## @seealso{patch, caxis, colormap}
74## @end deftypefn
75
76function h = fill (varargin)
77
78  [hax, varargin] = __plt_get_axis_arg__ ("fill", varargin{:});
79
80  hlist = [];
81  iargs = __find_patches__ (varargin{:});
82
83  opts = {};
84  if (numel (varargin) > iargs(end) + 2)
85    opts = varargin(iargs(end)+3 : end);
86  endif
87
88  if (! all (cellfun (@(x) iscolorspec (x), varargin(iargs + 2))))
89    print_usage ();
90  endif
91
92  oldfig = [];
93  if (! isempty (hax))
94    oldfig = get (0, "currentfigure");
95  endif
96  unwind_protect
97    hax = newplot (hax);
98    old_nxtplt = get (hax, "nextplot");
99    if (! ishold ())
100      set (hax, "box", "on");
101    endif
102    unwind_protect
103      set (hax, "nextplot", "add");
104
105      for i = 1 : length (iargs)
106        x = varargin{iargs(i)};
107        y = varargin{iargs(i) + 1};
108        cdata = varargin{iargs(i) + 2};
109
110        if (! size_equal (x,y))
111          if (iscolumn (y) && rows (y) == rows (x))
112            y = repmat (y, [1, columns(x)]);
113          elseif (iscolumn (x) && rows (x) == rows (y))
114            x = repmat (x, [1, columns(y)]);
115          else
116            error ("fill: X annd Y must have same number of rows");
117          endif
118        endif
119
120        if (isrow (x))
121          x = x(:);
122        endif
123        if (isrow (y))
124          y = y(:);
125        endif
126
127        if (ischar (cdata) || isequal (size (cdata), [1, 3]))
128          one_color = true;
129        else
130          one_color = false;
131        endif
132
133        ## For Matlab compatibility, replicate cdata to match size of data
134        if (! one_color && iscolumn (cdata))
135          sz = size (x);
136          if (all (sz > 1))
137            cdata = repmat (cdata, [1, sz(2)]);
138          endif
139        endif
140
141        ## For Matlab compatibility, return 1 patch object for each column
142        for j = 1 : columns (x)
143          if (one_color)
144            [htmp, err] = __patch__ (hax, x(:,j), y(:,j), cdata, opts{:});
145          else
146            [htmp, err] = __patch__ (hax, x(:,j), y(:,j), cdata(:,j), opts{:});
147          endif
148          if (err)
149            print_usage ();
150          endif
151          hlist(end+1, 1) = htmp;
152        endfor
153
154      endfor
155
156    unwind_protect_cleanup
157      if (strcmp (old_nxtplt, "replace"))
158        set (hax, "nextplot", old_nxtplt);
159      endif
160    end_unwind_protect
161
162  unwind_protect_cleanup
163    if (! isempty (oldfig))
164      set (0, "currentfigure", oldfig);
165    endif
166  end_unwind_protect
167
168  if (nargout > 0)
169    h = hlist;
170  endif
171
172endfunction
173
174function iargs = __find_patches__ (varargin)
175  iargs = 1:3:nargin;
176  optidx = find (! cellfun (@isnumeric, varargin(iargs)), 1);
177  iargs(optidx:end) = [];
178endfunction
179
180function retval = iscolorspec (arg)
181
182  retval = false;
183  if (ischar (arg))
184    persistent colors = {"y", "yellow", "r", "red", "m", "magenta", ...
185                         "c", "cyan", "g", "green", "b", "blue", ...
186                         "w", "white", "k", "black"};
187    if (any (strcmpi (arg, colors)))
188      retval = true;
189    endif
190  elseif (isnumeric (arg))
191    ## Assume any numeric argument is correctly formatted cdata.
192    ## Let patch worry about the multiple different input formats.
193    retval = true;
194  endif
195
196endfunction
197
198
199%!demo
200%! clf;
201%! t1 = (1/16:1/8:1) * 2*pi;
202%! t2 = ((1/16:1/8:1) + 1/32) * 2*pi;
203%! x1 = sin (t1) - 0.8;
204%! y1 = cos (t1);
205%! x2 = sin (t2) + 0.8;
206%! y2 = cos (t2);
207%! h = fill (x1,y1,"r", x2,y2,"g");
208%! title ({"fill() function"; "cdata specified with string"});
209
210%!demo
211%! clf;
212%! t1 = (1/16:1/8:1) * 2*pi;
213%! t2 = ((1/16:1/8:1) + 1/32) * 2*pi;
214%! x1 = sin (t1) - 0.8;
215%! y1 = cos (t1);
216%! x2 = sin (t2) + 0.8;
217%! y2 = cos (t2);
218%! h = fill (x1,y1,1, x2,y2,2);
219%! title ({"fill() function"; 'cdata = row vector produces FaceColor = "flat"'});
220
221%!demo
222%! clf;
223%! x = [0 0
224%!      1 0.5
225%!      1 0.5
226%!      0 0];
227%! y = [0 0
228%!      0 0
229%!      1 0.5
230%!      1 0.5];
231%! c = [1 2 3 4]';
232%! fill (x, y, [c c]);
233%! title ({"fill() function"; 'cdata = column vector produces FaceColor = "interp"'});
234