update of Signalbuilder to Scilab 5.x
[scilab.git] / scilab / modules / graphics / macros / edit_curv.sci
1 // Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
2 // Copyright (C) 1993 - INRIA - Serge Steer
3 // Copyright (C) 1993 - INRIA - Habib Jreij
4 // This file must be used under the terms of the CeCILL.
5 // This source file is licensed as described in the file COPYING, which
6 // you should have received as part of this distribution.  The terms
7 // are also available at    
8 // http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
9
10 function [x,y,ok,gc]=edit_curv(x,y,job,tit,gc)
11 //   mod_curv  - Edition  de courbe interactive
12 //%Syntaxe
13 //  [x,y,ok]=mod_curv(xd,yd,job,tit)
14 //%Parametres
15 //  xd    :  vecteur des abscisses donnees (eventuellement [])
16 //  yd    :  vecteur des ordonnees donnees (eventuellement [])
17 //  job   :  chaine de 3 caracteres  specifiant les operations
18 //           permises:
19 //            - Si la chaine contient le caractere 'a', il est 
20 //              possible d'ajouter des points aux donnees, sinon
21 //              il est seulement possible de les deplacer
22 //            - Si la chaine contient le caractere 'x', il est 
23 //              possible de deplacer les points horizontalement
24 //            - Si la chaine contient le caractere 'y', il est 
25 //              possible de deplacer les points verticalement
26 //  tit   : liste de trois chaines de caracteres
27 //          tit(1) : titre de la courbe (peut etre un vecteur colonne)
28 //          tit(2) : label de l'axe des abscisses
29 //          tit(3) : label de l'axe des ordonnees
30 //  x     : vecteur des abscisses resultat
31 //  y     : vecteur des ordonnees resultat
32 //  ok    : vaut %t si la sortie as ete demandee par le menu Ok
33 //           et  %f si la sortie as ete demandee par le menu Abort
34 //%menus
35 //  Ok    : sortie de l'editeur et retour de la courbe editee
36 //  Abort : sortie de l'editeur et retour au donnes initiales 
37 //  Undo  : annulation de la derniere modification
38 //  Size  : changement des bornes du graphique
39 //  Grids : changement des graduations du graphique
40 //  Clear : effacement de la courbe (x=[] et y=[]) (sans quitter l'editeur)
41 //  Read  : lecture de la courbe a partir d'un fichier d'extension .xy
42 //  Save  : sauvegarde binaire (sur un fichier d'extension .xy) de 
43 //          la courbe
44 //!
45   [lhs,rhs]=argn(0)
46
47   ok = %t; 
48   if rhs==0 then x=[]; y=[],end;
49   if rhs==1 then y=x;x=(1:size(y,'*'))',end
50   if rhs<3  then job='axy',end
51   if rhs<4 then tit=[' ',' ',' '],end
52   if size(tit,'*')<3 then tit(3)=' ',end
53   //
54  
55   [mx,nx] = size(x); x=x(:)
56   [my,ny] = size(y); y=y(:)
57   n = min(mx*nx,my*ny)
58   x= x(1:n);y=y(1:n);
59   xsav=x; ysav=y; xs=x; ys=y;
60   //
61   lj = length(job)
62   add=0;modx=0;mody=0
63   for k=1:lj
64     jk = part(job,k)
65     select jk
66     case 'a' then add = 1,
67     case 'x' then modx= 1
68     case 'y' then mody= 1
69     else error("[job] parameter is not correct")
70     end
71   end
72   eps = 0.03
73   symbsiz = 0.2
74   // bornes initiales du graphique
75   if rhs<5 then
76     if mx<>0 then
77       xmx = maxi(x); xmn = mini(x)
78       ymx = maxi(y); ymn = mini(y)
79       dx = xmx-xmn;  dy = ymx-ymn
80       if dx==0 then dx=maxi(xmx/2,1),end
81       xmn=xmn-dx/10;xmx=xmx+dx/10
82       if dy==0 then dy=maxi(ymx/2,1),end;
83       ymn=ymn-dy/10;ymx=ymx+dy/10;
84     else
85       xmn=0;ymn=0;xmx=1;ymx=1;dx=1;dy=1
86     end
87     rect=[xmn,ymn,xmx,ymx];
88     axisdata=[2 10 2 10]; 
89     gc = list(rect,axisdata);
90   else //** rhs=5 as in Scicos ;) 
91     [rect,axisdata] = gc(1:2)
92     xmn = rect(1);
93     ymn = rect(2);
94     xmx = rect(3);
95     ymx = rect(4); 
96     dx  = xmx-xmn;
97     dy  = ymx-ymn; 
98   end
99
100   // Set menus and callbacks
101   menu_d = ['Read','Save','Clear']
102   menu_e = ['Undo','Size','Replot','Ok','Abort']
103   menus  = list(['Edit','Data'],menu_e,menu_d)
104   w='menus(2)(';rpar=')'
105   Edit=w(ones(menu_e))+string(1:size(menu_e,'*'))+rpar(ones(menu_e))
106   w='menus(3)(';rpar=')'
107   Data=w(ones(menu_d))+string(1:size(menu_d,'*'))+rpar(ones(menu_d))
108
109   curwin = max(winsid())+1; 
110   scf(curwin) ;
111
112   //** Default layout is changed in Scilab 5 
113   //** unsetmenu(curwin,'File',1) // clear
114   //** unsetmenu(curwin,'File',2) // select
115   //** unsetmenu(curwin,'File',6) // load
116   //** unsetmenu(curwin,'File',7) // close
117   //** unsetmenu(curwin,'3D Rot.')
118
119   execstr('Edit_'+string(curwin)+'=Edit');
120   execstr('Data_'+string(curwin)+'=Data');
121   menubar(curwin,menus)
122   //
123   f = gcf(); a = gca();
124   a.data_bounds = [rect(1),rect(2);rect(3),rect(4)]
125   a.axes_visible='on';
126   a.grid=[4 4];
127   if x<>[] then
128     xpolys(x*[1 1],y*[1 1],[1,-1])
129     hdl=a.children.children
130   else
131     hdl=[]
132   end
133   
134   xtitle(tit(1),tit(2),tit(3));
135
136
137   // -- boucle principale
138   while %t then
139     [n1,n2] = size(x);
140     npt = n1*n2 ; 
141
142     [btn,xc,yc,win,Cmenu] = get_click();
143     
144     //** disp([btn,xc,yc,win]); //** DEBUG only 
145
146     c1 = [xc,yc];
147  
148     if Cmenu=="Quit" then Cmenu="Abort",end
149     if Cmenu==[]     then Cmenu="edit",end
150     if Cmenu=="Exit" then Cmenu="Ok",end
151     
152     select Cmenu
153     case [] then 
154       // ce n est pas un menu
155       break
156
157     case "Ok" then    //    -- ok menu 
158       rect = matrix(a.data_bounds',1,4);
159       gc   = list(rect,axisdata);
160       xdel(curwin);
161       return;
162
163     case "Abort" then //    -- abort menu
164       x = xsav
165       y = ysav
166       xdel(curwin)
167       ok = %f;
168       return
169
170     case "XClose" then //** the user manually close the win 
171       x = xsav
172       y = ysav
173       ok = %f;
174       return
175
176     case "Undo" then
177       if hdl<>[] then draw(hdl),end //erase
178       x=xs;y=ys
179       if x<>[] then hdl.data=[x y];draw(hdl);end
180
181     case "Size" then
182       while %t
183         [ok,xmn,xmx,ymn,ymx]=getvalue("Please input new limits",..
184                                       ['xmin';'xmax';'ymin';'ymax'],..
185                                       list('vec',1,'vec',1,'vec',1,'vec',1),..
186                                       string([xmn;xmx;ymn;ymx]))
187         if ~ok then break,end
188         if xmn>xmx|ymn>ymx then
189           x_message("Limits are not accettable")
190         else
191           break
192         end
193       end
194       if ok then
195         dx=xmx-xmn;dy=ymx-ymn
196         if dx==0 then dx=maxi(xmx/2,1),xmn=xmn-dx/10;xmx=xmx+dx/10;end
197         if dy==0 then dy=maxi(ymx/2,1),ymn=ymn-dy/5;ymx=ymx+dy/10;end
198         rect=[xmn,ymn,xmx,ymx];
199         a.data_bounds=[rect(1),rect(2);rect(3),rect(4)]
200       end
201
202     case "Grids" then //no more used
203       rep=x_mdialog('entrez les nouveaux nombres d''intervalles',..
204                     ['axe des x';'axe des y'],..
205                     string([axisdata(2);axisdata(4)]))
206       if rep<>[] then
207         rep=evstr(rep)
208         axisdata(2)=rep(1);axisdata(4)=rep(2);
209       end
210       
211     case "Clear" then
212       if hdl<>[] then delete(hdl),hdl=[];end
213       x=[];y=[];
214
215     case "Read" then
216       [x,y]=readxy()
217       mx=mini(prod(size(x)),prod(size(y)))
218       if mx<>0 then
219         xmx=maxi(x);xmn=mini(x)
220         ymx=maxi(y);ymn=mini(y)
221         dx=xmx-xmn;dy=ymx-ymn
222         if dx==0 then dx=maxi(xmx/2,1),xmn=xmn-dx/10;xmx=xmx+dx/10;end
223         if dy==0 then dy=maxi(ymx/2,1),ymn=ymn-dy/5;ymx=ymx+dy/10;end
224       else
225         xmn=0;ymn=0;xmx=1;ymx=1;dx=1;dy=1
226       end
227       rect=[xmn,ymn,xmx,ymx];
228       a.data_bounds=[rect(1),rect(2);rect(3),rect(4)]
229       if x<>[]&y<>[] then 
230         if hdl==[] then
231           xpolys(x(1)*[1 1],y(1)*[1 1],[1,-1])
232           hdl=gce();hdl=hdl.children
233         end
234         hdl.data=[x y];
235       else 
236         if hdl<>[] then delete(hdl),end
237         x=[];y=[];
238       end
239
240     case "Save" then
241       savexy(x,y)
242
243     case "Replot" then
244       draw(f)    
245
246     case "edit" then
247       npt=prod(size(x))
248       if npt<>0 then
249         dist=((x-ones(npt,1)*c1(1))/dx)^2+((y-ones(npt,1)*c1(2))/dy)^2
250         [m,k]=mini(dist);m=sqrt(m)
251       else
252         m=3*eps
253       end
254       if m<eps then                 //on deplace le point
255         xs=x;ys=y
256         [x,y]=movept(x,y)         
257       else                          
258         if add==1 then 
259           xs=x;ys=y                  //on rajoute un point de cassure
260           [x,y]=addpt(c1,x,y)
261         end
262       end
263     end
264   end
265 endfunction
266
267
268 function [btn,xc,yc,win,Cmenu] = get_click(flag)
269   //** 05/01/09 : update for Scilab 5.1: (close code is now -1000)     
270
271   if ~or(winsid()==curwin) then
272      Cmenu = "Quit";
273      return        ; 
274   end
275
276   if argn(2) == 1 then
277      [btn, xc, yc, win, str] = xclick(flag);
278   else
279      [btn, xc, yc, win, str] = xclick();
280   end
281
282   if btn == -1000 then //** user close the window [X]
283     if win == curwin then
284       Cmenu = "XClose";
285     else
286       Cmenu = "Open/Set";
287     end
288     return ; 
289   end
290
291   if btn == -2 then //** user select a dynamic menu 
292      xc = 0; yc = 0;
293      execstr('Cmenu=' + part(str, 9:length(str) - 1) );
294      execstr('Cmenu=' + Cmenu);
295      return; 
296   end
297
298   Cmenu = []; 
299
300 endfunction 
301
302
303 function [x,y] = addpt(c1,x,y)
304 // permet de rajouter un point de cassure
305   npt = prod(size(x))
306   c1 = c1'
307   if hdl==[] then
308     x = c1(1);
309     y = c1(2); 
310     xpolys(x*[1 1],y*[1 1],[1,-1]); 
311     hdl = resume(a.children(1).children)
312   end
313   //recherche des intervalles en x contenant l'abscisse designee
314   kk=[]
315   if npt>1 then
316     kk=find((x(1:npt-1)-c1(1)*ones(x(1:npt-1)))..
317             .*(x(2:npt)-c1(1)*ones(x(2:npt)))<=0)
318   end
319   if  kk<>[] then
320     //    recherche du segment sur le quel on a designe un point
321     pp=[];d=[];i=0
322     for k=kk
323       i=i+1
324       pr=projaff(x(k:k+1),y(k:k+1),c1)
325       if (x(k)-pr(1))*(x(k+1)-pr(1))<=0 then
326         pp=[pp pr]
327         d1=rect(3)-rect(1)
328         d2=rect(4)-rect(2)
329         d=[d norm([d1;d2].\(pr-c1))]
330       end
331     end
332     if d<>[] then
333       [m,i]=mini(d)
334       if m<eps
335         k=kk(i)
336         pp=pp(:,i)
337         x=x([1:k k:npt]);x(k+1)=pp(1);
338         y=y([1:k k:npt]);y(k+1)=pp(2);
339         hdl;drawlater();hdl.data=[x y];draw(hdl)
340         return
341       end
342     end
343   end
344   d1=rect(3)-rect(1)
345   d2=rect(4)-rect(2)
346   if norm([d1;d2].\([x(1);y(1)]-c1))<norm([d1;d2].\([x(npt);y(npt)]-c1)) then
347     //  -- mise a jour de x et y
348     x(2:npt+1)=x;x(1)=c1(1)
349     y(2:npt+1)=y;y(1)=c1(2)
350   else
351     //  -- mise a jour de x et y
352     x(npt+1)=c1(1)
353     y(npt+1)=c1(2)
354   end
355   hdl;drawlater();hdl.data=[x y];draw(hdl)
356 endfunction
357
358 function [x,y]=movept(x,y)
359 //on bouge un point existant
360   hdl;
361   //** f;f.pixmap='on';
362   rep(3)=-1
363   while rep(3)==-1 do
364     rep = xgetmouse();
365     xc=rep(1);yc=rep(2);c2=[xc;yc]
366     if modx==0 then c2(1)=x(k);end
367     if mody==0 then c2(2)=y(k);end
368     x(k)=c2(1);y(k)=c2(2)
369     hdl.data=[x,y];
370     //** show_pixmap();
371     drawnow()
372   end
373   //** f.pixmap='off';
374 endfunction
375
376
377 function [x,y] = readxy()
378   fn=uigetfile('*.xy')
379   if fn<>emptystr() then 
380     if execstr('load(fn)','errcatch')<>0 then
381       xy=read(fn,-1,2)
382       x=xy(:,1);y=xy(:,2)
383     else
384       x=xy(:,1);y=xy(:,2)
385     end
386   else
387     x=x
388     y=y
389   end
390
391 endfunction
392
393
394 function savexy(x,y)
395   fn = uigetfile('*.xy')
396   if fn<>emptystr()  then 
397     xy = [x y];
398     fil=fn+'.xy'
399     if execstr('save(fil,xy)','errcatch')<>0 then
400       x_message(["Impossible to save in the selected file";
401                  "Check file and directory access"])
402       return
403     end
404   end
405 endfunction