* Bug 15392 fixed: comet() comet3d() with named|#RRGGBB|[r g b] colors
[scilab.git] / scilab / modules / graphics / macros / comet3d.sci
1 // Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
2 // Copyright (C) 2011 - INRIA - Serge Steer <serge.steer@inria.fr>
3 // Copyright (C) 2012 - 2016 - Scilab Enterprises
4 // Copyright (C) 2018 - 2019 - Samuel GOUGEON
5 //
6 // This file is hereby licensed under the terms of the GNU GPL v2.0,
7 // pursuant to article 5.3.4 of the CeCILL v.2.1.
8 // This file was originally licensed under the terms of the CeCILL v2.1,
9 // and continues to be available under such terms.
10 // For more information, see the COPYING file which you should have received
11 // along with this program.
12
13 function comet3d(varargin)
14     // 3D Comet-like trajectory.
15     // comet3d(z)
16     // comet3d(x, y, z)
17     // comet3d(x, y, z, Lf)     // Lf: Leading fraction
18     // comet3d(x, y, fun)       // fun: function identifier, polynomial, rational
19     // comet3d(x, y, fun, Lf)
20     // comet3d(...,"colors", c) // c: -1, 4, "orange", "ma", "#RRGGBB", [r g b]
21     //
22     // History:
23     //  2018: colors as "name" "nam" "#RRGGBB" or [r g b] now allowed
24
25     nv = size(varargin)
26     if nv >= 3 & varargin(nv-1)=="colors" then
27         c = iscolor( varargin(nv))
28         if or(isnan(c))
29             msg = "%s: Argument #%d: Wrong color specification.\n";
30             error(msprintf(msg, "comet", nv))
31         end
32         if size(c,2)==3
33             c = addcolor(c)
34         end
35         varargin = list(varargin(1:$-2))
36     else
37         c = []
38     end
39
40     select size(varargin)
41     case 1 then //z
42         z = varargin(1)
43         if or(size(z)==1) then
44             x = 1:size(z,"*")
45         else
46             x = 1:size(z,1)
47         end
48         y = x
49         p = 0.1
50     case 3 then  //x,y,z
51         [x,y,z] = varargin(1:3)
52         p = 0.1
53     case 4 then  //x,y,z,p
54         [x,y,z,p] = varargin(1:4)
55     else
56         msg = _("%s: Wrong number of input arguments: %d or %d to %d expected.\n")
57         error(msprintf(msg, "comet3d", 1, 3, 6))
58     end
59
60
61     if type(x) <> 1 | ~isreal(x) then
62         msg = _("%s: Wrong type for argument #%d: Real vector expected.\n")
63         error(msprintf(msg, "comet3d", 1))
64     end
65     if type(y)<>1|~isreal(x) then
66         msg = _("%s: Wrong type for argument #%d: Real vector expected.\n")
67         error(msprintf(msg, "comet3d", 1))
68     end
69
70     if (type(z)<>1|~isreal(z))&type(z)<>13 then
71         msg = _("%s: Wrong type for argument #%d: Real vector expected.\n")
72         error(msprintf(msg, "comet3d", 3))
73     end
74
75     if type(z)==13 then
76         x = x(:);
77         y = y(:)
78         n = size(x,"*")
79         m = 1
80         if n <> size(y,"*") then
81             msg = _("%s: Incompatible input arguments #%d and #%d: Same sizes expected.\n")
82             error(msprintf(msg, "comet3d", 1, 2))
83         end
84         prot=funcprot();funcprot(0)
85         zz=z;
86         z=zeros(n,1);
87         for i=1:n
88             z(i)=zz(x(i),y(i))
89         end
90         funcprot(prot)
91     else
92         if or(size(z)==1) then
93             m = 1
94             z = z(:)
95             n = size(z,"*")
96         else
97             [n, m] = size(z)
98         end
99         if or(size(x)==1) then
100             x = x(:)
101             if size(x,"*")<>n then
102                 msg = _("%s: Wrong size for argument #%d: %d expected.\n")
103                 error(msprintf(msg, "comet3d", 1, n))
104             end
105             x = x*ones(1,m)
106         else
107             if or(size(x)<>size(z)) then
108                 msg = _("%s: Incompatible input arguments #%d and #%d: Same sizes expected.\n")
109                 error(msprintf(msg, "comet3d", 1, 3))
110             end
111         end
112         if or(size(y)==1) then
113             y = y(:)
114             if size(y,"*")<>n then
115                 msg = _("%s: Wrong size for argument #%d: %d expected.\n")
116                 error(msprintf(msg, "comet3d", 2, n))
117             end
118             y = y*ones(1,m)
119         else
120             if or(size(y)<>size(z)) then
121                 msg = _("%s: Incompatible input arguments #%d and #%d: Same sizes expected.\n")
122                 error(msprintf(msg, "comet3d", 2, 3))
123             end
124
125         end
126     end
127
128
129     if type(p) <> 1 | ~isreal(p) | size(p,"*") > 1 then
130         msg = _("%s: Wrong type for argument #%d: Real scalar expected.\n")
131         error(msprintf(msg, "comet3d", 3))
132     end
133     if p<0 | p >= 1 then
134         msg = _("%s: Wrong value for input argument #%d: Must be in the interval %s.\n")
135         error(msprintf(msg, "comet3d", 3, "[0 1["))
136     end
137     fig = gcf();
138     if c==[] then
139         c = 1:m
140     else
141         if size(c,"*") <> m then
142             msg = _("%s: Wrong size for argument #%d: %d expected.\n")
143             error(msprintf(msg, "comet", nv, m))
144         end
145     end
146     axes = gca();
147     axes.view = "3d"
148
149
150     if axes.children==[] then
151         axes.data_bounds = [min(x) min(y) min(z);max(x) max(y) max(z)];
152         axes.axes_visible = "on";
153         axes.box = "on";
154     else
155         axes.data_bounds = [min(axes.data_bounds(1,:), [min(x) min(y) min(z)]);
156         max(axes.data_bounds(2,:), [max(x) max(y) max(z)])];
157     end
158     //create the head, body and tail polylines
159     drawlater()
160     for l = 1:m
161         xpoly([],[]);
162         tail(l) = gce();
163         tail(l).foreground = c(l);
164
165         xpoly([],[]);
166         body(l) = gce();
167         body(l).foreground = c(l);
168         body(l).thickness = 2;
169         xpoly([], [], "marks");
170         head(l) = gce();
171         head(l).mark_size_unit = "point";
172         head(l).mark_size = 6;
173         head(l).mark_style = 9;
174         head(l).mark_foreground = c(l);
175     end
176     show_window();
177
178     function anim()
179         //animation loop
180         k = round(p*n);
181         step = ceil(n/200); //used to speed up the drawing
182
183         for i = 1:n
184             for l = 1:m
185                 head(l).data = [x(i,l),y(i,l),z(i,l)];
186                 if i <= k then
187                     body(l).data = [body(l).data;[x(i,l),y(i,l),z(i,l)]];
188                 else
189                     body(l).data = [body(l).data(2:$,:);[x(i,l),y(i,l),z(i,l)]];
190                     tail(l).data =[ tail(l).data;[x(i-k,l),y(i-k,l),z(i-k,l)]];
191                 end
192             end
193             if modulo(i,step)==0 then
194                 fig.immediate_drawing = "on";
195                 fig.immediate_drawing = "off";
196             end
197         end
198         drawnow(),drawlater()
199
200         for i = n:n+k
201             for l = 1:m
202                 body(l).data = body(l).data(2:$,:);
203                 tail(l).data = [tail(l).data;[x(i-k,l),y(i-k,l),z(i-k,l)]];
204             end
205             if modulo(i,step)==0 then
206                 fig.immediate_drawing = "on";
207                 fig.immediate_drawing = "off";
208             end
209         end
210         delete(body)
211         drawnow()
212     endfunction
213     //not to generate an error message if the window is closed
214     exec(anim, "errcatch", -1)
215     //exec(anim,-1)
216 endfunction