]> Creatis software - CreaPhase.git/blob - octave_packages/m/plot/private/__ezplot__.m
update packages
[CreaPhase.git] / octave_packages / m / plot / private / __ezplot__.m
1 ## Copyright (C) 2007-2012 David Bateman
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{needusage}] =} __ezplot__ (@var{pfunc}, @var{varargin})
21 ## Undocumented internal function.
22 ## @end deftypefn
23
24 function [h, needusage] = __ezplot__ (pfunc, varargin)
25
26   func = cstrcat ("ez", pfunc);
27   if (strncmp (pfunc, "contour", 7))
28     iscontour = true;
29   else
30     iscontour = false;
31   endif
32   if (strcmp (pfunc, "plot"))
33     isplot = true;
34     isplot3 = false;
35     ispolar = false;
36     nargs = 1;
37   elseif (strcmp (pfunc, "plot3"))
38     isplot = false;
39     isplot3 = true;
40     ispolar = false;
41     nargs = 1;
42   elseif (strcmp (pfunc, "polar"))
43     isplot = false;
44     isplot3 = false;
45     ispolar = true;
46     nargs = 1;
47   else
48     isplot = false;
49     isplot3 = false;
50     ispolar = false;
51     nargs = 2;
52   endif
53
54   [ax, varargin, nargin] = __plt_get_axis_arg__ (func, varargin{:});
55
56   needusage = false;
57   if (nargin < 1)
58     needusage = true;
59     return;
60   endif
61
62   parametric = false;
63   fun = varargin {1};
64   if (ischar (fun))
65     if (exist (fun, "file") || exist (fun, "builtin"))
66       fun = vectorize (inline (cstrcat (fun, "(t)")));
67     else
68       fun = vectorize (inline (fun));
69     endif
70     if (isplot && length (argnames (fun)) == 2)
71       nargs = 2;
72     elseif (length (argnames (fun)) != nargs)
73       error ("%s: excepting a function of %d arguments", func, nargs);
74     endif
75     fstr = formula (fun);
76     if (isplot)
77       xarg = argnames(fun){1};
78       if (nargs == 2)
79         yarg = argnames(fun){2};
80       else
81         yarg = "";
82       endif
83     elseif (isplot3)
84       xarg = "x";
85       yarg = "y";
86     elseif (ispolar)
87       xarg = "";
88       yarg = "";
89     else
90       xarg = argnames(fun){1};
91       yarg = argnames(fun){2};
92     endif
93   elseif (strcmp (typeinfo (fun), "inline function"))
94     if (isplot && length (argnames (fun)) == 2)
95       nargs = 2;
96     elseif (length (argnames (fun)) != nargs)
97       error ("%s: excepting a function of %d arguments", func, nargs);
98     endif
99     fun = vectorize (fun);
100     fstr = formula (fun);
101     if (isplot)
102       xarg = argnames(fun){1};
103       if (nargs == 2)
104         yarg = argnames(fun){2};
105       else
106         yarg = "";
107       endif
108     elseif (isplot3)
109       xarg = "x";
110       yarg = "y";
111     elseif (isplot || ispolar)
112       xarg = "";
113       yarg = "";
114     else
115       xarg = argnames(fun)(1);
116       yarg = argnames(fun)(2);
117     endif
118   elseif (isa (fun, "function_handle"))
119     fstr = func2str (fun);
120     if (length (findstr (fstr, ")")) != 0)
121       args = regexp (substr (fstr, 3, findstr (fstr, ")")(1) - 3),
122                      '(\w+)', 'tokens');
123     fstr = substr (fstr, findstr (fstr, ")")(1) + 1);
124     else
125       args = {{"x"}};
126     endif
127     if (isplot && length (args) == 2)
128       nargs = 2;
129     elseif (length (args) != nargs)
130       error ("%s: excepting a function of %d arguments", func, nargs);
131     endif
132     if (isplot)
133       xarg = args{1}{1};
134       if (nargs == 2)
135         yarg = args{2}{1};
136       else
137         yarg = "";
138       endif
139     elseif (isplot3)
140       xarg = "x";
141       yarg = "y";
142     elseif (ispolar)
143       xarg = "";
144       yarg = "";
145     else
146       xarg = args{1}{1};
147       yarg = args{2}{1};
148     endif
149   else
150     error ("%s: expecting string, inline function or function handle", func);
151   endif
152
153   if (nargin > 2 || (nargin == 2 && isplot))
154     funx = fun;
155     fstrx = fstr;
156     funy = varargin {2};
157     if (ischar (funy) && ! strcmp (funy, "circ") && ! strcmp (funy, "animate"))
158       parametric = true;
159       if (exist (funy, "file") || exist (funy, "builtin"))
160         funy = vectorize (inline (cstrcat (funy, "(t)")));
161       else
162         funy = vectorize (inline (funy));
163       endif
164       if (length (argnames (funy)) != nargs)
165         error ("%s: excepting a function of %d arguments", func, nargs);
166       endif
167       fstry = formula (funy);
168     elseif (strcmp (typeinfo (funy), "inline function"))
169       parametric = true;
170       if (length (argnames (funy)) != nargs)
171         error ("%s: excepting a function of %d arguments", func, nargs);
172       endif
173       funy = vectorize (funy);
174       fstry = formula (funy);
175     elseif (isa (funy, "function_handle"))
176       parametric = true;
177       fstry = func2str (funy);
178       if (length (findstr (fstry, ")")) != 0)
179         args = regexp (substr (fstry, 3, findstr (fstry, ")")(1) - 3),
180                        '(\w+)', 'tokens');
181         fstry = substr (fstry, findstr (fstry, ")")(1) + 1);
182       else
183         args = {{"y"}};
184       endif
185       if (length (args) != nargs)
186         error ("%s: excepting a function of %d arguments", func, nargs);
187       endif
188     endif
189
190     if (parametric && isplot)
191       xarg = "x";
192       yarg = "y";
193       if (nargs == 2)
194         error ("%s: can not define a parametric function in this manner");
195       endif
196     endif
197
198     if (!isplot && parametric)
199       funz = varargin {3};
200       if (ischar (funz) && ! strcmp (funz, "circ")
201           && ! strcmp (funz, "animate"))
202         if (exist (funz, "file") || exist (funz, "builtin"))
203           funz = vectorize (inline (cstrcat (funz, "(t)")));
204         else
205           funz = vectorize (inline (funz));
206         endif
207         if (length (argnames (funz)) != nargs)
208           error ("%s: excepting a function of %d arguments", func, nargs);
209         endif
210         fstrz = formula (funz);
211       elseif (strcmp (typeinfo (funz), "inline function"))
212         if (length (argnames (funz)) != nargs)
213           error ("%s: excepting a function of %d arguments", func, nargs);
214         endif
215         funz = vectorize (funz);
216         fstrz = formula (funz);
217       elseif (isa (funz, "function_handle"))
218         fstrz = func2str (funz);
219         args = regexp (substr (fstrz, 3, findstr (fstrz, ")")(1) - 3),
220                        '(\w+)', 'tokens');
221         if (length (args) != nargs)
222           error ("%s: excepting a function of %d arguments", func, nargs);
223         endif
224         fstrz = substr (fstrz, findstr (fstrz, ")")(1) + 1);
225       else
226         error ("%s: parametric plots expect 3 functions", func);
227       endif
228     endif
229   endif
230
231   if (isplot && nargs != 2)
232     n = 500;
233   else
234     n = 60;
235   endif
236   domain = [];
237   circ = false;
238   animate = false;
239   if (parametric)
240     if (isplot)
241       iarg = 3;
242     else
243       iarg = 4;
244     endif
245   else
246     iarg = 2;
247   endif
248   while (iarg <= nargin)
249     arg = varargin{iarg++};
250     if (ischar (arg) && strcmp (arg, "circ"))
251       circ = true;
252     elseif (ischar (arg) && strcmp (arg, "animate"))
253       animate = true;
254     elseif (isscalar (arg))
255       n = arg;
256     elseif (numel (arg) == 2)
257       domain = [arg(:).' arg(:).'];
258     elseif (numel (arg) == 4)
259       domain = arg(:).';
260     else
261       error ("%s: expecting scalar, 2 or 4 element vector", func);
262     endif
263   endwhile
264
265   if (isempty (domain))
266     if (isplot3 || ispolar)
267       domain = [0, 2*pi, 0, 2*pi];
268     else
269       domain = [-2*pi, 2*pi, -2*pi, 2*pi];
270     endif
271   endif
272
273   if (circ)
274     if (iscontour || isplot3 || isplot)
275       needusage = true;
276       return;
277     endif
278     if (parametric)
279       error ("%s: can not have both circular domain and parametric function",
280              func);
281     endif
282     cent = [domain(1) + domain(2), domain(3) + domain(4)] / 2;
283     funx = @(r,t) r .* cos (t) + cent (1);
284     funy = @(r,t) r .* sin (t) + cent (2);
285     domain = [0, sqrt((domain(2) - cent(1))^2 + (domain(4) - cent(2))^2), ...
286               -pi, pi];
287     funz = fun;
288     parametric = true;
289   endif
290
291   if (animate)
292     if (!isplot3)
293       error ("%s: animated graphs only valid with plot3", func);
294     endif
295     error ("%s: animated graphs not implemented", func);
296   endif
297
298   if (isplot3 || ispolar || (isplot && nargs == 1))
299     X = linspace (domain (1), domain (2), n);
300   elseif (isplot && numel (domain) == 2)
301     x = linspace (domain (1), domain (2), n);
302     [X, Y] = meshgrid (x, x);
303   else
304     x = linspace (domain (1), domain (2), n);
305     y = linspace (domain (3), domain (4), n);
306     [X, Y] = meshgrid (x, y);
307   endif
308
309   if (parametric)
310     if (isplot)
311       XX = feval (funx, X);
312       Z = feval (funy, X);
313       X = XX;
314     elseif (isplot3)
315       Z = feval (funz, X);
316       XX = feval (funx, X);
317       YY = feval (funy, X);
318       X = XX;
319       Y = YY;
320     else
321       Z = feval (funz, X, Y);
322       XX = feval (funx, X, Y);
323       YY = feval (funy, X, Y);
324       X = XX;
325       Y = YY;
326
327       ## Eliminate the singularities
328       X = __eliminate_sing__ (X);
329       Y = __eliminate_sing__ (Y);
330       Z = __eliminate_sing__ (Z);
331     endif
332
333     fstrx = regexprep (regexprep (regexprep (fstrx,'\s*\.?\^\s*','^'),
334                       '\./', '/'), '\.?\*', '');
335     fstry = regexprep (regexprep (regexprep (fstry,'\s*\.?\^\s*','^'),
336                       '\./', '/'), '\.?\*', '');
337     if (isplot)
338       fstr = cstrcat ("x = ",fstrx,", y = ",fstry);
339     else
340       fstrz = regexprep (regexprep (regexprep (fstrz,'\s*\.?\^\s*','^'),
341                                     '\./', '/'), '\.?\*', '');
342       fstr = cstrcat ("x = ",fstrx,",y = ",fstry,", z = ",fstrz);
343     endif
344   else
345     if (isplot3)
346       needusage = true;
347       return;
348     endif
349
350     fstr = regexprep (regexprep (regexprep (fstr,'\s*\.?\^\s*','^'), '\./', '/'),
351                       '\.?\*', '');
352     if (isplot && nargs == 2)
353       if (strcmp (typeinfo (fun), "inline function")
354           && !isempty (strfind (formula (fun) , "=")))
355         fun = inline (cstrcat (strrep (formula (fun), "=", "- ("), ")"));
356       else
357         fstr = cstrcat (fstr, " = 0");
358       endif
359
360       Z = feval (fun, X, Y);
361
362       ## Matlab returns line objects for this case and so can't call
363       ## contour directly as it returns patch objects to allow colormaps
364       ## to work with contours. Therefore recreate the lines from the
365       ## output for contourc, and store in cell arrays.
366       [c, lev] = contourc (X, Y, Z, [0, 0]);
367
368       i1 = 1;
369       XX = {};
370       YY = {};
371       while (i1 < length (c))
372         clev = c(1,i1);
373         clen = c(2,i1);
374         XX = [XX, {c(1, i1+1:i1+clen)}];
375         YY = [YY, {c(2, i1+1:i1+clen)}];
376         i1 += clen+1;
377       endwhile
378     else
379       if (ispolar)
380         Z = feval (fun, X);
381       elseif (isplot)
382         Z = real (feval (fun, X));
383
384         ## Eliminate the singularities. This seems to be what matlab
385         ## does, but can't be sure.
386         XX = sort (Z (isfinite (Z)));
387         if (length (X) > 4)
388           d = XX(fix (7 * length (XX) / 8)) - XX(fix (length (XX) / 8));
389           yrange = [max(XX(1) - d/8, XX(fix (length (XX) / 8)) - d), ...
390                     min(XX(end) + d/8, XX(fix (7 * length (XX) / 8)) + d)];
391         else
392           yrange = [XX(1), XX(end)];
393         endif
394
395         idx = 2 : length(Z);
396         idx = find (((Z(idx) > yrange(2) / 2) & (Z(idx-1) < yrange(1) / 2)) |
397                  ((Z(idx) < yrange(1) / 2) & (Z(idx-1) > yrange (2) / 2)));
398         if (any(idx))
399           Z(idx) = NaN;
400         endif
401       else
402         Z = feval (fun, X, Y);
403
404         ## Eliminate the singularities
405         Z = __eliminate_sing__ (Z);
406       endif
407     endif
408   endif
409
410   oldax = gca ();
411   unwind_protect
412     axes (ax);
413     if (iscontour)
414       [clev, h] = feval (pfunc, X, Y, Z);
415     elseif (isplot && nargs == 2)
416       h = [];
417       hold_state = get (ax, "nextplot");
418       for i = 1 : length (XX)
419         h = [h; plot(XX{i}, YY{i})];
420         if (i == 1)
421           set (ax, "nextplot", "add");
422         endif
423       endfor
424       set (ax, "nextplot", hold_state);
425     elseif (ispolar || isplot)
426       h = feval (pfunc, X, Z);
427       if (isplot && !parametric)
428         axis ([X(1), X(end), yrange]);
429       endif
430     else
431       h = feval (pfunc, X, Y, Z);
432     endif
433     xlabel (xarg);
434     ylabel (yarg);
435     title (fstr);
436   unwind_protect_cleanup
437     axes (oldax);
438   end_unwind_protect
439
440 endfunction
441
442 function x = __eliminate_sing__ (x)
443   x (isinf (x)) = NaN;
444   x (abs (del2 (x)) > 0.2 * (max(x(:)) - min(x(:)))) = NaN;
445 endfunction