Add new headers.
[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   //in line definition of get_click
47   deff('[btn,xc,yc,win,Cmenu]=get_click(flag)',[
48       'if ~or(winsid() == curwin) then   Cmenu = ''Quit'';return,end,';
49       'if argn(2) == 1 then';
50       '  [btn, xc, yc, win, str] = xclick(flag);';
51       'else';
52       '  [btn, xc, yc, win, str] = xclick();';
53       'end';
54       'if btn == -100 then';
55       '  if win == curwin then';
56       '    Cmenu = ''Quit'';';
57       '  else';
58       '    Cmenu = ''Open/Set'';';
59       '  end,';
60       '  return,';
61       'end';
62       'if btn == -2 then';
63       '  xc = 0;yc = 0;';
64       '  execstr(''Cmenu='' + part(str, 9:length(str) - 1));';
65       '  execstr(''Cmenu='' + Cmenu);';
66       '  return,';
67       'end';
68       'Cmenu=[]'])
69   
70
71
72   ok=%t
73   if rhs==0 then x=[];y=[],end;
74   if rhs==1 then y=x;x=(1:size(y,'*'))',end
75   if rhs<3  then job='axy',end
76   if rhs<4 then tit=[' ',' ',' '],end
77   if size(tit,'*')<3 then tit(3)=' ',end
78   //
79   [mx,nx]=size(x);x=x(:)
80   [my,ny]=size(y);y=y(:)
81   n=min(mx*nx,my*ny)
82   x=x(1:n);y=y(1:n);
83   xsav=x;ysav=y;xs=x;ys=y;
84   //
85   lj=length(job)
86   add=0;modx=0;mody=0
87   for k=1:lj
88     jk=part(job,k)
89     select jk
90     case 'a' then add=1,
91     case 'x' then modx=1
92     case 'y' then mody=1
93     else error('parametre job incorrect')
94     end
95   end
96   eps=0.03
97   symbsiz=0.2
98   // bornes initiales du graphique
99   if rhs<5 then
100     if mx<>0 then
101       xmx=maxi(x);xmn=mini(x)
102       ymx=maxi(y);ymn=mini(y)
103       dx=xmx-xmn;dy=ymx-ymn
104       if dx==0 then dx=maxi(xmx/2,1),end
105       xmn=xmn-dx/10;xmx=xmx+dx/10
106       if dy==0 then dy=maxi(ymx/2,1),end;
107       ymn=ymn-dy/10;ymx=ymx+dy/10;
108     else
109       xmn=0;ymn=0;xmx=1;ymx=1;dx=1;dy=1
110     end
111     rect=[xmn,ymn,xmx,ymx];
112     axisdata=[2 10 2 10]
113   else
114     [rect,axisdata]=gc(1:2)
115     xmn=rect(1);ymn=rect(2);xmx=rect(3);ymx=rect(4)
116     dx=xmx-xmn;dy=ymx-ymn
117   end
118
119   // Set menus and callbacks
120   menu_d=['Read','Save','Clear']
121   menu_e=['Undo','Size','Replot','Ok','Abort']
122   menus=list(['Edit','Data'],menu_e,menu_d)
123   w='menus(2)(';rpar=')'
124   Edit=w(ones(menu_e))+string(1:size(menu_e,'*'))+rpar(ones(menu_e))
125   w='menus(3)(';rpar=')'
126   Data=w(ones(menu_d))+string(1:size(menu_d,'*'))+rpar(ones(menu_d))
127
128   curwin=max(winsid())+1
129   xset('window',curwin)
130   xselect()
131
132   unsetmenu(curwin,'File',1) //clear
133   unsetmenu(curwin,'File',2) //select
134   unsetmenu(curwin,'File',6) //load
135   unsetmenu(curwin,'File',7) //close
136   unsetmenu(curwin,'3D Rot.')
137   //
138   execstr('Edit_'+string(curwin)+'=Edit')
139   execstr('Data_'+string(curwin)+'=Data')
140   menubar(curwin,menus)
141   //
142   f=gcf();a=gca();
143   a.data_bounds=[rect(1),rect(2);rect(3),rect(4)]
144   a.axes_visible='on';
145   a.grid=[4 4];
146   if x<>[] then
147     xpolys(x*[1 1],y*[1 1],[1,-1])
148     hdl=a.children.children
149   else
150     hdl=[]
151   end
152   
153   xtitle(tit(1),tit(2),tit(3));
154
155
156   // -- boucle principale
157   while %t then
158     [n1,n2]=size(x);npt=n1*n2
159     [btn,xc,yc,win,Cmenu]=get_click()
160     c1=[xc,yc]
161     if Cmenu=='Quit' then Cmenu='Abort',end
162     if Cmenu==[] then Cmenu='edit',end
163     if Cmenu=='Exit' then Cmenu='Ok',end
164     select Cmenu
165     case [] then 
166       //ce n est pas un menu
167       break
168     case 'Ok' then    //    -- ok menu
169       rect=matrix(a.data_bounds',1,4)
170       gc=list(rect,axisdata)
171
172       xdel(curwin)
173       return
174     case 'Abort' then //    -- abort menu
175       x=xsav
176       y=ysav
177       xdel(curwin)
178       ok=%f
179       return
180     case 'Undo' then
181       if hdl<>[] then draw(hdl),end //erase
182       x=xs;y=ys
183       if x<>[] then hdl.data=[x y];draw(hdl);end
184     case 'Size' then
185       while %t
186         [ok,xmn,xmx,ymn,ymx]=getvalue('entrez les nouvelles bornes',..
187                                       ['xmin';'xmax';'ymin';'ymax'],..
188                                       list('vec',1,'vec',1,'vec',1,'vec',1),..
189                                       string([xmn;xmx;ymn;ymx]))
190         if ~ok then break,end
191         if xmn>xmx|ymn>ymx then
192           x_message('Les bornes sont incorrectes')
193         else
194           break
195         end
196       end
197       if ok then
198         dx=xmx-xmn;dy=ymx-ymn
199         if dx==0 then dx=maxi(xmx/2,1),xmn=xmn-dx/10;xmx=xmx+dx/10;end
200         if dy==0 then dy=maxi(ymx/2,1),ymn=ymn-dy/5;ymx=ymx+dy/10;end
201         rect=[xmn,ymn,xmx,ymx];
202         a.data_bounds=[rect(1),rect(2);rect(3),rect(4)]
203       end
204     case 'Grids' then //no more used
205       rep=x_mdialog('entrez les nouveaux nombres d''intervalles',..
206                     ['axe des x';'axe des y'],..
207                     string([axisdata(2);axisdata(4)]))
208       if rep<>[] then
209         rep=evstr(rep)
210         axisdata(2)=rep(1);axisdata(4)=rep(2);
211       end
212       
213     case 'Clear' then
214       if hdl<>[] then delete(hdl),hdl=[];end
215       x=[];y=[];
216     case 'Read' then
217       [x,y]=readxy()
218       mx=mini(prod(size(x)),prod(size(y)))
219       if mx<>0 then
220         xmx=maxi(x);xmn=mini(x)
221         ymx=maxi(y);ymn=mini(y)
222         dx=xmx-xmn;dy=ymx-ymn
223         if dx==0 then dx=maxi(xmx/2,1),xmn=xmn-dx/10;xmx=xmx+dx/10;end
224         if dy==0 then dy=maxi(ymx/2,1),ymn=ymn-dy/5;ymx=ymx+dy/10;end
225       else
226         xmn=0;ymn=0;xmx=1;ymx=1;dx=1;dy=1
227       end
228       rect=[xmn,ymn,xmx,ymx];
229       a.data_bounds=[rect(1),rect(2);rect(3),rect(4)]
230       if x<>[]&y<>[] then 
231         if hdl==[] then
232           xpolys(x(1)*[1 1],y(1)*[1 1],[1,-1])
233           hdl=gce();hdl=hdl.children
234         end
235         hdl.data=[x y];
236       else 
237         if hdl<>[] then delete(hdl),end
238         x=[];y=[];
239       end
240     case 'Save' then
241       savexy(x,y)
242     case 'Replot' then
243       draw(f)    
244     case 'edit' then
245       npt=prod(size(x))
246       if npt<>0 then
247         dist=((x-ones(npt,1)*c1(1))/dx)^2+((y-ones(npt,1)*c1(2))/dy)^2
248         [m,k]=mini(dist);m=sqrt(m)
249       else
250         m=3*eps
251       end
252       if m<eps then                 //on deplace le point
253         xs=x;ys=y
254         [x,y]=movept(x,y)         
255       else                          
256         if add==1 then 
257           xs=x;ys=y                  //on rajoute un point de cassure
258           [x,y]=addpt(c1,x,y)
259         end
260       end
261     end
262   end
263 endfunction
264
265 function [x,y]=addpt(c1,x,y)
266 //permet de rajouter un point de cassure
267   npt=prod(size(x))
268   c1=c1'
269   if hdl==[] then
270     x=c1(1);y=c1(2)
271     xpolys(x*[1 1],y*[1 1],[1,-1])
272     hdl=resume(a.children(1).children)
273   end
274   //recherche des intervalles en x contenant l'abscisse designee
275   kk=[]
276   if npt>1 then
277     kk=find((x(1:npt-1)-c1(1)*ones(x(1:npt-1)))..
278             .*(x(2:npt)-c1(1)*ones(x(2:npt)))<=0)
279   end
280   if  kk<>[] then
281     //    recherche du segment sur le quel on a designe un point
282     pp=[];d=[];i=0
283     for k=kk
284       i=i+1
285       pr=projaff(x(k:k+1),y(k:k+1),c1)
286       if (x(k)-pr(1))*(x(k+1)-pr(1))<=0 then
287         pp=[pp pr]
288         d1=rect(3)-rect(1)
289         d2=rect(4)-rect(2)
290         d=[d norm([d1;d2].\(pr-c1))]
291       end
292     end
293     if d<>[] then
294       [m,i]=mini(d)
295       if m<eps
296         k=kk(i)
297         pp=pp(:,i)
298         x=x([1:k k:npt]);x(k+1)=pp(1);
299         y=y([1:k k:npt]);y(k+1)=pp(2);
300         hdl;drawlater();hdl.data=[x y];draw(hdl)
301         return
302       end
303     end
304   end
305   d1=rect(3)-rect(1)
306   d2=rect(4)-rect(2)
307   if norm([d1;d2].\([x(1);y(1)]-c1))<norm([d1;d2].\([x(npt);y(npt)]-c1)) then
308     //  -- mise a jour de x et y
309     x(2:npt+1)=x;x(1)=c1(1)
310     y(2:npt+1)=y;y(1)=c1(2)
311   else
312     //  -- mise a jour de x et y
313     x(npt+1)=c1(1)
314     y(npt+1)=c1(2)
315   end
316   hdl;drawlater();hdl.data=[x y];draw(hdl)
317 endfunction
318
319 function [x,y]=movept(x,y)
320 //on bouge un point existant
321   hdl;
322   f;f.pixmap='on';
323   rep(3)=-1
324   while rep(3)==-1 do
325     rep=xgetmouse()
326     xc=rep(1);yc=rep(2);c2=[xc;yc]
327     if modx==0 then c2(1)=x(k);end
328     if mody==0 then c2(2)=y(k);end
329     x(k)=c2(1);y(k)=c2(2)
330     hdl.data=[x,y];
331     show_pixmap();drawnow()
332   end
333   f.pixmap='off';
334 endfunction
335
336
337 function [x,y]=readxy()
338   fn=xgetfile('*.xy')
339   if fn<>emptystr() then 
340     if execstr('load(fn)','errcatch')<>0 then
341       xy=read(fn,-1,2)
342       x=xy(:,1);y=xy(:,2)
343     else
344       x=xy(:,1);y=xy(:,2)
345     end
346   else
347     x=x
348     y=y
349   end
350
351 endfunction
352
353 function savexy(x,y)
354   fn=xgetfile('*.xy')
355   if fn<>emptystr()  then 
356     xy=[x y];
357     fil=fn+'.xy'
358     if execstr('save(fil,xy)','errcatch')<>0 then
359       x_message(['Impossible to save in the selected file';
360                  'Check file and directory access'])
361       return
362     end
363   end
364 endfunction