f1373b5fcba522218bfff3aae7fb18d611b3fcc4
[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 //
4 // Copyright (C) 2012 - 2016 - Scilab Enterprises
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) displays an animated comet plot of the vector y.
16     //   comet(x,y) displays an animated comet plot of vector y vs. x.
17     //   comet(x,y,p) uses a comet of length p*size(y,'*').  Default is p = 0.1.
18
19     //   Example:
20     //       t = linspace(0,10*%pi,500);
21     //       clf();comet(t.*sin(t),t.*cos(t))
22     //
23     //       function y=traj(x),y=1.5*sin(x^2),endfunction
24     //       clf();comet(linspace(0,5,500),traj)
25     //
26     //       clf();comet(linspace(-2,4,500),(%s-3)/(%s^3+2*%s^2+1))
27
28     nv=size(varargin)
29     if nv>=3&varargin(nv-1)=="colors" then
30         c=round(varargin(nv))
31         if type(c)<>1|~isreal(c) then
32             error(msprintf(_("%s: Wrong type for argument #%d: Real vector expected.\n"),"comet",nv))
33         end
34         varargin=list(varargin(1:$-2))
35     else
36         c=[]
37     end
38     select size(varargin)
39     case 1 then //y
40         y=varargin(1)
41         if or(size(y)==1) then
42             x=1:size(y,"*")
43         else
44             x=1:size(y,1)
45         end
46         p=0.1
47     case 2 then  //x,y
48         [x,y]=varargin(1:2)
49         p=0.1
50     case 3 then  //x,y,p
51         [x,y,p]=varargin(1:3)
52     else
53         error(msprintf(_("%s: Wrong number of input arguments: %d to %d expected.\n"),"comet",1,3))
54     end
55     if type(x)<>1|~isreal(x) then
56         error(msprintf(_("%s: Wrong type for argument #%d: Real vector expected.\n"),"comet",1))
57     end
58     if type(y)==13 then //a function
59         prot=funcprot();funcprot(0)
60         y=feval(x,y)
61         funcprot(prot)
62     elseif type(y)==2 then //a polynomial
63         y=horner(y,x)
64     elseif typeof(y)=="rational" then //a rational fraction
65         y=horner(y,x)
66     end
67     if type(y)<>1|~isreal(y) then
68         error(msprintf(_("%s: Wrong type for argument #%d: Real vector expected.\n"),"comet",2))
69     end
70     if type(p)<>1|~isreal(p)|size(p,"*")>1 then
71         error(msprintf(_("%s: Wrong type for argument #%d: Real scalar expected.\n"),"comet",3))
72     end
73     if p<0|p>=1 then
74         error(msprintf(_("%s: Wrong value for input argument #%d: Must be in the interval %s.\n"),"comet",3,"[0 1["))
75     end
76
77     if or(size(x)==1) then
78         x=x(:)
79         n=size(x,1)
80         if or(size(y)==1) then
81             if n<>size(y,"*") then
82                 error(msprintf(_("%s: Incompatible input arguments #%d and #%d: Same sizes expected.\n"),"comet",1,2))
83             end
84             y=y(:)
85             m=1
86         else
87             m=size(y,2)
88             if size(y,1)<>n then
89                 error(msprintf(_("%s: Incompatible input arguments #%d and #%d: Same number of rows expected.\n"),"comet",1,2))
90             end
91             x=x*ones(1,m)
92         end
93     else
94         n=size(x,1)
95         m=size(x,2)
96         if or(size(y)<>size(x)) then
97             error(msprintf(_("%s: Incompatible input arguments #%d and #%d: Same sizes expected.\n"),"comet",1,2))
98         end
99     end
100     fig=gcf();
101     if c==[] then
102         c=1:m
103     else
104         if size(c,"*")<>m then
105             error(msprintf(_("%s: Wrong size for argument #%d: %d expected.\n"),"comet",nv,m))
106         end
107         if min(c)<1|max(c)>size(fig.color_map,1) then
108             error(msprintf(_( "%s: Wrong value for input argument #%d: Must be in the set {%s}.\n"),"comet",nv,"1,...,"+string(size(fig.color_map,1))))
109         end
110     end
111     axes=gca();
112
113     if axes.children==[] then
114         axes.data_bounds=[min(x) min(y);max(x) max(y)];
115         axes.axes_visible="on";
116     else
117         axes.data_bounds=[min(axes.data_bounds(1,:), [min(x) min(y)]);
118         max(axes.data_bounds(2,:), [max(x) max(y)])];
119     end
120     //create the head, body and tail polylines
121     drawlater()
122     tail=[];body=[];head=[];
123     for l=1:m
124         xpoly([],[]);tail(l)=gce();
125         tail(l).foreground=c(l);
126         xpoly([],[]);body(l)=gce();
127         body(l).foreground=c(l);
128         body(l).thickness=2;
129         xpoly([],[],"marks");head(l)=gce();
130         head(l).mark_size_unit="point";
131         head(l).mark_size=6;
132         head(l).mark_style=9;
133         head(l).mark_foreground=c(l);
134     end
135     show_window();
136
137
138     function anim()
139         //animation loop
140         k = round(p*n);
141         step=ceil(n/200); //used to speed up the drawing
142
143         for i=1:n
144             for l=1:m
145                 head(l).data=[x(i,l),y(i,l)];
146                 if i<=k then
147                     body(l).data= [body(l).data;[x(i,l),y(i,l)]];
148                 else
149                     body(l).data= [body(l).data(2:$,:);[x(i,l),y(i,l)]];
150                     tail(l).data=[ tail(l).data;[x(i-k+1,l),y(i-k+1,l)]];
151                 end
152             end
153             if modulo(i,step)==0 then
154                 fig.immediate_drawing = "on"
155                 fig.immediate_drawing = "off"
156             end
157         end
158         fig.immediate_drawing = "on"
159         fig.immediate_drawing = "off"
160         for i=1:k
161             for l=1:m
162                 body(l).data= body(l).data(2:$,:);
163                 tail(l).data=[tail(l).data;[x(n-k+i,l),y(n-k+i,l)]];
164             end
165             if modulo(i,step)==0 then
166                 fig.immediate_drawing = "on"
167                 fig.immediate_drawing = "off"
168             end
169         end
170         fig.immediate_drawing = "on"
171         delete(body)
172     endfunction
173     //not to generate an error message if the window is closed
174     exec(anim, "errcatch", -1);
175 endfunction