]> Creatis software - CreaPhase.git/blob - octave_packages/m/plot/private/__quiver__.m
update packages
[CreaPhase.git] / octave_packages / m / plot / private / __quiver__.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{hg} =} __quiver__ (@dots{})
21 ## Undocumented internal function.
22 ## @end deftypefn
23
24 function hg = __quiver__ (varargin)
25
26   h = varargin{1};
27   is3d = varargin{2};
28
29   autoscale = 0.9;
30   arrowsize = 0.2;
31
32   firstnonnumeric = Inf;
33   for i = 3:nargin
34     if (! isnumeric (varargin{i}))
35       firstnonnumeric = i;
36       break;
37     endif
38   endfor
39
40   ioff = 3;
41   if (nargin < (6 + is3d) || firstnonnumeric < (6 + is3d))
42     u = varargin{ioff++};
43     v = varargin{ioff++};
44     if (is3d)
45       w = varargin{ioff++};
46       [x, y, z] = meshgrid (1:size(u,2), 1:size(u,1), 1:max(size(w)));
47     else
48       [x, y] = meshgrid (1:size(u,2), 1:size(u,1));
49     endif
50     if (nargin >= ioff && isnumeric (varargin{ioff})
51         && isscalar (varargin{ioff}))
52       autoscale = varargin{ioff++};
53     endif
54   else
55     x = varargin{ioff++};
56     y = varargin{ioff++};
57     if (is3d)
58       z = varargin{ioff++};
59     endif
60     u = varargin{ioff++};
61     v = varargin{ioff++};
62     if (is3d)
63       w = varargin{ioff++};
64       if (isvector (x) && isvector (y) && isvector (z)
65           && (! isvector (u) || ! isvector (v) || ! isvector(w)))
66         [x, y, z] = meshgrid (x, y, z);
67       endif
68     else
69       if (isvector (x) && isvector (y) && (! isvector (u) || ! isvector (v)))
70         [x, y] = meshgrid (x, y);
71       endif
72     endif
73     if (nargin >= ioff && isnumeric (varargin{ioff})
74         && isscalar (varargin{ioff}))
75       autoscale = varargin{ioff++};
76     endif
77   endif
78
79   have_filled = false;
80   have_line_spec = false;
81   args = {};
82   while (ioff <= nargin)
83     arg = varargin{ioff++};
84     if (ischar (arg) && strncmpi (arg, "filled", 6))
85       have_filled = true;
86     elseif ((ischar (arg) || iscell (arg))
87             && ! have_line_spec)
88       [linespec, valid] = __pltopt__ ("quiver", arg, false);
89       if (valid)
90         have_line_spec = true;
91         if (strncmp (linespec.linestyle, "none", 4))
92           linespec.linestyle = "-";
93         endif
94       else
95         args {end + 1} = arg;
96         if (ioff <= nargin)
97           args {end + 1} = varargin{ioff++};
98         endif
99       endif
100     else
101       args {end + 1} = arg;
102       if (ioff <= nargin)
103         args {end + 1} = varargin{ioff++};
104       endif
105     endif
106   endwhile
107
108   if (autoscale && numel (u) > 1)
109     ## Scale the arrows to fit in the grid
110     if (isvector (x))
111       ny = nx = length (x);
112     else
113       [nx, ny] = size (x);
114     endif
115     dx = (max(x(:)) - min(x(:))) ./ nx;
116     dy = (max(y(:)) - min(y(:))) ./ ny;
117     if (is3d)
118       dz = (max(z(:)) - min(z(:))) ./ max (size (z));
119       len = max (sqrt (u(:).^2 + v(:).^2 + w(:).^2));
120     else
121       dz = 0;
122       len = max (sqrt (u(:).^2 + v(:).^2));
123     endif
124     if (len > 0)
125       sd = sqrt (dx.^2 + dy.^2 + dz.^2) / len;
126       if (sd != 0)
127         s = sqrt(2) * autoscale * sd;
128       else # special case of identical points with multiple vectors
129         s = autoscale;
130       endif
131       uu = s * u;
132       vv = s * v;
133       if (is3d)
134         ww = s*w;
135       endif
136     endif
137   else
138     uu = u;
139     vv = v;
140     if (is3d)
141       ww = w;
142     endif
143   endif
144
145   hstate = get (h, "nextplot");
146   unwind_protect
147     hg = hggroup ();
148     if (is3d)
149       args = __add_datasource__ ("quiver3", hg,
150                                  {"x", "y", "z", "u", "v", "w"}, args{:});
151     else
152       args = __add_datasource__ ("quiver", hg,
153                                  {"x", "y", "z", "u", "v", "w"}, args{:});
154     endif
155     hold on;
156
157     addproperty ("xdata", hg, "data", x);
158     addproperty ("ydata", hg, "data", y);
159
160     addproperty ("udata", hg, "data", u);
161     addproperty ("vdata", hg, "data", v);
162     if (is3d)
163       addproperty ("zdata", hg, "data", z);
164       addproperty ("wdata", hg, "data", w);
165     else
166       addproperty ("zdata", hg, "data", []);
167       addproperty ("wdata", hg, "data", []);
168     endif
169
170     addlistener (hg, "xdata", @update_data);
171     addlistener (hg, "ydata", @update_data);
172     addlistener (hg, "zdata", @update_data);
173     addlistener (hg, "udata", @update_data);
174     addlistener (hg, "vdata", @update_data);
175     addlistener (hg, "wdata", @update_data);
176
177     x = x(:);
178     y = y(:);
179     xend = x + uu(:);
180     yend = y + vv(:);
181     if (is3d)
182       z = z(:);
183       zend = z + ww(:);
184     endif
185
186     if (have_line_spec)
187       if (is3d)
188         h1 = plot3 ([x.'; xend.'; NaN(1, length (x))](:),
189                     [y.'; yend.'; NaN(1, length (y))](:),
190                     [z.'; zend.'; NaN(1, length (z))](:),
191                     "linestyle", linespec.linestyle,
192                     "color", linespec.color, "parent", hg);
193       else
194         h1 = plot ([x.'; xend.'; NaN(1, length (x))](:),
195                    [y.'; yend.'; NaN(1, length (y))](:),
196                    "linestyle", linespec.linestyle,
197                     "color", linespec.color, "parent", hg);
198       endif
199     else
200       if (is3d)
201         h1 = plot3 ([x.'; xend.'; NaN(1, length (x))](:),
202                     [y.'; yend.'; NaN(1, length (y))](:),
203                     [z.'; zend.'; NaN(1, length (z))](:),
204                     "color", "black", "parent", hg);
205       else
206         h1 = plot ([x.'; xend.'; NaN(1, length (x))](:),
207                    [y.'; yend.'; NaN(1, length (y))](:),
208                    "parent", hg);
209       endif
210     endif
211
212     xtmp = x + uu(:) .* (1 - arrowsize);
213     ytmp = y + vv(:) .* (1 - arrowsize);
214     xarrw1 = xtmp + (y - yend) * arrowsize / 3;
215     xarrw2 = xtmp - (y - yend) * arrowsize / 3;
216     yarrw1 = ytmp - (x - xend) * arrowsize / 3;
217     yarrw2 = ytmp + (x - xend) * arrowsize / 3;
218     if (is3d)
219       zarrw1 = zarrw2 = zend - ww(:) * arrowsize;
220     endif
221
222     if (have_line_spec)
223       if (isfield (linespec, "marker")
224           && ! strncmp (linespec.marker, "none", 4))
225         if (is3d)
226           h2 = plot3 ([xarrw1.'; xend.'; xarrw2.'; NaN(1, length (x))](:),
227                       [yarrw1.'; yend.'; yarrw2.'; NaN(1, length (y))](:),
228                       [zarrw1.'; zend.'; zarrw2.'; NaN(1, length (z))](:),
229                       "linestyle", "none", "parent", hg);
230         else
231           h2 = plot ([xarrw1.'; xend.'; xarrw2.'; NaN(1, length (x))](:),
232                      [yarrw1.'; yend.'; yarrw2.'; NaN(1, length (y))](:),
233                      "linestyle", "none", "parent", hg);
234         endif
235       else
236         if (is3d)
237           h2 = plot3 ([xarrw1.'; xend.'; xarrw2.'; NaN(1, length (x))](:),
238                       [yarrw1.'; yend.'; yarrw2.'; NaN(1, length (y))](:),
239                       [zarrw1.'; zend.'; zarrw2.'; NaN(1, length (z))](:),
240                       "linestyle", linespec.linestyle,
241                       "color", linespec.color, "parent", hg);
242         else
243           h2 = plot ([xarrw1.'; xend.'; xarrw2.'; NaN(1, length (x))](:),
244                      [yarrw1.'; yend.'; yarrw2.'; NaN(1, length (y))](:),
245                      "linestyle", linespec.linestyle,
246                       "color", linespec.color, "parent", hg);
247         endif
248       endif
249     elseif (is3d)
250       h2 = plot3 ([xarrw1.'; xend.'; xarrw2.'; NaN(1, length (x))](:),
251                   [yarrw1.'; yend.'; yarrw2.'; NaN(1, length (y))](:),
252                   [zarrw1.'; zend.'; zarrw2.'; NaN(1, length (z))](:),
253                   "color", "black", "parent", hg);
254     else
255       h2 = plot ([xarrw1.'; xend.'; xarrw2.'; NaN(1, length (x))](:),
256                  [yarrw1.'; yend.'; yarrw2.'; NaN(1, length (y))](:),
257                  "parent", hg);
258     endif
259
260     if (! have_line_spec
261         || (isfield (linespec, "marker")
262             && strncmp (linespec.marker, "none", 4)))
263       if (is3d)
264         h3 = plot3 (x, y, z, "linestyle", "none", "marker", "none",
265                     "parent", hg);
266       else
267         h3 = plot (x, y, "linestyle", "none", "marker", "none", "parent", hg);
268       endif
269     else
270       if (is3d)
271         h3 = plot3 (x, y, z, "linestyle", "none", "marker", linespec.marker,
272                     "parent", hg);
273       else
274
275         h3 = plot (x, y, "linestyle", "none", "marker", linespec.marker,
276                    "parent", hg);
277       endif
278     endif
279     if (have_filled)
280       ## FIXME gnuplot doesn't respect the markerfacecolor field
281       set (h3, "markerfacecolor", get (h1, "color"));
282     endif
283
284     ## Set up the hggroup properties and listeners
285     if (autoscale)
286       addproperty ("autoscale", hg, "radio", "{on}|off", "on");
287       addproperty ("autoscalefactor", hg, "data", autoscale);
288     else
289       addproperty ("autoscale", hg, "radio", "{on}|off", "off");
290       addproperty ("autoscalefactor", hg, "data", 1.0);
291     endif
292     addlistener (hg, "autoscale", @update_data);
293     addlistener (hg, "autoscalefactor", @update_data);
294
295     addproperty ("maxheadsize", hg, "data", arrowsize);
296     addlistener (hg, "maxheadsize", @update_data);
297
298     addproperty ("showarrowhead", hg, "radio", "{on}|off", "on");
299     addlistener (hg, "showarrowhead", @update_props);
300
301     addproperty ("color", hg, "linecolor", get (h1, "color"));
302     addproperty ("linewidth", hg, "linelinewidth", get (h1, "linewidth"));
303     addproperty ("linestyle", hg, "linelinestyle", get (h1, "linestyle"));
304     addproperty ("marker", hg, "linemarker", get (h3, "marker"));
305     addproperty ("markerfacecolor", hg, "linemarkerfacecolor",
306                  get (h3, "markerfacecolor"));
307     addproperty ("markersize", hg, "linemarkersize", get (h3, "markersize"));
308
309     addlistener (hg, "color", @update_props);
310     addlistener (hg, "linewidth", @update_props);
311     addlistener (hg, "linestyle", @update_props);
312     addlistener (hg, "marker", @update_props);
313     addlistener (hg, "markerfacecolor", @update_props);
314     addlistener (hg, "markersize", @update_props);
315
316     if (! isempty (args))
317       set (hg, args{:});
318     endif
319   unwind_protect_cleanup
320     set (h, "nextplot", hstate);
321   end_unwind_protect
322
323 endfunction
324
325 function update_data (h, d)
326   x = get (h, "xdata");
327   y = get (h, "ydata");
328   z = get (h, "zdata");
329
330   u = get (h, "udata");
331   v = get (h, "vdata");
332   w = get (h, "wdata");
333
334   s = get (h, "autoscalefactor");
335   arrowsize = get (h, "maxheadsize");
336
337   kids = get (h, "children");
338
339   if (isempty (z) || isempty (w))
340     is3d = false;
341   else
342     is3d = true;
343   endif
344
345   if (strcmpi (get (h, "autoscale"), "on") && s != 0)
346     ## Scale the arrows to fit in the grid
347     if (isvector (x))
348       ny = nx = length (x);
349     else
350       [nx, ny] = size (x);
351     endif
352     dx = (max(x(:)) - min(x(:))) ./ nx;
353     dy = (max(y(:)) - min(y(:))) ./ ny;
354     if (is3d)
355       dz = (max(z(:)) - min(z(:))) ./ max (size (z));
356       len = max (sqrt (u(:).^2 + v(:).^2 + w(:).^2));
357     else
358       dz = 0;
359       len = max (sqrt (u(:).^2 + v(:).^2));
360     endif
361     if (len > 0)
362       sd = sqrt (dx.^2 + dy.^2 + dz.^2) / len;
363       if (sd != 0)
364         s *= sqrt(2) * sd;
365       endif
366       u = s * u;
367       v = s * v;
368       if (is3d)
369         w = s*w;
370       endif
371     endif
372   endif
373
374   x = x(:);
375   y = y(:);
376   xend = x + u(:);
377   yend = y + v(:);
378   if (is3d)
379     z = z(:);
380     zend = z + w(:);
381   endif
382
383   set (kids (3), "xdata", [x.'; xend.'; NaN(1, length (x))](:));
384   set (kids (3), "ydata", [y.'; yend.'; NaN(1, length (y))](:));
385   if (is3d)
386     set (kids (3), "zdata", [z.'; zend.'; NaN(1, length (z))](:));
387   endif
388
389   xtmp = x + u(:) .* (1 - arrowsize);
390   ytmp = y + v(:) .* (1 - arrowsize);
391   xarrw1 = xtmp + (y - yend) * arrowsize / 3;
392   xarrw2 = xtmp - (y - yend) * arrowsize / 3;
393   yarrw1 = ytmp - (x - xend) * arrowsize / 3;
394   yarrw2 = ytmp + (x - xend) * arrowsize / 3;
395   if (is3d)
396     zarrw1 = zarrw2 = zend - w(:) * arrowsize;
397   endif
398
399   set (kids (2), "xdata", [x.'; xend.'; NaN(1, length (x))](:));
400   set (kids (2), "ydata", [y.'; yend.'; NaN(1, length (y))](:));
401   if (is3d)
402     set (kids (2), "zdata", [z.'; zend.'; NaN(1, length (z))](:));
403   endif
404
405   set (kids (2), "xdata", [xarrw1.'; xend.'; xarrw2.'; NaN(1, length (x))](:));
406   set (kids (2), "ydata", [yarrw1.'; yend.'; yarrw2.'; NaN(1, length (y))](:));
407   if (is3d)
408     set (kids (2), "zdata", [zarrw1.'; zend.'; zarrw2.'; NaN(1, length (z))](:));
409   endif
410
411   set (kids (1), "xdata", x);
412   set (kids (1), "ydata", y);
413   if (is3d)
414     set (kids (1), "zdata", z);
415   endif
416
417 endfunction
418
419 function update_props (h, d)
420   kids = get (h, "children");
421
422   set (kids(3), "color", get (h, "color"),
423        "linewidth", get (h, "linewidth"),
424        "linestyle", get (h, "linestyle"));
425   set (kids(2), "color", get (h, "color"),
426        "linewidth", get (h, "linewidth"),
427        "linestyle", get (h, "linestyle"));
428   if (strcmpi (get (h, "showarrowhead"), "on"))
429     set (kids (2), "visible", "on");
430   else
431     set (kids (2), "visible", "off");
432   endif
433   set (kids(1), "color", get (h, "color"),
434        "marker", get (h, "marker"),
435        "markerfacecolor", get (h, "markerfacecolor"),
436        "markersize", get (h, "markersize"));
437 endfunction