/*
 * Copyright 1988 Anant Agarwal
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose and without fee is hereby granted, provided
 * that the above copyright notice appear in all copies and that both that
 * copyright notice and this permission notice appear in supporting
 * documentation.  No representations about the suitability of this software
 * for any purpose.  It is provided "as is" without express or implied 
 * warranty.
 *
 * Author:  Anant Agarwal, MIT Laboratory for Computer Science
 */

#include <strings.h>	
#include <stdio.h>
#include <math.h>
#include "plotio.h"
#include "defs.h"
#include "structs.h"
#include "plot.h"

extern double getdegrees(), atan(), charheight(),charwidth(),log10(),mylog();


printaxes()
{
boolean mirror=FALSE;/* regular axes first */
	/* graph label */
	if (idlabel) graphlabel();
	/* graph title */
	graphtitle();

	if (ShowAxes)
	{
		mirror = FALSE;
		/* x axis line */
		if (ShowXLine) graphaxis(xpt,mirror);
		/* y axis line */
		if (ShowYLine) graphaxis(ypt,mirror);
	}

	/* mirror axes if necessary */
	if (MirrorAxes)
	{
		mirror = TRUE;
		if (ShowXLine) graphaxis(xpt,mirror);
		if (ShowYLine) graphaxis(ypt,mirror);
	}
	if (ShowAxes)
	{
		mirror = FALSE;
		/* x axis label */
		graphaxislabel(xpt, mirror);

		/* y axis label */
		graphaxislabel(ypt, mirror);
	}
	if ((MirrorAxisLabels)&&(MirrorAxes))
	{
		mirror = TRUE;
		/* x axis label */
		graphaxislabel(xpt, mirror);

		/* y axis label */
		graphaxislabel(ypt, mirror);
	}
}

/* do graph title  */
graphtitle()
{
	(obj[curobj])->name   = objtext;
	(obj[curobj])->from[xpt]   = graphsize[xpt] / 2.0;/*center*/
	(obj[curobj])->from[ypt]   = - titleBelowXAxis;
	(obj[curobj])->un.text.fontsize = FFsize(graph.font);
	(obj[curobj])->un.text.font = graph.font;
	(obj[curobj])->un.text.FF = FF(graph.font);
	(obj[curobj])->scale = FALSE;
	(obj[curobj])->un.text.StrPtr = graph.title;
	(obj[curobj])->un.text.angle 	= getdegrees(1.0,0.0);/* horizontal */
	(obj[curobj])->un.text.align = center;
	cmtopoints(obj[curobj]);
	GetNewObjcurobj();
	(obj[curobj])->name = objflagaxes;/*signal start of axes for
		setting line cap */
	GetNewObjcurobj();
}

/* do label title  */
graphlabel()
{
	(obj[curobj])->name   = objtext;
	(obj[curobj])->from[xpt]   = idLabelFromAxes;
	(obj[curobj])->from[ypt]   = idLabelFromAxes;
	(obj[curobj])->un.text.fontsize = FFsize(graph.font);
	(obj[curobj])->un.text.font = graph.font;
	(obj[curobj])->un.text.FF = FF(graph.font);
	(obj[curobj])->scale = FALSE;
	(obj[curobj])->un.text.StrPtr = graph.label;
	(obj[curobj])->un.text.angle 	= getdegrees(1.0,0.0);/* horizontal */
	(obj[curobj])->un.text.align = left;
	cmtopoints(obj[curobj]);
	GetNewObjcurobj();
}

graphaxis(z,mirror)
int z;
boolean mirror;
{
int zinv;
	if (z == xpt) zinv = ypt;
	else zinv = xpt;
	(obj[curobj])->name   	= objline;
	(obj[curobj])->gray = DefAxisGray;
	(obj[curobj])->un.line.line 	= solid;
	(obj[curobj])->un.line.interp 	= linearinterp;
	(obj[curobj])->un.line.thick 	= FFthick(graph.font);

/*	unscaled method removed so that I can put axes where I want */
/*	(obj[curobj])->from[xpt]   = 0;
	(obj[curobj])->from[ypt]   = 0;
	(obj[curobj])->un.line.to[z] = graphsize[z];
	(obj[curobj])->un.line.to[zinv] = 0;
*/
/*	scaled method */
	(obj[curobj])->from[z] = limits[z][minval];
	(obj[curobj])->un.line.to[z] = limits[z][maxval];
	/* common for mirror and regular axes done outside */
	if (!mirror)
	{
		(obj[curobj])->from[zinv] = 
			(NewOrigin ? origin[zinv] : limits[zinv][minval]);
		(obj[curobj])->un.line.to[zinv] = (obj[curobj])->from[zinv];
	}
	else
	{
		(obj[curobj])->from[zinv] = limits[zinv][maxval];
		(obj[curobj])->un.line.to[zinv] = (obj[curobj])->from[zinv];
	}

	(obj[curobj])->scale = TRUE;
/*	cmtopoints(obj[curobj]); *//* do not scale here */
	GetNewObjcurobj();
}

graphaxislabel(z, mirror)
int z;
boolean mirror;
{
int zinv;
int minussign= -1, plussign= 1;
	if (z == xpt) zinv = ypt;
	else zinv = xpt;
	(obj[curobj])->name   = objtext;
	(obj[curobj])->un.text.fontsize = FFsize(graph.font);
	(obj[curobj])->un.text.font = graph.font;
	(obj[curobj])->un.text.FF = FF(graph.font);
	(obj[curobj])->un.text.StrPtr = axis[z].label;
	(obj[curobj])->scale = FALSE;
	(obj[curobj])->un.text.align = right;

/*	(obj[curobj])->from[z]   = graphsize[z] ;
*	(obj[curobj])->un.text.angle =
*		(z ? getdegrees(0.0,1.0) : getdegrees(1.0,0.0) ); */
/*	now  move y axis label to left if numbers too wide. */
/*	creates new labelLeftYAxis if numbers too wide */
/*	if (z == ypt) CheckLabelPos();
*
*	(obj[curobj])->from[zinv]   = -1 *
*		(z ? labelLeftYAxis : labelBelowXAxis);
*	cmtopoints(obj[curobj]); */
/* 	prev commented text used unscaled axes, now do scaled so that origin
*	is usable */

	/* common for mirror and regular */
	(obj[curobj])->from[z]   = limits[z][maxval];
	(obj[curobj])->un.text.angle =
		(z ? getdegrees(0.0,1.0) : getdegrees(1.0,0.0) );

	/*creates new labelLeftYAxis if numbers too wide */
	if (z == ypt) CheckLabelPos();/* idempotent, so can do again on 
					mirroring */
	/* common for mirror and regular axes done outside */
	if (!mirror)
	{
		(obj[curobj])->from[zinv]   = 
			(NewOrigin ? origin[zinv] : limits[zinv][minval]);
		(obj[curobj])->scale = TRUE;
		scaleobj(obj[curobj]);/* so that the labels can be shuffled */

		/*now  move y axis label to left if numbers too wide. */
		(obj[curobj])->from[zinv]   -= CMPT * 
			(z ? labelLeftYAxis : labelBelowXAxis);
	}
	else
	{
		(obj[curobj])->from[zinv]   = limits[zinv][maxval];
		(obj[curobj])->scale = TRUE;
		scaleobj(obj[curobj]);/* so that the labels can be shuffled */

		/* labelLeftYAxis
		move mirror y axis label to right if numbers too wide. */
		(obj[curobj])->from[zinv]   += CMPT * 
			(z ? labelLeftYAxis : labelBelowXAxis);

		/* FracDownMirror
		move x or y label back a small amount (determined as 
		a function of charheight) down */
		(obj[curobj])->from[zinv]   += CMPT * 
			(z ? 
				plussign * numberLeftYAxis / FracDownMirror : 
				minussign * numberBelowXAxis * FracDownMirror
			);
	}
	GetNewObjcurobj();
}


/* checking necessary only for Y axis */
CheckLabelPos()
{
int maxi, mini;
int WH, WL;/*counts how many chars in number */
/* WH counts for maximum number and mini for minimum number */
/* choose higher one */

	maxi = (int) axis[ypt].axismax;
	mini = (int) axis[ypt].axismin;

	if (maxi > 1) 
	{
		if ((axis[ypt].numberstyle == exponent)||
			(axis[ypt].numberstyle == scientific))
			WH = (int) log10(log10(1.0 * maxi) + 1);
		else WH = (int) log10(1.0 * maxi) + 1;
	}
	else if (maxi < -1) 
	{
		if ((axis[ypt].numberstyle == exponent)||
			(axis[ypt].numberstyle == scientific))
			WH = (int) log10(log10(-1.0 * maxi) + 2);
		else WH = (int) log10(-1.0 * maxi) + 2;
	}
	else if (maxi < 0) 
		WH = 2;
	else 
		WH = 1;
	
	if (axis[ypt].numberstyle == exponent)
		WH += 5;
	else if (axis[ypt].numberstyle == scientific)
		WH += 7;
	else if (axis[ypt].numberstyle == floating)
		WH += 1 + axis[ypt].signif;
	
	if (mini > 1) 
	{
		if ((axis[ypt].numberstyle == exponent)||
			(axis[ypt].numberstyle == scientific))
			WL = (int) log10(log10(1.0 * mini) + 1);
		else WL = (int) log10(1.0 * mini) + 1;
	}
	else if (mini < -1) 
	{
		if ((axis[ypt].numberstyle == exponent)||
			(axis[ypt].numberstyle == scientific))
			WL = (int) log10(log10(-1.0 * mini) + 2);
		else WL = (int) log10(-1.0 * mini) + 2;
	}
	else if (mini < 0) 
		WL = 2;
	else 
		WL = 1;
	
	if (axis[ypt].numberstyle == exponent)
		WL += 5;
	else if (axis[ypt].numberstyle == scientific)
		WL += 7;
	else if (axis[ypt].numberstyle == floating)
		WL += 1 + axis[ypt].signif;
	
	if (WH < WL)
		WH = WL;

	WH += 2;/* for spacing */
	WH = WH + (int) log10((float) axis[ypt].unit);

	if ((WH * charwidth(axis[ypt].font)) > 2.0) /*cms*/
	{
		fprintf(stderr,"****splot warning: Y axis label may be out of page.\n");
		fprintf(stderr,"You may want to translate graph to see it.\n");
	}

	if (WH > 6) /*recompute labelLeftYAxis */
		labelLeftYAxis = WH * charwidth(axis[ypt].font);
}


