]> Creatis software - CreaPhase.git/blob - octave_packages/m/plot/private/__patch__.m
update packages
[CreaPhase.git] / octave_packages / m / plot / private / __patch__.m
1 ## Copyright (C) 2007-2012 John W. Eaton, Shai Ayal, Kai Habel
2 ##
3 ## This file is part of Octave.
4 ##
5 ## Octave is free software; you can redistribute it and/or modify it
6 ## under the terms of the GNU General Public License as published by
7 ## the Free Software Foundation; either version 3 of the License, or (at
8 ## your option) any later version.
9 ##
10 ## Octave is distributed in the hope that it will be useful, but
11 ## WITHOUT ANY WARRANTY; without even the implied warranty of
12 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 ## General Public License for more details.
14 ##
15 ## You should have received a copy of the GNU General Public License
16 ## along with Octave; see the file COPYING.  If not, see
17 ## <http://www.gnu.org/licenses/>.
18
19 ## -*- texinfo -*-
20 ## @deftypefn {Function File} {[@var{h}, @var{fail}] =} __patch__ (@var{p}, @dots{})
21 ## Undocumented internal function.
22 ## @end deftypefn
23
24 ## __patch__ (p, x, y, c)
25 ## Create patch object from x and y with color c and parent p.
26 ## Return handle to patch object.
27
28 ## Author: Kai Habel
29
30 function [h, failed] = __patch__ (p, varargin)
31
32   h = NaN;
33   failed = false;
34
35   is_numeric_arg = cellfun (@isnumeric, varargin);
36
37   if (isempty (varargin))
38     args = {"xdata", [0; 1; 0], "ydata", [1; 1; 0], "facecolor", [0, 0, 0]};
39     args = setvertexdata (args);
40   elseif (isstruct (varargin{1}))
41     if (isfield (varargin{1}, "vertices") && isfield (varargin{1}, "faces"))
42       args{1} = "faces";
43       args{2} = getfield(varargin{1}, "faces");
44       args{3} = "vertices";
45       args{4} = getfield(varargin{1}, "vertices");
46       args{5} = "facevertexcdata";
47       if (isfield (varargin{1}, "facevertexcdata"))
48         args{6} = getfield(varargin{1}, "facevertexcdata");
49       else
50         args{6} = [];
51       endif
52       args = [args; varargin(2:end)];
53       args = setdata (args);
54     else
55       failed = true;
56     endif
57   elseif (is_numeric_arg(1))
58     if (nargin < 3 || ! is_numeric_arg(2))
59       failed = true;
60     else
61
62       if (nargin > 4 && all (is_numeric_arg(1:4)))
63         x = varargin{1};
64         y = varargin{2};
65         z = varargin{3};
66         c = varargin{4};
67         iarg = 5;
68       elseif (nargin > 3 && all (is_numeric_arg(1:3)))
69         x = varargin{1};
70         y = varargin{2};
71         iarg = 4;
72         if (rem (nargin - iarg, 2) == 1)
73           c = varargin {iarg};
74           z = varargin{3};
75           iarg = 5;
76         else
77           z = [];
78           c = varargin{3};
79         endif
80       elseif (nargin > 2 && all (is_numeric_arg(1:2)))
81         x = varargin{1};
82         y = varargin{2};
83         z = [];
84         iarg = 3;
85         if (rem (nargin - iarg, 2) == 1)
86           c = varargin {iarg};
87           iarg++; 
88         else
89           c = [];
90         endif
91       endif
92
93       if (isvector (x))
94         x = x(:);
95         y = y(:);
96         z = z(:);
97         if (isnumeric (c))
98           if (isvector (c) && numel (c) == numel (x))
99             c = c(:);
100           elseif (size (c, 1) != numel (x) && size (c, 2) == numel (x))
101             c = c.';
102           endif
103         endif
104       endif
105       args{1} = "xdata";
106       args{2} = x;
107       args{3} = "ydata";
108       args{4} = y;
109       args{5} = "zdata";
110       args{6} = z;
111
112       if (isnumeric (c))
113
114         if (ndims (c) == 3 && size (c, 2) == 1)
115           c = permute (c, [1, 3, 2]);
116         endif
117
118         if (isvector (c) && numel (c) == columns (x))
119           if (isnan (c))
120             args{7} = "facecolor";
121             args{8} = [1, 1, 1];
122             args{9} = "cdata";
123             args{10} = c;
124           elseif (isnumeric (c))
125             args{7} = "facecolor";
126             args{8} = "flat";
127             args{9} = "cdata";
128             args{10} = c;
129           else
130             error ("patch: color value not valid");
131           endif
132         elseif (isvector (c) && numel (c) == 3)
133           args{7} = "facecolor";
134           args{8} = c;
135           args{9} = "cdata";
136           args{10} = [];
137         elseif (ndims (c) == 3 && size (c, 3) == 3)
138           ## CDATA is specified as RGB data
139           if ((size (c, 1) == 1 && size (c, 2) == 1) ...
140               || (size (c, 1) == 1 && size (c, 2) == columns (x)))
141             ## Single patch color or per-face color
142             args{7} = "facecolor";
143             args{8} = "flat";
144             args{9} = "cdata";
145             args{10} = c;
146           elseif (size (c, 1) == rows (x) && size (c, 2) == columns (x))
147             ## Per-vertex color
148             args{7} = "facecolor";
149             args{8} = "interp";
150             args{9} = "cdata";
151             agrs{10} = c;
152           else
153             error ("patch: color value not valid");
154           endif
155         else
156           ## Color Vectors
157           if (isempty (c))
158             args{7} = "facecolor";
159             args{8} = "interp";
160             args{9} = "cdata";
161             args{10} = [];
162           elseif (isequal (size (c), size (x)) && isequal (size (c), size (y)))
163             args{7} = "facecolor";
164             args{8} = "interp";
165             args{9} = "cdata";
166             args{10} = c;
167           else
168             error ("patch: size of x, y, and c must be equal");
169           endif
170         endif
171       elseif (ischar (c) && rem (nargin - iarg, 2) == 0)
172         ## Assume that any additional argument over an even number is
173         ## color string.
174         args{7} = "facecolor";
175         args{8} =  tolower (c);
176         args{9} = "cdata";
177         args{10} = [];
178       else
179         args{7} = "facecolor";
180         args{8} = [0, 1, 0];
181         args{9} = "cdata";
182         args{10} = [];
183       endif
184
185       args = [args, varargin(iarg:end)];
186       args = setvertexdata (args);
187     endif
188   else
189     args = varargin;
190     if (any (strcmpi (args, "faces") | strcmpi (args, "vertices")))
191       args = setdata (args);
192     else
193       args = setvertexdata (args);
194     endif
195   endif
196
197   if (!failed)
198     h = __go_patch__ (p, args {:});
199
200     ## Setup listener functions
201     addlistener (h, "xdata", @update_data);
202     addlistener (h, "ydata", @update_data);
203     addlistener (h, "zdata", @update_data);
204     addlistener (h, "cdata", @update_data);
205
206     addlistener (h, "faces", @update_fvc);
207     addlistener (h, "vertices", @update_fvc);
208     addlistener (h, "facevertexcdata", @update_fvc);
209   endif
210 endfunction
211
212 function args = delfields(args, flds)
213   idx = cellfun (@(x) any (strcmpi (x, flds)), args);
214   if (rows (idx) == 1)
215     idx = idx | [false, idx(1:end-1)];
216   else
217     idx = idx | [false; idx(1:end-1)];
218   endif
219   args (idx) = [];
220 endfunction
221
222 function args = setdata (args)
223   args = delfields (args, {"xdata", "ydata", "zdata", "cdata"});
224   ## Remove the readonly fields as well
225   args = delfields (args, {"type", "uicontextmenu"});
226   nargs = length (args);
227   idx = find (strcmpi (args, "faces"), 1, "last") + 1;
228   if (idx > nargs)
229     faces = [];
230   else
231     faces = args {idx};
232   endif
233   idx = find (strcmpi (args, "vertices"), 1, "last") + 1;
234   if (idx > nargs)
235     vert = [];
236   else
237     vert = args {idx};
238   endif
239   idx = find (strcmpi (args, "facevertexcdata"), 1, "last") + 1;
240   if (isempty(idx) || idx > nargs)
241     fvc = [];
242   else
243     fvc = args {idx};
244   endif
245   idx = find (strcmpi (args, "facecolor"), 1, "last") + 1;
246   if (isempty(idx) || idx > nargs)
247     if (!isempty (fvc))
248       fc = "flat";
249     else
250       fc = [0, 1, 0];
251     endif
252     args = {"facecolor", fc, args{:}};
253   endif
254
255   nc = size (faces, 1);
256   idx = faces .';
257   t1 = isnan (idx);
258   for i = find (any (t1))
259     first_idx_in_column = find (t1(:,i), 1);
260     idx(first_idx_in_column:end,i) = idx(first_idx_in_column-1,i);
261   endfor
262   x = reshape (vert(:,1)(idx), size (idx));
263   y = reshape (vert(:,2)(idx), size (idx));
264   if (size(vert,2) > 2)
265     z = reshape (vert(:,3)(idx), size (idx));
266   else
267     z = [];
268   endif
269
270   if (size(fvc, 1) == nc || size (fvc, 1) == 1)
271     c = reshape (fvc, [1, size(fvc)]);
272   else
273     if (size(fvc, 2) == 3)
274       c = cat(3, reshape (fvc(idx, 1), size(idx)),
275               reshape (fvc(idx, 2), size(idx)),
276               reshape (fvc(idx, 3), size(idx)));
277     elseif (isempty (fvc))
278       c = [];
279     else ## if (size (fvc, 2) == 1)
280       c = permute (fvc(faces), [2, 1]);
281     endif
282   endif
283   args = {"xdata", x, "ydata", y, "zdata", z, "cdata", c, args{:}};
284 endfunction
285
286 function args = setvertexdata (args)
287   args = delfields (args, {"vertices", "faces", "facevertexcdata"});
288   ## Remove the readonly fields as well
289   args = delfields (args, {"type", "uicontextmenu"});
290   nargs = length (args);
291   idx = find (strcmpi (args, "xdata"), 1, "last") + 1;
292   if (idx > nargs)
293     x = [];
294   else
295     x = args {idx};
296   endif
297   idx = find (strcmpi (args, "ydata"), 1, "last") + 1;
298   if (idx > nargs)
299     y = [];
300   else
301     y = args {idx};
302   endif
303   idx = find (strcmpi (args, "zdata"), 1, "last") + 1;
304   if (isempty(idx) || idx > nargs)
305     z = [];
306   else
307     z = args {idx};
308   endif
309   idx = find (strcmpi (args, "cdata"), 1, "last") + 1;
310   if (isempty(idx) || idx > nargs)
311     c = [];
312   else
313     c = args {idx};
314   endif
315   idx = find (strcmpi (args, "facecolor"), 1, "last") + 1;
316   if (isempty(idx) || idx > nargs)
317     if (!isempty (c))
318       fc = "flat";
319     else
320       fc = [0, 1, 0];
321     endif
322     args = {"facecolor", fc, args{:}};
323   endif
324
325   [nr, nc] = size (x);
326   if (nr == 1 && nc > 1)
327     nr = nc;
328     nc = 1;
329   end
330   if (!isempty (z))
331     vert = [x(:), y(:), z(:)];
332   else
333     vert = [x(:), y(:)];
334   endif
335   faces = reshape (1:numel(x), nr, nc);
336   faces = faces';
337
338   if (ndims (c) == 3)
339     fvc = reshape (c, size (c, 1) * size (c, 2), size(c, 3));
340   else
341     fvc = c(:);
342   endif
343
344   args = {"faces", faces, "vertices", vert, "facevertexcdata", fvc, args{:}};
345 endfunction
346
347 function update_data (h, d)
348   update_handle (h, false);
349 endfunction
350
351 function update_fvc (h, d)
352   update_handle (h, true);
353 endfunction
354
355 function update_handle (h, isfv)
356   persistent recursive = false;
357
358   if (! recursive)
359     recursive = true;
360     f = get (h);
361     if (isfv)
362       set (h, setdata ([fieldnames(f), struct2cell(f)].'(:)){:});
363     else
364       set (h, setvertexdata ([fieldnames(f), struct2cell(f)].'(:)){:});
365     endif
366     recursive = false;
367   endif
368 endfunction