1 /*
2  * $Id: oagrid.c,v 1.4 2002/07/06 08:51:42 isizaka Exp isizaka $
3  *
4  * This file is part of "Ngraph for X11".
5  *
6  * Copyright (C) 2002, Satoshi ISHIZAKA. isizaka@msa.biglobe.ne.jp
7  *
8  * "Ngraph for X11" is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * "Ngraph for X11" is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21  *
22  */
23 
24 /**
25  *
26  * $Log: oagrid.c,v $
27  * Revision 1.4  2002/07/06 08:51:42  isizaka
28  * change to GPL.
29  *
30  * Revision 1.3  2001/03/23 12:15:31  isizaka
31  * for 6.3.13
32  *
33  * Revision 1.2  1999/04/15 12:15:27  isizaka
34  * for release 6.03.01
35  *
36  * Revision 1.1  1999/03/17 13:46:09  isizaka
37  * Initial revision
38  *
39  *
40  **/
41 
42 #include <math.h>
43 #include <string.h>
44 #include <stdio.h>
45 #include "ngraph.h"
46 #include "object.h"
47 #include "mathfn.h"
48 #include "gra.h"
49 #include "axis.h"
50 #include "oroot.h"
51 #include "odraw.h"
52 
53 #define NAME "axisgrid"
54 #define PARENT "draw"
55 #define VERSION  "1.00.00"
56 #define TRUE  1
57 #define FALSE 0
58 
59 #define ERRNUM 3
60 
61 #define ERRNOAXISINST 100
62 #define ERRMINMAX 101
63 #define ERRAXISDIR 102
64 
65 char *agriderrorlist[ERRNUM]={
66   "no instance for axis",
67   "illegal axis min/max.",
68   "illegal axis direction.",
69 };
70 
agridinit(struct objlist * obj,char * inst,char * rval,int argc,char ** argv)71 int agridinit(struct objlist *obj,char *inst,char *rval,int argc,char **argv)
72 {
73   int wid1,wid2,wid3,dot;
74   int r,g,b,br,bg,bb;
75   struct narray *style1;
76 
77   if (_exeparent(obj,(char *)argv[1],inst,rval,argc,argv)) return 1;
78   wid1=5;
79   wid2=10;
80   wid3=20;
81   r=0;
82   g=255;
83   b=255;
84   br=255;
85   bg=255;
86   bb=255;
87   style1=arraynew(sizeof(int));
88   dot=150;
89   arrayadd(style1,&dot);
90   arrayadd(style1,&dot);
91   if (_putobj(obj,"width1",inst,&wid1)) return 1;
92   if (_putobj(obj,"width2",inst,&wid2)) return 1;
93   if (_putobj(obj,"width3",inst,&wid3)) return 1;
94   if (_putobj(obj,"style1",inst,style1)) return 1;
95   if (_putobj(obj,"R",inst,&r)) return 1;
96   if (_putobj(obj,"G",inst,&g)) return 1;
97   if (_putobj(obj,"B",inst,&b)) return 1;
98   if (_putobj(obj,"BR",inst,&br)) return 1;
99   if (_putobj(obj,"BG",inst,&bg)) return 1;
100   if (_putobj(obj,"BB",inst,&bb)) return 1;
101   return 0;
102 }
103 
104 
agriddone(struct objlist * obj,char * inst,char * rval,int argc,char ** argv)105 int agriddone(struct objlist *obj,char *inst,char *rval,int argc,char **argv)
106 {
107   if (_exeparent(obj,(char *)argv[1],inst,rval,argc,argv)) return 1;
108   return 0;
109 }
110 
agriddraw(struct objlist * obj,char * inst,char * rval,int argc,char ** argv)111 int agriddraw(struct objlist *obj,char *inst,char *rval,int argc,char **argv)
112 {
113   int GC;
114   int fr,fg,fb,br,bg,bb,lm,tm,w,h;
115   char *axisx,*axisy;
116   int wid1,wid2,wid3,wid;
117   struct narray *st1,*st2,*st3;
118   int snum,*sdata,snum1,snum2,snum3,*sdata1,*sdata2,*sdata3;
119   struct narray iarray;
120   struct objlist *aobj;
121   int anum,id;
122   char *inst1;
123   int axposx,axposy,ayposx,ayposy,axdir,aydir,dirx,diry,axlen,aylen;
124   double axmin,axmax,aymin,aymax,axinc,ayinc,dir;
125   int axdiv,aydiv,axtype,aytype;
126   struct axislocal alocal;
127   int rcode,gx0,gy0,gx1,gy1,x0,y0,x1,y1;
128   double po,minx,miny,maxx,maxy;
129   int clip,zoom,back;
130   char *raxis;
131 
132   if (_exeparent(obj,(char *)argv[1],inst,rval,argc,argv)) return 1;
133   _getobj(obj,"GC",inst,&GC);
134   if (GC<0) return 0;
135   _getobj(obj,"R",inst,&fr);
136   _getobj(obj,"G",inst,&fg);
137   _getobj(obj,"B",inst,&fb);
138   _getobj(obj,"axis_x",inst,&axisx);
139   _getobj(obj,"axis_y",inst,&axisy);
140   _getobj(obj,"width1",inst,&wid1);
141   _getobj(obj,"style1",inst,&st1);
142   _getobj(obj,"width2",inst,&wid2);
143   _getobj(obj,"style2",inst,&st2);
144   _getobj(obj,"width3",inst,&wid3);
145   _getobj(obj,"style3",inst,&st3);
146   _getobj(obj,"clip",inst,&clip);
147   _getobj(obj,"background",inst,&back);
148   _getobj(obj,"BR",inst,&br);
149   _getobj(obj,"BG",inst,&bg);
150   _getobj(obj,"BB",inst,&bb);
151   snum1=arraynum(st1);
152   sdata1=arraydata(st1);
153   snum2=arraynum(st2);
154   sdata2=arraydata(st2);
155   snum3=arraynum(st3);
156   sdata3=arraydata(st3);
157 
158   if (axisx==NULL) {
159     return 0;
160   } else {
161     arrayinit(&iarray,sizeof(int));
162     if (getobjilist(axisx,&aobj,&iarray,FALSE,NULL)) return 1;
163     anum=arraynum(&iarray);
164     if (anum<1) {
165       arraydel(&iarray);
166       error2(obj,ERRNOAXISINST,axisx);
167       return 1;
168     }
169     id=*(int *)arraylast(&iarray);
170     arraydel(&iarray);
171     if ((inst1=getobjinst(aobj,id))==NULL) return 1;
172     if (_getobj(aobj,"x",inst1,&axposx)) return 1;
173     if (_getobj(aobj,"y",inst1,&axposy)) return 1;
174     if (_getobj(aobj,"length",inst1,&axlen)) return 1;
175     if (_getobj(aobj,"direction",inst1,&dirx)) return 1;
176     if (_getobj(aobj,"min",inst1,&axmin)) return 1;
177     if (_getobj(aobj,"max",inst1,&axmax)) return 1;
178     if (_getobj(aobj,"inc",inst1,&axinc)) return 1;
179     if (_getobj(aobj,"div",inst1,&axdiv)) return 1;
180     if (_getobj(aobj,"type",inst1,&axtype)) return 1;
181     if ((axmin==0) && (axmax==0) && (axinc==0)) {
182       if (_getobj(aobj,"reference",inst1,&raxis)) return 1;
183       if (raxis!=NULL) {
184         arrayinit(&iarray,sizeof(int));
185         if (!getobjilist(raxis,&aobj,&iarray,FALSE,NULL)) {
186           anum=arraynum(&iarray);
187           if (anum>0) {
188             id=*(int *)arraylast(&iarray);
189             arraydel(&iarray);
190             if ((anum>0) && ((inst1=getobjinst(aobj,id))!=NULL)) {
191               _getobj(aobj,"min",inst1,&axmin);
192               _getobj(aobj,"max",inst1,&axmax);
193               _getobj(aobj,"inc",inst1,&axinc);
194               _getobj(aobj,"div",inst1,&axdiv);
195               _getobj(aobj,"type",inst1,&axtype);
196             }
197           }
198         }
199       }
200     }
201     if ((dirx%9000)!=0) {
202       error(obj,ERRAXISDIR);
203       return 1;
204     }
205     axdir=dirx/9000;
206     if (axmin!=axmax) {
207       if (axtype==1) {
208         minx=log10(axmin);
209         maxx=log10(axmax);
210       } else if (axtype==2) {
211         minx=1/axmin;
212         maxx=1/axmax;
213       } else {
214         minx=axmin;
215         maxx=axmax;
216       }
217     }
218   }
219   if (axisy==NULL) {
220     return 0;
221   } else {
222     arrayinit(&iarray,sizeof(int));
223     if (getobjilist(axisy,&aobj,&iarray,FALSE,NULL)) return 1;
224     anum=arraynum(&iarray);
225     if (anum<1) {
226       arraydel(&iarray);
227       error2(obj,ERRNOAXISINST,axisy);
228       return 1;
229     }
230     id=*(int *)arraylast(&iarray);
231     arraydel(&iarray);
232     if ((inst1=getobjinst(aobj,id))==NULL) return 1;
233     if (_getobj(aobj,"x",inst1,&ayposx)) return 1;
234     if (_getobj(aobj,"y",inst1,&ayposy)) return 1;
235     if (_getobj(aobj,"length",inst1,&aylen)) return 1;
236     if (_getobj(aobj,"direction",inst1,&diry)) return 1;
237     if (_getobj(aobj,"min",inst1,&aymin)) return 1;
238     if (_getobj(aobj,"max",inst1,&aymax)) return 1;
239     if (_getobj(aobj,"inc",inst1,&ayinc)) return 1;
240     if (_getobj(aobj,"div",inst1,&aydiv)) return 1;
241     if (_getobj(aobj,"type",inst1,&aytype)) return 1;
242     if ((aymin==0) && (aymax==0) && (ayinc==0)) {
243       if (_getobj(aobj,"reference",inst1,&raxis)) return 1;
244       if (raxis!=NULL) {
245         arrayinit(&iarray,sizeof(int));
246         if (!getobjilist(raxis,&aobj,&iarray,FALSE,NULL)) {
247           anum=arraynum(&iarray);
248           if (anum>0) {
249             id=*(int *)arraylast(&iarray);
250             arraydel(&iarray);
251             if ((anum>0) && ((inst1=getobjinst(aobj,id))!=NULL)) {
252               _getobj(aobj,"min",inst1,&aymin);
253               _getobj(aobj,"max",inst1,&aymax);
254               _getobj(aobj,"inc",inst1,&ayinc);
255               _getobj(aobj,"div",inst1,&aydiv);
256               _getobj(aobj,"type",inst1,&aytype);
257             }
258           }
259         }
260       }
261     }
262     if ((diry%9000)!=0) {
263       error(obj,ERRAXISDIR);
264       return 1;
265     }
266     aydir=diry/9000;
267     if (aymin!=aymax) {
268       if (aytype==1) {
269         miny=log10(aymin);
270         maxy=log10(aymax);
271       } else if (aytype==2) {
272         miny=1/aymin;
273         maxy=1/aymax;
274       } else {
275         miny=aymin;
276         maxy=aymax;
277       }
278     }
279   }
280   if (((axdir+aydir)%2)==0) {
281     error(obj,ERRAXISDIR);
282     return 1;
283   }
284 
285   GRAregion(GC,&lm,&tm,&w,&h,&zoom);
286   GRAview(GC,0,0,w*10000.0/zoom,h*10000.0/zoom,clip);
287   if (back) {
288     GRAcolor(GC,br,bg,bb);
289     dir=dirx/18000.0*MPI;
290     gx0=axposx;
291     gx1=axposx;
292     x1=axposx+nround(axlen*cos(dir));
293     if (x1<gx0) gx0=x1;
294     if (x1>gx1) gx1=x1;
295     gy0=axposy;
296     gy1=axposy;
297     y1=axposy-nround(axlen*sin(dir));
298     if (y1<gy0) gy0=y1;
299     if (y1>gy1) gy1=y1;
300     dir=diry/18000.0*MPI;
301     x1=ayposx;
302     if (x1<gx0) gx0=x1;
303     if (x1>gx1) gx1=x1;
304     x1=ayposx+nround(aylen*cos(dir));
305     if (x1<gx0) gx0=x1;
306     if (x1>gx1) gx1=x1;
307     y1=ayposy;
308     if (y1<gy0) gy0=y1;
309     if (y1>gy1) gy1=y1;
310     y1=ayposy-nround(aylen*sin(dir));
311     if (y1<gy0) gy0=y1;
312     if (y1>gy1) gy1=y1;
313     GRArectangle(GC,gx0,gy0,gx1,gy1,1);
314   }
315   if ((axmin==axmax) || (aymin==aymax)) goto exit;
316   GRAcolor(GC,fr,fg,fb);
317 
318   if (getaxispositionini(&alocal,axtype,axmin,axmax,axinc,axdiv,TRUE)!=0) {
319     error(obj,ERRMINMAX);
320     goto exit;
321   }
322   while ((rcode=getaxisposition(&alocal,&po))!=-2) {
323     if (rcode>=1) {
324       if (rcode==1) {
325         snum=snum1;
326         sdata=sdata1;
327         wid=wid1;
328       } else if (rcode==2) {
329         snum=snum2;
330         sdata=sdata2;
331         wid=wid2;
332       } else {
333         snum=snum3;
334         sdata=sdata3;
335         wid=wid3;
336       }
337       if (wid!=0) {
338         GRAlinestyle(GC,snum,sdata,wid,0,0,1000);
339         if (axdir==0) gx0=axposx+(po-minx)*axlen/(maxx-minx);
340         else if (axdir==1) gy0=axposy-(po-minx)*axlen/(maxx-minx);
341         else if (axdir==2) gx0=axposx-(po-minx)*axlen/(maxx-minx);
342         else gy0=axposy+(po-minx)*axlen/(maxx-minx);
343         if (aydir==0) {
344           x0=ayposx;
345           y0=gy0;
346           x1=ayposx+aylen;
347           y1=gy0;
348         } else if (aydir==1) {
349           x0=gx0;
350           y0=ayposy;
351           x1=gx0;
352           y1=ayposy-aylen;
353         } else if (aydir==2) {
354           x0=ayposx;
355           y0=gy0;
356           x1=ayposx-aylen;
357           y1=gy0;
358         } else {
359           x0=ayposx;
360           y0=gy0;
361           x1=ayposx-aylen;
362           y1=gy0;
363         }
364         GRAline(GC,x0,y0,x1,y1);
365       }
366     }
367   }
368   if (getaxispositionini(&alocal,aytype,aymin,aymax,ayinc,aydiv,TRUE)!=0) {
369     error(obj,ERRMINMAX);
370     goto exit;
371   }
372   while ((rcode=getaxisposition(&alocal,&po))!=-2) {
373     if (rcode>=1) {
374       if (rcode==1) {
375         snum=snum1;
376         sdata=sdata1;
377         wid=wid1;
378       } else if (rcode==2) {
379         snum=snum2;
380         sdata=sdata2;
381         wid=wid2;
382       } else {
383         snum=snum3;
384         sdata=sdata3;
385         wid=wid3;
386       }
387       if (wid!=0) {
388         GRAlinestyle(GC,snum,sdata,wid,0,0,1000);
389         if (aydir==0) gx0=ayposx+(po-miny)*aylen/(maxy-miny);
390         else if (aydir==1) gy0=ayposy-(po-miny)*aylen/(maxy-miny);
391         else if (aydir==2) gx0=ayposx-(po-miny)*aylen/(maxy-miny);
392         else gy0=ayposy+(po-miny)*aylen/(maxy-miny);
393         if (axdir==0) {
394           x0=axposx;
395           y0=gy0;
396           x1=axposx+axlen;
397           y1=gy0;
398         } else if (axdir==1) {
399           x0=gx0;
400           y0=axposy;
401           x1=gx0;
402           y1=axposy-axlen;
403         } else if (axdir==2) {
404           x0=axposx;
405           y0=gy0;
406           x1=axposx-axlen;
407           y1=gy0;
408         } else {
409           x0=axposx;
410           y0=gy0;
411           x1=axposx-axlen;
412           y1=gy0;
413         }
414         GRAline(GC,x0,y0,x1,y1);
415       }
416     }
417   }
418 exit:
419   GRAaddlist(GC,obj,inst,(char *)argv[0],(char *)argv[1]);
420   return 0;
421 }
422 
agridtight(struct objlist * obj,char * inst,char * rval,int argc,char ** argv)423 int agridtight(struct objlist *obj,char *inst,char *rval,
424                int argc,char **argv)
425 {
426   char *axis,*axis2;
427   struct narray iarray;
428   int anum,id,oid;
429   struct objlist *aobj;
430 
431   if ((!_getobj(obj,"axis_x",inst,&axis)) && (axis!=NULL)) {
432     arrayinit(&iarray,sizeof(int));
433     if (!getobjilist(axis,&aobj,&iarray,FALSE,NULL)) {
434       anum=arraynum(&iarray);
435       if (anum>0) {
436         id=*(int *)arraylast(&iarray);
437         if (getobj(aobj,"oid",id,0,NULL,&oid)!=-1) {
438           if ((axis2=(char *)memalloc(strlen(chkobjectname(aobj))+10))!=NULL) {
439             sprintf(axis2,"%s:^%d",chkobjectname(aobj),oid);
440             _putobj(obj,"axis_x",inst,axis2);
441             memfree(axis);
442           }
443         }
444       }
445     }
446     arraydel(&iarray);
447   }
448   if ((!_getobj(obj,"axis_y",inst,&axis)) && (axis!=NULL)) {
449     arrayinit(&iarray,sizeof(int));
450     if (!getobjilist(axis,&aobj,&iarray,FALSE,NULL)) {
451       anum=arraynum(&iarray);
452       if (anum>0) {
453         id=*(int *)arraylast(&iarray);
454         if (getobj(aobj,"oid",id,0,NULL,&oid)!=-1) {
455           if ((axis2=(char *)memalloc(strlen(chkobjectname(aobj))+10))!=NULL) {
456             sprintf(axis2,"%s:^%d",chkobjectname(aobj),oid);
457             _putobj(obj,"axis_y",inst,axis2);
458             memfree(axis);
459           }
460         }
461       }
462     }
463     arraydel(&iarray);
464   }
465   return 0;
466 }
467 
468 #define TBLNUM 17
469 
470 struct objtable agrid[TBLNUM] = {
471   {"init",NVFUNC,NEXEC,agridinit,NULL,0},
472   {"done",NVFUNC,NEXEC,agriddone,NULL,0},
473   {"next",NPOINTER,0,NULL,NULL,0},
474   {"axis_x",NOBJ,NREAD|NWRITE,NULL,NULL,0},
475   {"axis_y",NOBJ,NREAD|NWRITE,NULL,NULL,0},
476   {"width1",NINT,NREAD|NWRITE,oputabs,NULL,0},
477   {"style1",NIARRAY,NREAD|NWRITE,NULL,NULL,0},
478   {"width2",NINT,NREAD|NWRITE,oputabs,NULL,0},
479   {"style2",NIARRAY,NREAD|NWRITE,NULL,NULL,0},
480   {"width3",NINT,NREAD|NWRITE,oputabs,NULL,0},
481   {"style3",NIARRAY,NREAD|NWRITE,NULL,NULL,0},
482   {"background",NBOOL,NREAD|NWRITE,NULL,NULL,0},
483   {"BR",NINT,NREAD|NWRITE,NULL,NULL,0},
484   {"BG",NINT,NREAD|NWRITE,NULL,NULL,0},
485   {"BB",NINT,NREAD|NWRITE,NULL,NULL,0},
486   {"draw",NVFUNC,NREAD|NEXEC,agriddraw,"i",0},
487   {"tight",NVFUNC,NREAD|NEXEC,agridtight,NULL,0},
488 };
489 
addagrid()490 void *addagrid()
491 {
492   return addobject(NAME,NULL,PARENT,VERSION,TBLNUM,agrid,ERRNUM,agriderrorlist,NULL,NULL);
493 }
494