/*
 * 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();
private boolean ClipOn = FALSE;
/* set when clipping is enabled */

sendobj()
{
boolean firstcurves = FALSE;
/* curobj has first invalid object */
int ob=0;/* obj under consideration */

	/* do not send curves and curve symbols
		first time. So that clip can be set for
		curves once rest is gone */

	/* do not send symbols first time for 2 reasons*/
	/* 1. optimization reasons only for the psf printer */
	/* 2. more importantly, if symbols are interspersed with
	 *	curve segments, start point of lines gets disturbed 
	 *	in continuous line segments mode
	*/

      	while (ob < curobj)
	{
		if ((obj[ob])->name == objflagcurves)
		{
			firstcurves = TRUE;
			clip();/* in plotcur.c */
			ClipOn = TRUE;
		}
		else if ((obj[ob])->name == objflag)
		{
			firstcurves = FALSE;	
			noclip();
			ClipOn = FALSE;
		}
		
		if ((!firstcurves)||((obj[ob])->name != objsymbol))
			 /*do not send symbols first time */
		{
			if ((obj[ob])->name == objtext)
				HandleSpecialText(obj[ob]);
			if ((obj[ob])->scale) scaleobj(obj[ob]);
			sendintermediate(obj[ob]);
		}
		ob++;
	}
	/* Now day of the symbols */
	ob = 0;
      	while (ob < curobj)
	{
		if ((obj[ob])->name == objflagcurves)
		{
			firstcurves = TRUE;
			clip();
			ClipOn = TRUE;
		}
		else if ((obj[ob])->name == objflag)
		{
			firstcurves = FALSE;	
			noclip();
			ClipOn = FALSE;
		}

		if ((firstcurves)&&((obj[ob])->name == objsymbol))
		{
			if ((obj[ob])->scale) scaleobj(obj[ob]);
			sendintermediate(obj[ob]);
		}
		ob++;
	}
}


static double XMLMT, YMLMT;/*x max limit and y max limit */

sendintermediate(p)
LocalObjectType *p;
{
Boolean Clipped = FALSE;


	XMLMT = translate + graphsize[xpt] * 72.0 / 2.54;
	YMLMT = translate + graphsize[ypt] * 72.0 / 2.54;
	/* Do clipping here for XView or IView only*/
	/* note symbols outside limits are clipped */
	/* text not clipped */



	if ((XView || IView)&&(ClipOn)) switch (p->name)
	{
	   case objCurLine:
	   case objline:
		if (
		    (
		     (p->from[xpt] >= translate)&&
		     (p->from[ypt] >= translate)
		    )&&
		    (
		     (p->from[xpt] <= XMLMT)&&
		     (p->from[ypt] <= YMLMT)
		    )&&
		    (
		     (p->un.line.to[xpt] >= translate)&&
		     (p->un.line.to[ypt] >= translate)
		    )&&
		    (
		     (p->un.line.to[xpt] <= XMLMT)&&
		     (p->un.line.to[ypt] <= YMLMT)
		    )
		   )
			Clipped = FALSE;/* both points in */
		else if 
		   (
		    (
		     (
		      (p->from[xpt] >= translate)&&
		      (p->from[ypt] >= translate)
		     )&&
		     (
		      (p->from[xpt] <= XMLMT)&&
		      (p->from[ypt] <= YMLMT)
		     )
		    )||
		    ( 
		     (
		      (p->un.line.to[xpt] >= translate)&&
		      (p->un.line.to[ypt] >= translate)
		     )&&
		     (
		      (p->un.line.to[xpt] <= XMLMT)&&
		      (p->un.line.to[ypt] <= YMLMT)
		     )
		    )
		   )
		{
			Clipped = FALSE;
			TruncLine(p);/* one point in */

		}
		else
			Clipped = TRUE; /* both points out */
	   break;
	   case objsymbol:
		if (
		    (
		     (p->from[xpt] < translate)||
		     (p->from[ypt] < translate)
		    )||
		    (
		     (p->from[xpt] > XMLMT)||
		     (p->from[ypt] > YMLMT)
		    )
		   )
			Clipped = TRUE;/* point out of bounds */
		else 
			Clipped = FALSE;
	   break;
	   default:
	   break;

	}
	if (!Clipped) 
		if (XView) sendx(p);
		else if (IView) sendi(p);
		else sendpsf(p);
}


TruncLine(p)
LocalObjectType *p;
{
double IntrpX(), IntrpY();

	if (p->from[xpt] < translate)
	{
		p->from[ypt] = IntrpX(translate,p->from[xpt],p->from[ypt],p->un.line.to[xpt],p->un.line.to[ypt]);
		p->from[xpt] = translate;
	}
	if (p->un.line.to[xpt] > XMLMT)
	{
		p->un.line.to[ypt] = IntrpX(XMLMT,p->from[xpt],p->from[ypt],p->un.line.to[xpt],p->un.line.to[ypt]);
		p->un.line.to[xpt] = XMLMT;
	}


	if (p->from[ypt] < translate)
	{
		p->from[xpt] = IntrpY(translate,p->from[xpt],p->from[ypt],p->un.line.to[xpt],p->un.line.to[ypt]);
		p->from[ypt] = translate;
	}
	if (p->un.line.to[ypt] > YMLMT)
	{
		p->un.line.to[xpt] = IntrpY(YMLMT,p->from[xpt],p->from[ypt],p->un.line.to[xpt],p->un.line.to[ypt]);
		p->un.line.to[ypt] = YMLMT;
	}



	if (p->from[xpt] > XMLMT)
	{
		p->from[ypt] = IntrpX(XMLMT,p->from[xpt],p->from[ypt],p->un.line.to[xpt],p->un.line.to[ypt]);
		p->from[xpt] = XMLMT;
	}
	if (p->un.line.to[xpt] < translate)
	{
		p->un.line.to[ypt] = IntrpX(translate,p->from[xpt],p->from[ypt],p->un.line.to[xpt],p->un.line.to[ypt]);
		p->un.line.to[xpt] = translate;
	}


	if (p->from[ypt] > YMLMT)
	{
		p->from[xpt] = IntrpY(YMLMT,p->from[xpt],p->from[ypt],p->un.line.to[xpt],p->un.line.to[ypt]);
		p->from[ypt] = YMLMT;
	}
	if (p->un.line.to[ypt] < translate)
	{
		p->un.line.to[xpt] = IntrpY(translate,p->from[xpt],p->from[ypt],p->un.line.to[xpt],p->un.line.to[ypt]);
		p->un.line.to[ypt] = translate;
	}
}


double IntrpX(x,x1,y1,x2,y2)
double x,x1,y1,x2,y2;
{
double y;
	if (x2 != x1)
		y = y1 + ((x-x1)*(y2-y1)/(x2-x1));
	else
		y = (y1+y2) / 2.0;
	return(y);
}

double IntrpY(y,x1,y1,x2,y2)
double y,x1,y1,x2,y2;
{
double x;
	if (y2 != y1)
		x = x1 + ((y-y1)*(x2-x1)/(y2-y1));
	else
		x = (x1+x2) / 2.0;
	return(x);
}


/* used earlier for debugging. No longer valid */
sendobjold()
{
boolean firstcurves = TRUE;
/* curobj has first invalid object */
int ob=0;/* obj under consideration */
	while (ob < curobj)
	{
		if (((obj[ob])->name == objflagcurves) && (firstcurves)) 
		{
			clip();
			firstcurves = FALSE;
		}
		if ((obj[ob])->scale) scaleobj(obj[ob]);
		sendintermediate(obj[ob]);
		/* now output psf stuff */
		switch ((obj[ob])->name)
		{
			case objtext:
			{
			printf("\n");
			printf("OBJECT #%d TEXT\n",ob);
			printf("fontfamily      =%s\n",(obj[ob])->un.text.FF);
			printf("fontsize	=%d\n",(obj[ob])->un.text.fontsize);
			printf("scale 		=%d\n",(obj[ob])->scale);
			printf("TEXT: %s\n",(obj[ob])->un.text.StrPtr);
			printf("pos		=%f,%f\n",(obj[ob])->from[xpt],(obj[ob])->from[ypt]);
			printf("angle		=%f\n",(obj[ob])->un.text.angle);
			printf("align		=%d\n",(obj[ob])->un.text.align);
				break;
			}
			case objsymbol:
			{
			printf("\n");
			printf("OBJECT #%d SYMBOL\n",ob);
			printf("fontsize	=%d\n",(obj[ob])->un.symbol.fontsize);
			printf("scale 		=%d\n",(obj[ob])->scale);
			printf("pos		=%f,%f\n",(obj[ob])->from[xpt],(obj[ob])->from[ypt]);
				break;
			}
			case objline:
			{
			printf("\n");
			printf("OBJECT #%d LINE\n",ob);
			printf("linetype	=%d\n",(obj[ob])->un.line.line);
			printf("thickness	=%d\n",(obj[ob])->un.line.thick);
			printf("scale 		=%d\n",(obj[ob])->scale);
			printf("from		=%f,%f\n",(obj[ob])->from[xpt],(obj[ob])->from[ypt]);
			printf("to		=%f,%f\n",(obj[ob])->un.line.to[xpt],(obj[ob])->un.line.to[ypt]);
				break;
			}
			default:
			break;
		}
		ob++;
	}
}

