/*===========================================================================
  Copyright (C) 1995-2009 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 Massachusetts Ave, Cambridge, 
  MA 02139, USA.
 
  Correspondence 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
===========================================================================*/

/*
 * 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
.VERSION

 090630		last modif
 */

#include <aglenvr.h>
#include <aglaxes.h>


static void Isset(what,val,mfmode)
char *what;
int mfmode, 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&QUOTE_DISPL) ? 22 : 20;
	Qcnt1 = (type&QUOTE_DISPL) ? 18 : 20;
	Lcenter=20;
	logflg = s_logx;
	Tdir=Tdir1;
	Ldir=Tdir1;
	break;
case 1:
	x_vect=auxc1;
	y_vect=auxc0;
	Qcnt1 = (type&QUOTE_DISPL) ? 22 : 24;
	Qcnt2 = (type&QUOTE_DISPL) ? 10 : 24;
	logflg = s_logy;
	Lcenter=20;
	Tdir=Tdir2;
	Ldir=Tdir2;
	break;
case 2:
	x_vect=auxc0;
	y_vect=auxc1;
	Qcnt2 = (type&QUOTE_DISPL) ? 10 : 12;
	Qcnt1 = (type&QUOTE_DISPL) ? 14 : 12;
	logflg = s_logx;
	Lcenter=12;
	Tdir=Tdir3;
	Ldir=Tdir1;
	break;
case 3:
	x_vect=auxc1;
	y_vect=auxc0;
	Qcnt1 = (type&QUOTE_DISPL) ? 18 : 16;
	Qcnt2 = (type&QUOTE_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; */
	Mjt=Mjtick;			/* has to be initialized anyway... */

	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]<AGLGuardL(stop,logflg,Mnstep))
			break;

		AG_GTXT(*x_vect,*y_vect,Mntick,1);
	}

	auxc0[0]=data[2];

	while(Mjstep>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]<AGLGuardU((double)data[3],logflg,Mjstep)) {	/* quotes loop */
		double quote;
		int Qcenter;
		float rx[3],ry[3];

		if(auxc0[0]<0.0)
			Qcenter=Qcnt1;
		else
			Qcenter=Qcnt2;

        	quote = (auxc0[0]*data[9] + data[8])*iexp;

		AGLConvert(Form,quote,auxst);

		AG_TGET(auxst,rx,ry);
		xspace = (rx[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=0;

		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();
}
