Demos: increased control panel.
[scilab.git] / scilab / modules / differential_equations / demos / levitron / levitron_gui.sci
1 //
2 // Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 // Copyright (C) 2008 - INRIA - Serge Steer <Serge.Steer@scilab.org>
4 //
5 // This file is distributed under the same license as the Scilab package.
6 //
7
8 //The graphics objects builder and subsidiaries
9 //--------------------------------------------
10 function [H]=build_levitron(h)
11     //construct the graphical object representing the levitron in 3D
12
13     n=21;// assumed to be odd
14     [X, Y, Z]=levitron_facets(levitron_profile, n)
15     N=n-1;
16     np=1+size(X, 2)/N
17     f = get("levitron_main_figure")
18
19     //Plot the levitron
20     f.color_map = graycolormap(N);
21     f.immediate_drawing = "off"
22
23     s=[((N/2)):(N-1), N:-1:((N/2)+1)];
24     plot3d(X, Y, list(Z, ones(1, np-1).*.s))// the top
25
26     H=gce();
27     H.hiddencolor=-1;
28     H.color_mode = -1;
29     H.color_flag = 3;
30     H.clip_state = "off";
31
32     H.user_data=[0 0 0 0 0 0];
33     //The z axis
34     x=0:0.05:2.5;
35     param3d(zeros(x), zeros(x), x) //z axis
36     e=gce();e.thickness=2;
37     //the bottom
38     plot3d([-1 1]*1.5, [-1 1]*1.5, zeros(2, 2))
39     e=gce();e.color_mode=color("red");
40
41     levitron_axes = gca();
42     //Axes definition for the plot
43     //plot will be on the left-hand side of the screen
44     levitron_axes.axes_bounds = [0 0 3.5/5 1];
45     levitron_axes.tight_limits="on";
46     levitron_axes.clip_state="off";
47     levitron_axes.data_bounds=[-1 -1 0;1 1 2];
48     levitron_axes.axes_visible="off";
49     levitron_axes.box="off";
50     levitron_axes.cube_scaling="on";
51     levitron_axes.isoview="on";
52     levitron_axes.rotation_angles=[76 45];
53     levitron_axes.foreground=N
54     levitron_axes.x_label.text=""
55     levitron_axes.y_label.text=""
56     levitron_axes.z_label.text=""
57
58     immediate_drawing ="on"
59     f.visible = "on"
60 endfunction
61
62 function [zp, ro]=levitron_profile()
63     //zp : elevation of the profile's points
64     //ro : radius
65     //c  : color
66     zp = [0.6;0.22;0.15;0.06;0.04;0.02;-0.04;-0.06;
67     -0.07;-0.15;-0.19;-0.27;-0.34;-0.38]*0.8;
68     ro = [0;0.03;0.07;0.42;0.43;0.44;0.44;
69     0.43;0.42;0.07;0.05;0.03;0.02;0];
70     c = ones(ro)
71 endfunction
72
73 function [X, Y, Z]=levitron_facets(prof, n)
74     //computes the facets of the surface of a revolution surface
75     // prof is a function that returns the elevation and the radiud of ech
76     // profile point
77     // n: is the number of points for the rotation angle discretization
78
79     [zp, ro]=prof();//one profile
80     np=size(ro, "*");
81     //generate points on the top surface
82     t=linspace(0, 2*%pi, n);
83     x=ro*cos(t);//np x n
84     y=ro*sin(t);
85     z=zp*ones(t);
86
87     //build the facets
88     Iz=([0;0;1;1]*ones(1, np-1)+ones(4, 1)*(1:(np-1))).*.ones(1, n-1);
89     It=ones(1, np-1).*.([0;1;1;0]*ones(1, n-1)+ones(4, 1)*(0:(n-2)));
90     I=matrix(Iz+np*It, -1, 1);
91     X=matrix(x(I), 4, -1);
92     Y=matrix(y(I), 4, -1);
93     Z=matrix(z(I), 4, -1);
94 endfunction
95
96
97 //The callbacks
98 //-------------------------------------------------------------
99
100 function update_height(h)
101     Slider_Height=get("slider_height");
102     Value_Height =get("value_height")
103     if argn(2)==1 then
104         Slider_Height.Value=(h-1.6)*100/0.2;
105     else
106         h=Slider_Height.Value
107         h=max(0.001, 1.6+h*0.2/100)
108     end
109     Value_Height.String=msprintf("%.3f", h)
110     update_state(3, h)
111 endfunction
112
113 function update_theta(t)
114     Slider_Theta=get("slider_theta")
115     Value_Theta=get("value_theta")
116     if argn(2)==1 then
117         Slider_Theta.Value=(t-0.01)*100;
118     else
119         t=Slider_Theta.Value
120         t=t/100 + 0.01
121     end
122     Value_Theta.String=msprintf("%.3f", t)
123     update_state(4, t)
124 endfunction
125
126 function update_phi(p)
127     Slider_Phi=get("slider_phi")
128     Value_Phi=get("value_phi")
129     if argn(2)==1 then
130         Slider_Phi.Value=p*100/360;
131     else
132         p=Slider_Phi.Value
133         p=360*p/100
134     end
135     Value_Phi.String=msprintf("%.3f", p)
136     update_state(5, p)
137 endfunction
138
139 function update_psi(p)
140     Slider_Psi=get("slider_psi")
141     Value_Psi=get("value_psi")
142     if argn(2)==1 then
143         Slider_Psi.Value=p*100/360;
144     else
145         p=Slider_Psi.Value
146         p=360*p/100
147     end
148     Value_Psi.String=msprintf("%.3f", p)
149     update_state(6, p)
150 endfunction
151
152
153 function levitron_start()
154     global Stop;Stop=%f;
155     show();
156 endfunction
157
158 function levitron_stop()
159     global Stop;Stop=%t
160 endfunction
161
162 function levitron_reinit()
163     global y0 y1  Stop
164     Stop=%t
165     y1=y0
166     update_height(1.72)
167     update_theta(0.28)
168     update_phi(0)
169     update_psi(0)
170 endfunction
171
172
173 // Callbacks subsidiary functions
174 //-------------------------------
175 function update_state(k, value)
176     global y1 state_changed init  Stop changed
177     if ~changed then
178         if or(k==(4:6)) then value=value*%pi/180;end
179         y1(k)=value;
180         if init then
181             set_levitron(H, y1),
182         else
183             state_changed=%t;
184         end
185     end
186 endfunction
187
188 function set_levitron(H, q)
189     O=H.user_data;
190     Data=H.data;
191     f=20 //Dilatation factor of X and Y coordinates
192     XYZ=[matrix(Data.x-f*O(1), 1, -1)
193     matrix(Data.y-f*O(2), 1, -1)
194     matrix(Data.z-O(3), 1, -1)];
195     psi  =q(6); //precession:rotation Oxyz ->Ouvz
196     theta=q(4);//nutation Ouvz -> Ouwz'
197     phi  =q(5);// rotation propre Ouwz'->0x'y'z' (referentiel attache a la toupie)
198
199     XYZ=euler(psi, theta, phi)*eulerm1(O(6), O(4), O(5))*XYZ
200
201     drawlater()
202     Data.x=f*q(1)+matrix(XYZ(1, :), 4, -1);
203     Data.y=f*q(2)+matrix(XYZ(2, :), 4, -1);
204     Data.z=q(3)+matrix(XYZ(3, :), 4, -1);
205     H.user_data(1:6)=q(1:6)';
206     H.data=Data;
207     drawnow()
208 endfunction
209
210 function show()
211     global y1 state_changed init Stop changed
212     //y1 is a copy of that can be updated by the gui (state_changed is true
213     //if the GUI has modified its value).
214     y=y1;
215     init=%f;changed=%f
216     dt=0.05
217     if state_changed then y=y1;end
218     [y, w, iw]=ode(y, 0, dt, list(levitron_dyn, a, c, Mc)); y1=y;
219     realtimeinit(dt)
220     t0=dt
221     k=1
222     while %t
223         if state_changed then
224             [y, w, iw]=ode(y1, t0, t0+dt, list(levitron_dyn, a, c, Mc));y1=y;
225         else
226             [y, w, iw]=ode(y, t0, t0+dt, list(levitron_dyn, a, c, Mc), w, iw);y1=y;
227         end
228         if y(3)<=0 then Stop=%t, end
229         if Stop then init=%t, break, end
230         if ~is_handle_valid(H) then break; end
231         set_levitron(H, y(1:6));
232
233         if %t then
234             changed=%t
235             update_height(y(3))
236             update_theta(y(4)*180/%pi)
237             update_phi(modulo(y(5)*180/%pi, 360))
238             update_psi(modulo(y(6)*180/%pi, 360))
239             changed=%f
240         end
241
242         k=k+1;t0=t0+dt;
243         realtime(k);
244     end
245 endfunction
246
247 function levitron_create_gui()
248     //Simulation parameters
249     height_param = tlist(["sim_param", "name", "unit", "default"]);
250     height_param.name = "height";
251     height_param.unit = "m";
252     height_param.default = (1.72-1.6)*50;
253
254     theta_param  = tlist(["sim_param", "name", "unit", "default"]);
255     theta_param.name = "theta" 
256     theta_param.unit = "deg"
257     theta_param.default = 28;
258
259     phi_param    = tlist(["sim_param", "name", "unit", "default"]);
260     phi_param.name = "phi"
261     phi_param.unit = "deg"
262     phi_param.default = 0;
263
264     psi_param    = tlist(["sim_param", "name", "unit", "default"]);
265     psi_param.name = "psi"
266     psi_param.unit = "deg"
267     psi_param.default = 0
268
269     param_list = list(height_param, theta_param, phi_param, psi_param);
270
271     //Create the figure and the frame to put the sliders
272     levitron_main_fig = figure( ...
273         "dockable", "off", ...
274         "infobar_visible", "off", ...
275         "toolbar_visible", "off", ...
276         "toolbar", "none", ...
277         "menubar_visible", "off", ...
278         "menubar", "none", ...
279         "default_axes", "on", ...
280         "layout", "none", ...
281         "visible", "off", ...
282         "immediate_drawing", "off", ...
283         "background", -2, ...
284         "figure_position", [0 0], ...
285         "axes_size", [800, 600], ...
286         "figure_name", "Levitron Simulation", ...
287         "tag", "levitron_main_figure");
288
289
290     levitron_main_fig.layout = "gridbag"
291
292     //An empty frame to push parameters on the right when resizing
293     c = createConstraints("gridbag", [1, 1, 1, 1], [0.75, 1], "horizontal", "upper_left", [0, 0], [500, 0])
294     empty_frame = uicontrol(levitron_main_fig, "style", "frame", "constraints", c, "backgroundcolor", [1, 0, 0]);
295
296     c = createConstraints("gridbag", [2, 1, 1, 1], [0.25, 1], "both", "right", [0, 0], [300, 0]);
297     right_frame = uicontrol(levitron_main_fig, "style", "frame", "backgroundcolor", [1, 1, 1], ...
298         "constraints", c);
299
300     right_frame.layout = "border";
301     right_frame.layout_options = createLayoutOptions("border");
302
303     l_border = createBorder("line", "black", 2)
304     param_border = createBorder("titled", l_border, "Simulation Parameters", "center", "top")
305     c = createConstraints("border", "center");
306     param_frame = uicontrol(right_frame, "style", "frame", "backgroundcolor", [1, 1, 1], ...
307         "constraints", c, "tag", "param_frame", "border", param_border, "layout", "gridbag");
308
309     c = createConstraints("border", "bottom", [0, 50]);
310     button_frame = uicontrol(right_frame, "style", "frame", "backgroundcolor", [1, 1, 1], ...
311         "constraints", c, "tag", "button_frame", "layout", "gridbag");
312
313     c = createConstraints("border", "right", [10, 0]);
314     empty_frame = uicontrol(right_frame, "style", "frame", "backgroundcolor", [1, 1, 1], ...
315         "constraints", c);
316
317     c = createConstraints("border", "left", [10, 0]);
318     empty_frame = uicontrol(right_frame, "style", "frame", "backgroundcolor", [1, 1, 1], ...
319         "constraints", c);
320
321     gui_createParamFrame(param_list);
322     gui_createButtonFrame();
323 endfunction
324
325 function gui_createParamFrame(param_list);
326     param_frame = get("param_frame");
327
328     for i = 1:size(param_list)
329         c = createConstraints("gridbag", [1, i, 1, 1], [1, 1], "both", "left", [5, 0], [25, 0]);
330             name_p = uicontrol(param_frame, ...
331             "Style", "text", ...
332             "String", param_list(i).name + " ", ...
333             "BackgroundColor", [1 1 1], ...
334             "horizontalalignment", "right", ...
335             "constraints", c, ...
336             "tag", "text_" + param_list(i).name); 
337
338         c = createConstraints("gridbag", [2, i, 1, 1], [1, 1], "both", "center", [0, 0], [60, 0]);
339         slider_p = uicontrol(param_frame, ...
340             "Style", "slider", ...
341             "Value", param_list(i).default, ...
342             "Min", 0, ...
343             "Max", 100, ...
344             "callback", "update_" + param_list(i).name + "()", ...
345             "constraints", c, ...
346             "horizontalalignment", "center", ...
347             "backgroundcolor", [1, 1, 1], ...
348             "tag", "slider_" + param_list(i).name);
349
350         c = createConstraints("gridbag", [3, i, 1, 1], [1, 1], "both", "left", [15, 0], [25, 0]);
351         value_p = uicontrol(param_frame, ...
352             "Style", "text", ...
353             "String", msprintf("%.3f", param_list(i).default), ...
354             "BackgroundColor", [1 1 1], ...
355             "constraints", c, ...
356             "foregroundcolor", [0 0 1], ...
357             "horizontalalignment", "right", ...
358             "tag", "value_" + param_list(i).name);
359
360         c = createConstraints("gridbag", [4, i, 1, 1], [1, 1], "both", "right", [5, 0], [25, 0]);
361         unite_p = uicontrol(param_frame, ...
362             "Style", "text", ...
363             "String", " " + param_list(i).unit, ...
364             "BackgroundColor", [1 1 1], ...
365             "constraints", c, ...
366             "horizontalalignment", "left", ...
367             "tag", "unite_" + param_list(i).name);
368     end
369 endfunction
370
371
372 function gui_createButtonFrame();
373     button_frame = get("button_frame");
374
375     c = createConstraints("gridbag", [1, 1, 1, 1], [1, 1], "horizontal", "left");
376     empty = uicontrol(button_frame, "style", "frame", "backgroundcolor", [1, 1, 1], "constraints", c);
377
378     c = createConstraints("gridbag", [2, 1, 1, 1], [0, 0], "none", "center");
379     Start = uicontrol("parent", button_frame, ...
380         "Style"     , "pushbutton", ...
381         "String"    , "Start", ...
382         "callback"  , "levitron_start()", ...
383         "constraints", c, ...
384         "tag", "Start");
385
386     c = createConstraints("gridbag", [3, 1, 1, 1], [1, 1], "horizontal", "center");
387     empty = uicontrol(button_frame, "style", "frame", "backgroundcolor", [1, 1, 1], "constraints", c);
388
389     c = createConstraints("gridbag", [4, 1, 1, 1], [0, 0], "none", "center");
390     Stop = uicontrol("parent", button_frame, ...
391         "Style"     , "pushbutton", ...
392         "String"    , "Stop", ...
393         "callback"  , "levitron_stop()", ...
394         "constraints", c, ...
395         "tag", "Stop");
396
397     c = createConstraints("gridbag", [5, 1, 1, 1], [1, 1], "horizontal", "center");
398     empty = uicontrol(button_frame, "style", "frame", "backgroundcolor", [1, 1, 1], "constraints", c);
399
400     c = createConstraints("gridbag", [6, 1, 1, 1], [0, 0], "none", "center");
401     Reinit = uicontrol("parent", button_frame, ...
402         "Style"     , "pushbutton", ...
403         "String"    , "Reset", ...
404         "callback"  , "levitron_reinit()", ...
405         "constraints", c, ...
406         "tag", "Reinit");
407
408     c = createConstraints("gridbag", [7, 1, 1, 1], [1, 1], "horizontal", "right");
409     empty = uicontrol(button_frame, "style", "frame", "backgroundcolor", [1, 1, 1], "constraints", c);
410 endfunction