* Bug 15392 fixed: comet() comet3d() with named|#RRGGBB|[r g b] colors
[scilab.git] / scilab / modules / graphics / macros / comet.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 - 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 comet(varargin)
14     // Comet-like trajectory.
15     // comet(y)
16     // comet(x, y)
17     // comet(x, y, Lf)     // Lf: Leading fraction
18     // comet(x, fun)       // fun: function identifier, polynomial, rational
19     // comet(x, fun, Lf)
20     // comet(..., "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 //y
42         y=varargin(1)
43         if or(size(y)==1) then
44             x=1:size(y,"*")
45         else
46             x=1:size(y,1)
47         end
48         p=0.1
49     case 2 then  //x,y
50         [x,y]=varargin(1:2)
51         p=0.1
52     case 3 then  //x,y,p
53         [x,y,p]=varargin(1:3)
54     else
55         msg = _("%s: Wrong number of input arguments: %d to %d expected.\n");
56         error(msprintf(msg, "comet", 1, 5))
57     end
58     if type(x)<>1|~isreal(x) then
59         msg = _("%s: Wrong type for argument #%d: Real vector expected.\n");
60         error(msprintf(msg, "comet", 1))
61     end
62     if type(y)==13 then //a function
63         prot=funcprot();funcprot(0)
64         y=feval(x,y)
65         funcprot(prot)
66     elseif type(y)==2 then //a polynomial
67         y=horner(y,x)
68     elseif typeof(y)=="rational" then //a rational fraction
69         y=horner(y,x)
70     end
71     if type(y)<>1|~isreal(y) then
72         msg = _("%s: Wrong type for argument #%d: Real vector expected.\n");
73         error(msprintf(msg, "comet", 2))
74     end
75     if type(p)<>1|~isreal(p)|size(p,"*")>1 then
76         msg = _("%s: Wrong type for argument #%d: Real scalar expected.\n");
77         error(msprintf(msg, "comet", 3))
78     end
79     if p<0|p>=1 then
80         msg = _("%s: Wrong value for input argument #%d: Must be in the interval %s.\n");
81         error(msprintf(msg, "comet", 3, "[0 1["))
82     end
83
84     if or(size(x)==1) then
85         x=x(:)
86         n=size(x,1)
87         if or(size(y)==1) then
88             if n<>size(y,"*") then
89                 msg = _("%s: Incompatible input arguments #%d and #%d: Same sizes expected.\n");
90                 error(msprintf(msg, "comet", 1, 2))
91             end
92             y=y(:)
93             m=1
94         else
95             m=size(y,2)
96             if size(y,1)<>n then
97                 msg = _("%s: Incompatible input arguments #%d and #%d: Same number of rows expected.\n")
98                 error(msprintf(msg, "comet", 1, 2))
99             end
100             x=x*ones(1,m)
101         end
102     else
103         n=size(x,1)
104         m=size(x,2)
105         if or(size(y)<>size(x)) then
106             msg = _("%s: Incompatible input arguments #%d and #%d: Same sizes expected.\n")
107             error(msprintf(msg, "comet", 1, 2))
108         end
109     end
110     fig = gcf();
111     if c==[] then
112         c = 1:m
113     else
114         if size(c,"*") <> m then
115             msg = _("%s: Wrong size for argument #%d: %d expected.\n")
116             error(msprintf(msg, "comet", nv, m))
117         end
118     end
119
120     axes = gca();
121     if axes.children==[] then
122         axes.data_bounds=[min(x) min(y);max(x) max(y)];
123         axes.axes_visible="on";
124     else
125         axes.data_bounds=[min(axes.data_bounds(1,:), [min(x) min(y)]);
126         max(axes.data_bounds(2,:), [max(x) max(y)])];
127     end
128     //create the head, body and tail polylines
129     drawlater()
130     tail=[];body=[];head=[];
131     for l=1:m
132         xpoly([],[]);tail(l)=gce();
133         tail(l).foreground=c(l);
134         xpoly([],[]);body(l)=gce();
135         body(l).foreground=c(l);
136         body(l).thickness=2;
137         xpoly([],[],"marks");head(l)=gce();
138         head(l).mark_size_unit="point";
139         head(l).mark_size=6;
140         head(l).mark_style=9;
141         head(l).mark_foreground=c(l);
142     end
143     show_window();
144
145
146     function anim()
147         //animation loop
148         k = round(p*n);
149         step=ceil(n/200); //used to speed up the drawing
150
151         for i=1:n
152             for l=1:m
153                 head(l).data=[x(i,l),y(i,l)];
154                 if i<=k then
155                     body(l).data= [body(l).data;[x(i,l),y(i,l)]];
156                 else
157                     body(l).data= [body(l).data(2:$,:);[x(i,l),y(i,l)]];
158                     tail(l).data=[ tail(l).data;[x(i-k+1,l),y(i-k+1,l)]];
159                 end
160             end
161             if modulo(i,step)==0 then
162                 fig.immediate_drawing = "on"
163                 fig.immediate_drawing = "off"
164             end
165         end
166         fig.immediate_drawing = "on"
167         fig.immediate_drawing = "off"
168         for i=1:k
169             for l=1:m
170                 body(l).data= body(l).data(2:$,:);
171                 tail(l).data=[tail(l).data;[x(n-k+i,l),y(n-k+i,l)]];
172             end
173             if modulo(i,step)==0 then
174                 fig.immediate_drawing = "on"
175                 fig.immediate_drawing = "off"
176             end
177         end
178         fig.immediate_drawing = "on"
179         delete(body)
180     endfunction
181     //not to generate an error message if the window is closed
182     exec(anim, "errcatch", -1);
183 endfunction