*Bug #12433 fixed- show_pixmap() has been removed in Scilab files.
[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(msprintf(gettext("%s: Wrong value for input argument #%d: Must be in the set {%s}.\n"), "edit_curv", 3, "a, x, y"));
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 = max(x); xmn = min(x)
78             ymx = max(y); ymn = min(y)
79             dx = xmx-xmn;  dy = ymx-ymn
80             if dx==0 then dx=max(xmx/2,1),end
81             xmn=xmn-dx/10;xmx=xmx+dx/10
82             if dy==0 then dy=max(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 hdl.visible = "on";end //erase
178             x=xs;y=ys
179             if x<>[] then hdl.data=[x y];hdl.visible = "on";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                     messagebox("Limits are not accettable","modal");
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=max(xmx/2,1),xmn=xmn-dx/10;xmx=xmx+dx/10;end
197                 if dy==0 then dy=max(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=min(prod(size(x)),prod(size(y)))
218             if mx<>0 then
219                 xmx=max(x);xmn=min(x)
220                 ymx=max(y);ymn=min(y)
221                 dx=xmx-xmn;dy=ymx-ymn
222                 if dx==0 then dx=max(xmx/2,1),xmn=xmn-dx/10;xmx=xmx+dx/10;end
223                 if dy==0 then dy=max(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]=min(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]=min(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];hdl.visible = "on"; drawnow();
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];hdl.visible = "on"; drawnow();
356 endfunction
357
358 function [x,y]=movept(x,y)
359     //on bouge un point existant
360     hdl;
361     rep(3)=-1
362     while rep(3)==-1 do
363         rep = xgetmouse();
364         xc=rep(1);yc=rep(2);c2=[xc;yc]
365         if modx==0 then c2(1)=x(k);end
366         if mody==0 then c2(2)=y(k);end
367         x(k)=c2(1);y(k)=c2(2)
368         hdl.data=[x,y];
369         drawnow()
370     end
371 endfunction
372
373
374 function [x,y] = readxy()
375     fn=uigetfile("*.xy")
376     if fn<>emptystr() then
377         if execstr("load(fn)","errcatch")<>0 then
378             xy=read(fn,-1,2)
379             x=xy(:,1);y=xy(:,2)
380         else
381             x=xy(:,1);y=xy(:,2)
382         end
383     else
384         x=x
385         y=y
386     end
387
388 endfunction
389
390
391 function savexy(x,y)
392     fn = uigetfile("*.xy")
393     if fn<>emptystr()  then
394         xy = [x y];
395         fil=fn+".xy"
396         if execstr("save(fil,xy)","errcatch")<>0 then
397             messagebox(["Impossible to save in the selected file";
398             "Check file and directory access"],"modal");
399             return
400         end
401     end
402 endfunction