/*===========================================================================
  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 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
===========================================================================*/

/*
 * HEADER : ag_orax.c      - Vers 3.6.003  - Sep 1993 -  L. Fini, OAA
 *                         - Vers 3.6.002  - Apr 1992 -  L. Fini, OAA
 *                         - Vers 3.6.001  - Apr 1991 -  L. Fini, OAA
 .VERSION

 090630		last modif
 */



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


#define READ_FROM_BOT_C	(-0.034899)
#define READ_FROM_BOT_S	(-0.993908)


/*****************************************************************************/
/*++                          AG_ORAX (User callable)                        */

/* AG_ORAX                                                                   */


/* This module draws an axis of given orientation.                           */

/* The routine AG_ORAX allows the drawing of an axis with arbitrary          */
/* orientation angle. The axis scales and quotes are defined independently   */
/* of the current graphic status.                                            */

/* To draw horizontal or vertical axes with a greater detail of specifica-   */
/* tion the AG_AXIS() routine can be used instead.                           */


void AG_ORAX(flags,ends,data,form,label)

 int flags;                   /* Specification flags. The inclusive or of    */
                              /* the following values:                       */

                              /*   1 - Draw ticks below the axis (Default is */
                              /*       above).                               */
                              /*       Quotes are drawn on the opposite side */
                              /*       of the axis                           */

                              /*   2 - Draw tiks with specified angle (see   */
                              /*       data[6]). Default is to make tiks     */
                              /*       perpendicular to the axis.            */
                              /*       Setting flag 1 above, will add 180    */
                              /*       degrees to the specified angle; i.e.  */
                              /*       with the same angle value tiks are    */
                              /*       drawn in the opposite direction when  */
                              /*       flag 1 is set.                        */

                              /*   4 - Draw quotes parallel to the axis. The */
                              /*       default is to draw quotes always      */
                              /*       horizontally.                         */

 float ends[4];               /* Axis starting and ending points:            */

                              /* (ends[0],ends[1]) = (xstart,ystart)         */
                              /* (ends[2],ends[3]) = (xend,yend)             */

                              /* Values are referred to the currently active */
                              /* coordinate system                           */

 float data[7];               /* Array of specifications, with the following */
                              /* meaning: (N.B.: array base is 0 for C and   */
                              /* 1 for Fortran !!)                           */

                              /* The following values are independent on the */
                              /* active coordinate system.                   */

                              /* [0]  Axis starting point coordinate         */
                              /* [1]  Axis ending point coordinate.          */
                              /*      N.B.:  data[0] < data[1]               */

                              /* [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]  Tiks drawing angle. This value has     */
                              /*      effect only if flag 2 is set (see      */
                              /*      above). The angle must be given in the */
                              /*      proper units (see: AG_SSET, items      */
                              /*      DEGREES and RADIANS) and with respect  */
                              /*      to the currently defined coordinate    */
                              /*      system, independently on the actual    */
                              /*      aspect ratio of the vieport. E.g. while*/
                              /*      in user mode with a window defined as  */
                              /*      AG_WDEF(0.,10.,0.,10) specifying an    */
                              /*      angle of 45 degrees will result in tik */
                              /*      marks parallel to the diagonal of the  */
                              /*      window. To obtain the same result with */
                              /*      a window defined as:                   */
                              /*      AG_WDEF(0.,10.,0.,1) will require to   */
                              /*      specify an angle of 5.71 degrees (it   */
                              /*      corresponds to atan(1/10))             */

 char *form;                  /* 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 = "ORAX";

static char *Mjtick = "~0\36";		/* Major tick character code       */
static char *Mntick = "~0\37";		/* Minor tick character code       */
char aux_str[60];
char *Mjt;

float Nends[4];
float rx[3],ry[3];
float x_vect[2], y_vect[2];
float ratio;
float AngFc;

int DoTiks,DoQuotes;
int Qcenter;
int mmode;
int gmode;

double AxAngle,TkAngle,QtAngle;
double nchar=0.0;
double xstart=0.0,ystart=0.0;
double xmj=0.0,ymj=0.0;
double xmn,ymn;
double cosb,sinb;
double Mjstep,Mnstep;


Mjt=Mjtick;

AG_DMSG(modnam,(char *)0);

AGL_push(modnam);

AG_VU2N(ends[0],ends[1],&Nends[0],&Nends[1]);
AG_VU2N(ends[2],ends[3],&Nends[2],&Nends[3]);

AG_IGET("mfode",&mmode);
AG_IGET("mode",&gmode);
AG_RGET("aspect",&ratio);
AG_RGET("angfct",&AngFc);

AxAngle=atan2((double)((Nends[3]-Nends[1])*ratio),
               (double)(Nends[2]-Nends[0]));

if(!(flags&0x02))
	TkAngle = AxAngle;
else {
	float wnd[4];
	double sina,cosa;

	TkAngle = data[6]*AngFc;

	if(gmode>0) {
		sina=sin(TkAngle);
		cosa=cos(TkAngle);
		AG_RGET("wndl",wnd);
		AG_RGET("clpasp",&ratio);
		sina *= (wnd[1]-wnd[0])*ratio;
		cosa *= (wnd[3]-wnd[2]);
		TkAngle = atan2(sina,cosa) - AG_PI05 ;
	}
}

Mjstep=(data[4]>0.0) ? data[4] : 0.0;

Mnstep=data[5];

AGLsset("normal",mmode);


if(flags&0x01) {
	AxAngle -= AG_PI;
	TkAngle -= AG_PI;
}


cosb = cos(AxAngle);
sinb = sin(AxAngle);

x_vect[0]=Nends[0];
x_vect[1]=Nends[2];
y_vect[0]=Nends[1];
y_vect[1]=Nends[3];

AG_GPLL(x_vect,y_vect,2);			/* Draw the axis           */

Mjstep=data[4];
Mnstep=data[5];

if(Mnstep<Mjstep*0.01)
	Mnstep=0.0;

if(Mjstep<(data[3]-data[2])*0.0001) {
	Mjstep=0.0;
	DoTiks=FALSE;
	DoQuotes=FALSE;
} else {
	DoTiks=TRUE;
	if(*form == '%')
		DoQuotes=TRUE;
	else
		DoQuotes=FALSE;
}

if((data[1]-data[0]<=0.0) ||
   (data[3]-data[2]<=0.0) ||
   ((Mnstep==0.0)&&(Mjstep==0.0))) {
	AG_GERR(RANGEERR,modnam);
	AGL_pop();
	return;
}
	

if(Mnstep>0.0) {
	if(Mjstep==0.0) {		/* This is the case when major step */
					/* is 0.0 and minor step > 0.0      */
		Mjstep=Mnstep;			/* whe want small ticks     */
		Mjt=Mntick;			/* where big ones would be  */
		DoQuotes=FALSE;		/* But without quotes       */
	}
} else
	Mnstep=0.0;

if(DoTiks||DoQuotes) {
	double ax_lng;
	double x_rat, y_rat;

	ax_lng = data[1]-data[0];
	x_rat  = (Nends[2]-Nends[0])/ax_lng;
	y_rat  = (Nends[3]-Nends[1])/ax_lng;

	xstart=Nends[0]+ x_rat*(data[2]-data[0]);
	ystart=Nends[1]+ y_rat*(data[2]-data[0]);
	xmj = x_rat*data[4];
	ymj = y_rat*data[4];
	xmn = x_rat*data[5];
	ymn = y_rat*data[5];
}

if(DoTiks) {
	double quote;
	double stop;
	double xp,yp;

	sprintf(aux_str,"changle=%f",TkAngle/AngFc);
	AGLsset(aux_str,mmode);

	if(Mjstep>0.0)
		Mjt=Mjtick;

	stop=MIN(data[2],data[0])-(Mnstep*0.001);

	quote=data[2]; xp=xstart; yp=ystart;

	while(Mnstep>0.0) {	/* Draw minor ticks to the left of first   */
				/* major one                               */
					/* N.B. This is an infinite loop   */
					/*      terminated by "break"      */

		quote=AGLnmnt(quote,FALSE,(-Mnstep),Mjstep);

		if(quote<AGLGuardL(stop,FALSE,Mnstep))
			break;

		AG_GTXT(xp,yp,Mntick,1);
		xp -= xmn;
		yp -= ymn;
	}

	quote=data[2]; xp=xstart; yp=ystart;

	while(Mjstep>0.0) {		/* loop on major tiks              */
		double next;		/* N.B. This is an infinite loop   */
		double xpm,ypm;		/*      terminated by "break"      */

		if(quote>AGLGuardU((double)data[3],0,Mjstep))
			break;

		AG_GTXT(xp,yp,Mjt,1);			/* Draw the tick   */

		next = AGLnmjt(quote,0,Mjstep);

		xpm=xp; ypm=yp;

		if(Mnstep>0.0) {	/* Draw minor ticks to the right   */
			double curr = quote;

			stop=MIN(data[1],next);

			for(;;) {
					/* N.B. This is an if or an loop   */
					/*      terminated by "break"      */

				quote=AGLnmnt(quote,0,Mnstep,curr);
				if(quote>AGLGuardU((double)stop,0,Mjstep))
					break;

				xpm += xmn;
				ypm += ymn;

				AG_GTXT(xpm,ypm,Mntick,1);
			}
		}
		quote=next; xp += xmj; yp += ymj;
	}
}

if((cosb>READ_FROM_BOT_C)&&(sinb>READ_FROM_BOT_S)) {
	QtAngle = AxAngle;
	Qcenter = 20;
} else {
	QtAngle = AxAngle-AG_PI;
	Qcenter = 12;
}

if(DoQuotes) {
	double quote,QAngle=QtAngle;
	double xp,yp;
	int Qc;

	if(flags&0x4) {
		float qd[2];
		Qc = Qcenter;
		AG_RGET("chnd",qd);	/* Get character normalized dims  */
					/* to compute quote disoplacement */
	} else {
		QAngle = 0.0;
		if(cosb>0.996)		/* The axis is within 5 degrees   */
			Qc=20; 	/* from horizontal quotes below   */
		else if(cosb<-0.996)	/* The axis is within 5 degrees   */
			Qc=12;	/* from horizontal quotes above   */
		else if(sinb>0.996)	/* The axis is within 5 degrees   */
			Qc=24;	/* from vertical quotes at right  */
		else if(sinb<-0.996)	/* The axis is within 5 degrees   */
			Qc=16;	/* from vertical quotes at leftt  */
		else if(cosb>0.0)
			if(sinb>0.0)	/* The axis is in the first       */
				if(sinb<0.707)  /* quadrant, quotes below */
					Qc=21;
				else
					Qc=23;
			else 		/* The axis is in the fourth      */
				if(sinb<-0.707) /* quadrant, quotes below */
					Qc=17;
				else
					Qc=19;
		else
			if(sinb>0.0)	/* The axis is in the second      */
				if(sinb<0.707)  /* quadrant, quotes above */
					Qc=11;
				else
					Qc=9;
			else		/* The axis is in the third       */
				if(sinb<-0.707) /* quadrant, quotes above */
					Qc=15;
				else
					Qc=13;

	}
	sprintf(aux_str,"changle=%f",(double)QAngle/AngFc);
	AGLsset(aux_str,mmode);

	quote=data[2]; xp=xstart; yp=ystart;

	nchar=0;
	while(quote<AGLGuardU((double)data[3],0,Mjstep)) {
		int qthlng;
		double value;

        	value = quote;

		AGLConvert(form,value,aux_str);

		AG_GTXT(xp,yp,aux_str,Qc);

		qthlng=strlen(aux_str);
		if(qthlng>nchar) {		/* string length for label  */
			nchar=qthlng;		/* spacing is computed on   */
			AG_TGET(aux_str,rx,ry);	/* the longest quote        */
		}
		quote = AGLnmjt(quote,0,Mjstep);
		xp += xmj;
		yp += ymj;
	}
}
if(*label!='\0') {
	double x0,y0;
	double sx;
					/* Compute space occupied by quotes */
	if(flags&0x4) {
		sx = 2.0*sqrt((double)(rx[2]*rx[2])+(double)(ry[2]*ry[2]));
	} else {
		sx = fabs(rx[0]*(1.0+1.5/(double)nchar)*sinb) + 
                     fabs(ry[2]*cosb*2.0);
	}
	x0 = (Nends[2]+Nends[0])*0.5 + sinb*sx;
	y0 = (Nends[3]+Nends[1])*0.5 - cosb*sx;

	sprintf(aux_str,"changle=%f",(double)QtAngle/AngFc);
	AGLsset(aux_str,mmode);
	AG_GTXT(x0,y0,label,Qcenter);
}

switch(gmode) {
case 1:
	AGLsset("user",mmode);
	break;
case 2:
	AGLsset("special",mmode);
	break;
}
AGLsset("lfrg;lstyl=0",mmode);		/* reset line style                 */

AGL_pop();
}
