/* @(#)ag_axis.c 17.1.1.1 (ES0-DMD) 01/25/02 17:33:29 */ /*=========================================================================== Copyright (C) 1995 European Southern Observatory (ESO) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Massachusetss Ave, Cambridge, MA 02139, USA. Corresponding concerning ESO-MIDAS should be addressed as follows: Internet e-mail: midas@eso.org Postal address: European Southern Observatory Data Management Division Karl-Schwarzschild-Strasse 2 D 85748 Garching bei Muenchen GERMANY ===========================================================================*/ /* @(#)ag_axis.c 17.1.1.1 (OAA-ASTRONET) 01/25/02 17:33:29 /* * HEADER : ag_axis.c - Vers 3.6.005 - Oct 1993 - L. Fini, OAA * - Vers 3.6.004 - Sep 1993 - L. Fini, OAA * - Vers 3.6.003 - Aug 1992 - L. Fini, OAA */ #include #include static void Isset(what,val,mfmode) char *what; int val; { char setbuf[50]; sprintf(setbuf,"%s=%d",what,val); AGLsset(setbuf,mfmode); } /*****************************************************************************/ /*++ AG_AXIS (User callable) */ /* AG_AXIS */ /* This module draws an axis according to given specifications. */ /* The routine AG_AXIS allows the user to design himself the layout of the */ /* axis, but the caller must carefully compute and provide all the required */ /* parameters. */ /* To get automatic positioning and quoting of axes use AG_AXES instead. */ /* The routine AG_AXIS will draw either horizontal or vertical axes in the */ /* currently active graphic mode. */ /* In order to draw axes with arbitrary orientation and scales the routine */ /* AG_ORAX() must be used, instead. */ void AG_AXIS(type,data,lspace,format,label) int type; /* Axis type and more specifications */ /* - Axis type selection: */ /* 0 = horizontal, quotes and label below */ /* 1 = vertical, quotes and label at right */ /* 2 = horizontal, quotes and label above */ /* 3 = vertical, quotes and label at left */ /* The value of the axis type can be or-ed */ /* with the following specification bits: */ /* 4 = Draw the axis with thicker line width*/ /* 8 = Do not draw the axis line (supersedes*/ /* the above value) */ /* 16 = draw the grid with solid line */ /* (default is dotted) */ /* 32 - Quotes are not centered on tick, but */ /* sligtly displaced */ float data[11]; /* Array of specifications, with the following */ /* meaning: (N.B.: array base is 0 for C and */ /* 1 for Fortran !!) */ /* [0] Axis starting coordinate. */ /* [1] Axis ending coordinate. */ /* N.B.: data[0] < data[1] */ /* if(data[0]==data[1]) no axis or */ /* ticks are plotted, but only */ /* quotes */ /* [2] Divisions (ticks) starting coordinate. */ /* This may differ from the axis starting */ /* coordinate if the latter is not at an */ /* even multiple of the division step. */ /* [3] Divisions (ticks) ending coordinate. */ /* This may differ from the axis ending */ /* coordinate if the latter is not at an */ /* even multiple of the division step. */ /* N.B.: data[2] < data[3] */ /* [4] Step distance between major ticks or */ /* grid lines. If <= 0.0 no ticks or grid*/ /* lines will be drawn. */ /* If the logarithmic option is selected */ /* it is a multiplicative factor. */ /* [5] Step distance between minor ticks or */ /* If <= 0.0 no minor ticks will be drawn.*/ /* If the logarithmic option is selected */ /* it is a multiplicative factor. */ /* [6] Constant position of this axis along */ /* the other coordinate. */ /* [7] Constant position of the ending points */ /* of grid lines along the other coor- */ /* dinate(i.e., usually, the position of */ /* the parallel opposite axis). */ /* If data[6] is equal to data[7], ticks */ /* are drawn instead of grid lines. */ /* [8] Offset for quotes: see [9]. */ /* [9] Multiplying factor for quotes. */ /* Major ticks are drawn at the requested */ /* positions, and the corresponding quote */ /* values are computed as: */ /* quote = data[8] + position*data[9] */ /* before they are actually drawn. To get */ /* quotes in the usual way (i.e.: numbers */ /* exactly corresponding to coordinates) */ /* you must specify: data[8]=0.0, and */ /* data[9]=1.0. */ /* N.B.: if data[9] is equal to 0.0, no */ /* quotes are drawn. */ /* [10] An exponent value to be removed from */ /* quotes. I.e. if data[10] is not equal */ /* to 0.0 all quotes are further divided */ /* by 10**data[10] and the exponent is */ /* written in a suitable place close to */ /* the end of the axis. */ double lspace; /* Space left between the axis and the label */ /* It is expressed as an lspace number of */ /* characters in the current dimension. */ /* If 0.0 it computed accordingly to current */ /* length of quotes */ char *format; /* Format specification to draw quotes */ /* The string may contain some standard C */ /* format specifications PLUS a set of special */ /* ones as listed below (standard specifica- */ /* tion are marked with (C) and special with */ /* (S)) */ /* If the string has not the '%' as first */ /* character quotes are not drawn */ /* %[w.p]d (C) : Decimal integer */ /* %[w.p]f (C) : Floating point */ /* %[w.p]e (C) : Exponential format */ /* w=width, p=precision */ /* %g (S) : as the %f above, but strips */ /* all trailing zeroes and deci-*/ /* mal point (not the same as */ /* the C standard %g format!) */ /* %p (S) : Writes only the power of 10 */ /* %x (S) : Writes only the power of e */ /* %au (S) : Degrees */ /* %aum (S) : Degrees minutes */ /* %aums (S) : Degrees minutes seconds */ /* %ams (S) : minutes seconds */ /* %amss (S) : minutes seconds fraction */ /* %hu (S) : Hours */ /* %hum (S) : Hours minutes */ /* %hums (S) : Hours minutes seconds */ /* %hms (S) : minutes seconds */ /* %hmss (S) : minutes seconds fraction */ /* NOTE: Add more s' to the end of the format */ /* string to get more fraction digits */ char *label; /* String to be drawn as label. */ /* If the string is empty, obviously no label */ /* is drawn. */ /* Note: quotes and label are both drawn in the*/ /* current setting of character strings */ /* (see AG_SSET for details on how to set*/ /* various items affecting how characters*/ /* are drawn), and with the same char- */ /* acter size. */ /* You can modify the way the label is */ /* drawn by means of the standard AGL */ /* metacharacter sequences (see AG_GTXT) */ /*--*/ { static char *modnam = "AXIS"; static char *Tdir1="lfrg"; static char *Tdir2="bott"; static char *Tdir3="rglf"; static char *Tdir4="updo"; static char *Mjtick = "~0\36"; /* Major tick character code */ static char *Mntick = "~0\37"; /* Minor tick character code */ float auxc0[2], auxc1[2]; float *x_vect, *y_vect; float xspace,yspace; double Mjstep,Mnstep; int do_axis; int logflg; int Qcnt1,Qcnt2; int Lcenter; void (*Draw_polyline)(); double stop; int a_type; int s_mode, s_mfmode, s_width, s_twidth, s_logx, s_logy, s_lstyl; char *Tdir; char *Ldir; char *Mjt; char Form[10]; static char *Norm = "norm"; static char *Mfmo = "mfmo"; static char *Mode = "mode"; static char *Logx = "logx"; static char *Logy = "logy"; static char *Lwid = "lwid"; static char *Twid = "twid"; static char *Lsty = "lsty"; AG_DMSG(modnam,(char *)0); AGL_push(modnam); AG_IGET(Mfmo,&s_mfmode); AG_IGET(Mode,&s_mode); AG_IGET(Logx,&s_logx); AG_IGET(Logy,&s_logy); AG_IGET(Lwid,&s_width); AG_IGET(Twid,&s_twidth); AG_IGET(Lsty,&s_lstyl); if(s_mode==(int)SPECIAL) Draw_polyline = AG_GINT; else Draw_polyline = AG_GPLL; a_type = type&AXIS_TYPE; switch(a_type) { case 0: x_vect=auxc0; y_vect=auxc1; Qcnt2 = (type"E_DISPL) ? 22 : 20; Qcnt1 = (type"E_DISPL) ? 18 : 20; Lcenter=20; logflg = s_logx; Tdir=Tdir1; Ldir=Tdir1; break; case 1: x_vect=auxc1; y_vect=auxc0; Qcnt1 = (type"E_DISPL) ? 22 : 24; Qcnt2 = (type"E_DISPL) ? 10 : 24; logflg = s_logy; Lcenter=20; Tdir=Tdir2; Ldir=Tdir2; break; case 2: x_vect=auxc0; y_vect=auxc1; Qcnt2 = (type"E_DISPL) ? 10 : 12; Qcnt1 = (type"E_DISPL) ? 14 : 12; logflg = s_logx; Lcenter=12; Tdir=Tdir3; Ldir=Tdir1; break; case 3: x_vect=auxc1; y_vect=auxc0; Qcnt1 = (type"E_DISPL) ? 18 : 16; Qcnt2 = (type"E_DISPL) ? 14 : 16; logflg = s_logy; Lcenter=12; Tdir=Tdir4; Ldir=Tdir2; break; default: AGL_puterr(ILLSETWNG,modnam); AGL_pop(); return; } if(data[9]==0.0) *Form='*'; else strncpy(Form,format,10); if(*Form!='%') *Form='*'; Mjstep=(data[4]>0.0) ? data[4] : 0.0; Mnstep=data[5]; do_axis = (data[1]>data[0]); if(do_axis) { auxc0[0]=data[0]; auxc0[1]=data[1]; auxc1[0]=data[6]; auxc1[1]=data[6]; if(type&THICK_AXIS) { Isset(Lwid,1,s_mfmode); Isset(Twid,1,s_mfmode); } Isset(Lsty,0,s_mfmode); Draw_polyline(x_vect,y_vect,2); /* Draw the axis */ auxc1[0]=data[6]; auxc1[1]=data[7]; auxc0[0]=data[2]; if(type & GRID_SOLID) /* prepare line style for grid */ Isset(Lsty,0,s_mfmode); else Isset(Lsty,1,s_mfmode); AGLsset(Tdir,s_mfmode); if(Mjstep>0.0) Mjt=Mjtick; if(Mnstep>0.0) { if(Mjstep==0.0) { /* This is the case when major step */ /* is 0.0 and minor step > 0.0 */ auxc1[1]=auxc1[0]; /* this to avoid grid */ Mjstep=Mnstep; /* whe want small ticks */ Mjt=Mntick; /* where big ones would be */ *Form='*'; /* But without quotes */ } } else Mnstep=0.0; stop=MIN(data[2],data[0]); while(Mnstep>0.0) { /* Draw minor ticks to the left of first */ /* major one */ /* N.B. This is an infinite loop */ /* terminated by "break" */ auxc0[0]=AGLnmnt(auxc0[0],logflg, (-Mnstep),(double)data[2]); if(auxc0[0]0.0) { /* loop on major tiks */ double next; /* N.B. This is an infinite loop */ /* terminated by "break" */ if(auxc0[0]>AGLGuardU((double)data[3],logflg,Mjstep)) break; if(auxc1[0]==auxc1[1]) AG_GTXT(*x_vect,*y_vect,Mjt,1); /* Draw the tick */ else { auxc0[1]=auxc0[0]; Draw_polyline(x_vect,y_vect,2); /* Draw grid line */ } next = AGLnmjt(auxc0[0],logflg,Mjstep); if(Mnstep>0.0) { /* Draw minor ticks to the right */ double curr = auxc0[0]; stop=MIN(data[1],next); for(;;) { /* N.B. This is an if or an loop */ /* terminated by "break" */ auxc0[0]=AGLnmnt(auxc0[0],logflg, Mnstep,curr); if(auxc0[0]>AGLGuardU(stop,logflg,Mjstep)) break; AG_GTXT(*x_vect,*y_vect,Mntick,1); } } auxc0[0]=next; } } xspace=0; yspace=0; Isset(Twid,s_twidth,s_mfmode); /* Set label tickness */ if((*Form!='*')&&(Mjstep>0.0)) { char auxst[60]; double iexp = 1.0/pow(10.0,(double)data[10]); AGLsset(Tdir1,s_mfmode); auxc0[0]=data[2]; auxc1[0]=data[6]; while(auxc0[0]xspace) ? rx[0] : xspace; AG_GTXT(*x_vect,*y_vect,auxst,Qcenter); auxc0[0] = AGLnmjt(auxc0[0],logflg,Mjstep); } if(iexp!=1.0) { char auxst1[20]; char *pt; float rx[3],ry[3]; int Qcenter; AG_TGET("O",rx,ry); AGLConvert("%e",(1.0/iexp),auxst1); pt=strchr(auxst1,' ')+1; sprintf(auxst,"(~{~0x~}%s)",pt); switch(a_type) { case 0: case 2: auxc0[0]=data[1]; auxc1[0]=data[6]; AG_VU2N(auxc0[0],auxc1[0],auxc0,auxc1); if(a_type==0) { auxc1[0] -= 2.0*ry[1]; Qcenter = 20; } else { auxc1[0] += 2.0*ry[1]; Qcenter = 12; } break; case 1: case 3: auxc0[0]=data[6]; auxc1[0]=data[1]; AG_VU2N(auxc0[0],auxc1[0],auxc0,auxc1); auxc1[0] += ry[1]; Qcenter = 12; break; } AGLsset(Norm,s_mfmode); AG_GTXT(auxc0[0],auxc1[0],auxst,Qcenter); } } if(*label!=0) { float rx[3],ry[3]; AGLsset(Tdir1,s_mfmode); AG_TGET("O",rx,ry); switch(a_type) { case 0: case 2: xspace=0; if(lspace>0.0) yspace = lspace*ry[1]; else yspace = 3.0 * ry[1]; break; case 1: case 3: yspace=0; if(lspace>0.0) xspace= lspace*rx[0]; else xspace += 2.0*rx[0]; break; } if((a_type==0)||(a_type==3)) { xspace = -xspace; yspace = -yspace; } auxc0[0]=data[0]; auxc1[0]=data[6]; auxc0[1]=data[1]; auxc1[1]=data[6]; AG_VU2N(*x_vect,*y_vect,auxc0,auxc1); AG_VU2N(*(x_vect+1),*(y_vect+1),(auxc0+1),(auxc1+1)); auxc0[0] = (auxc0[0]+auxc0[1])*0.5; auxc1[0] = (auxc1[0]+auxc1[1])*0.5; auxc0[0] += xspace; auxc1[0] += yspace; AGLsset(Norm,s_mfmode); AGLsset(Ldir,s_mfmode); AG_GTXT(auxc0[0],auxc1[0],label,Lcenter); } switch(s_mode) { case 1: AGLsset("user",s_mfmode); break; case 2: AGLsset("special",s_mfmode); break; } Isset(Mfmo,s_mfmode,s_mfmode); Isset(Mode,s_mode,s_mfmode); Isset(Lwid,s_width,s_mfmode); Isset(Twid,s_twidth,s_mfmode); Isset(Lsty,s_lstyl,s_mfmode); AGL_pop(); }