/* Steven Andrews, version 1 written 10/31/90; modified 8/6/96	*//* Modified to work with MetroWerks C and on a color computer 9/9/98	*//* See documentation called Plot doc *//* Copyright 2003 by Steven Andrews.  Permission is granted   for non-commercial use of and modifications to the code. */#include <Types.h>#include <Memory.h>#include <Quickdraw.h>#include <Fonts.h>#include <Events.h>#include <Menus.h>#include <Windows.h>#include <TextEdit.h>#include <Dialogs.h>#include <OSUtils.h>#include <ToolUtils.h>#include <SegLoad.h>#include <Sound.h>#include <limits.h>#include <float.h>#include <stdio.h>#include <math.h>#include "Plot.h"#include "random.h"#include "string2.h"float xmin=-10.0,xmax=10.0,ymin=-10.0,ymax=10.0;WindowPtr output;Rect wBounds;void InitPlot() {	#if TARGET_API_MAC_CARBON		InitCursor();	#else		OSErr error;		SysEnvRec theWorld;				error=SysEnvirons(1,&theWorld);		if(theWorld.hasColorQD==false)	{			SysBeep(50);			ExitToShell(); }		InitGraf(&qd.thePort);		InitFonts();		InitWindows();		InitMenus();		TEInit();		InitDialogs(nil);		InitCursor();	#endif	return; }void EndPlot() {	EndUpdate(output); }void MakeWindow(float left,float right,float top,float bottom) {	#if TARGET_API_MAC_CARBON		BitMap theScreenBits;	#endif	Rect r;		#if TARGET_API_MAC_CARBON		GetQDGlobalsScreenBits(&theScreenBits);		r=theScreenBits.bounds;	#else		r=qd.screenBits.bounds;	#endif	wBounds.left=(r.right-r.left)*left+r.left;	wBounds.right=(r.right-r.left)*right+r.left;	wBounds.top=(r.bottom-r.top)*top+r.top;	wBounds.bottom=(r.bottom-r.top)*bottom+r.top;	output=NewCWindow(nil,&wBounds,"\pOutput",true,documentProc,(WindowPtr)(-1),false,0);	#if TARGET_API_MAC_CARBON		SetPortWindowPort(output);	#else		SetPort(output);	#endif	BeginUpdate(output);	return; }void KillWindow() {	DisposeWindow(output); }void InvalPlot() {	struct Rect r;	#if TARGET_API_MAC_CARBON		GetWindowPortBounds(output,&r);		InvalWindowRect(output,&r);	#else		r=(*qd.thePort).portRect;		InvalRect(&r);	#endif	return; }void SetScales(float xa,float xb,float ya,float yb) {	if(xa>=-FLT_MAX&&xa<=FLT_MAX) xmin=xa;	if(xb>=-FLT_MAX&&xb<=FLT_MAX) xmax=xb;	if(ya>=-FLT_MAX&&ya<=FLT_MAX) ymin=ya;	if(yb>=-FLT_MAX&&yb<=FLT_MAX) ymax=yb; }void GetScales(float *xa,float *xb,float *ya,float *yb) {	*xa=xmin;	*xb=xmax;	*ya=ymin;	*yb=ymax; }void ScalePtrs(float **xa,float **xb,float **ya,float **yb) {	*xa=&xmin;	*xb=&xmax;	*ya=&ymin;	*yb=&ymax; }void SetColor(char c) {	RGBColor x;		if(c=='A'||c=='a')	{x.red=0x7000;x.green=0xdb00;x.blue=0x9300;}							/* aqua			*/	else if(c=='B'||c=='b'||c=='6')	{x.red=0x0000;x.green=0x0000;x.blue=0xffff;}	/* blue			*/	else if(c=='C'||c=='c')	{x.red=0x0000;x.green=0xffff;x.blue=0xffff;}					/* cyan			*/	else if(c=='D'||c=='d')	{x.red=0x8000;x.green=0x0000;x.blue=0x0000;}					/* dark red	*/	else if(c=='E'||c=='e'||c=='8')	{x.red=0x8000;x.green=0x8000;x.blue=0x8000;}	/* grey			*/	else if(c=='F'||c=='f')	{x.red=0xff00;x.green=0x6e00;x.blue=0xc700;}					/* fuchsia	*/	else if(c=='G'||c=='g')	{x.red=0x0000;x.green=0xffff;x.blue=0x0000;}					/* green		*/	else if(c=='H'||c=='h'||c=='5')	{x.red=0x0000;x.green=0x8000;x.blue=0x0000;}	/* hunter		*/	else if(c=='I'||c=='i')	{x.red=0xdb00;x.green=0x7000;x.blue=0xdb00;}					/* indigo		*/	else if(c=='J'||c=='j')	{x.red=0x8000;x.green=0x8000;x.blue=0x0000;}					/* olive		*/	else if(c=='K'||c=='k'||c=='0')	{x.red=0x0000;x.green=0x0000;x.blue=0x0000;}	/* black		*/	else if(c=='L'||c=='l')	{x.red=0x3200;x.green=0xcd00;x.blue=0x3200;}					/* lime			*/	else if(c=='M'||c=='m')	{x.red=0xffff;x.green=0x0000;x.blue=0xffff;}					/* magenta	*/	else if(c=='N'||c=='n')	{x.red=0x0000;x.green=0x0000;x.blue=0x8000;}					/* navy			*/	else if(c=='O'||c=='o'||c=='3')	{x.red=0xffff;x.green=0xaf00;x.blue=0x0000;}	/* orange		*/	else if(c=='P'||c=='p')	{x.red=0x8000;x.green=0x0000;x.blue=0x8000;}					/* purple		*/	else if(c=='Q'||c=='q')	{x.red=0xd900;x.green=0xd900;x.blue=0xf300;}					/* quartz		*/	else if(c=='R'||c=='r'||c=='2')	{x.red=0xffff;x.green=0x0000;x.blue=0x0000;}	/* red			*/	else if(c=='S'||c=='s')	{x.red=0x8e00;x.green=0xdb00;x.blue=0x2300;}					/* sienna		*/	else if(c=='T'||c=='t')	{x.red=0x0000;x.green=0x8000;x.blue=0x8000;}					/* teal			*/	else if(c=='U'||c=='u')	{x.red=0x2000;x.green=0x0000;x.blue=0x2000;}					/* ultraviolet */	else if(c=='V'||c=='v'||c=='7')	{x.red=0xee00;x.green=0x8200;x.blue=0xee00;}	/* violet		*/	else if(c=='W'||c=='w'||c=='9')	{x.red=0xffff;x.green=0xffff;x.blue=0xffff;}	/* white		*/	else if(c=='X'||c=='x')	{x.red=intrand(0xffff);x.green=intrand(0xffff);x.blue=intrand(0xffff);}	/* random	*/	else if(c=='Y'||c=='y'||c=='4')	{x.red=0xffff;x.green=0xffff;x.blue=0x0000;}	/* yellow		*/	else if(c=='Z'||c=='z')	{x.red=intrand(2)*0xffff;x.green=intrand(2)*0xffff;x.blue=intrand(2)*0xffff;}	/* random	*/	else if(c=='1')	{x.red=0x4000;x.green=0x4000;x.blue=0x2000;}									/* brown		*/	else if(c=='-')	{x.red=0xc000;x.green=0xc000;x.blue=0xc000;}									/* silver		*/	else if(c=='+')	{x.red=0xffff;x.green=0xd700;x.blue=0x2000;}									/* gold		*/	else {x.red=0x0000;x.green=0x0000;x.blue=0x0000;}															/* black		*/	RGBForeColor(&x); }void SetPenSize(int w,int h) {	PenSize(w,h);	return; }void ToPixel(float x,float y,int *a,int *b) {	#if TARGET_API_MAC_CARBON		struct Rect r;				GetWindowPortBounds(output,&r);		x=(x-xmin)/(xmax-xmin)*(r.right-r.left)+r.left;		y=(y-ymin)/(ymax-ymin)*(r.top-r.bottom)+r.bottom;	#else		x=(x-xmin)/(xmax-xmin)*((*qd.thePort).portRect.right-(*qd.thePort).portRect.left)+(*qd.thePort).portRect.left;		y=(y-ymin)/(ymax-ymin)*((*qd.thePort).portRect.top-(*qd.thePort).portRect.bottom)+(*qd.thePort).portRect.bottom;	#endif	*a=(x>32767)?32767:((x<-32767)?-32767:x);	*b=(y>32767)?32767:((y<-32767)?-32767:y);	return; }int ToPoint(int a,int b,float *x,float *y) {	#if TARGET_API_MAC_CARBON		struct Rect r;				GetWindowPortBounds(output,&r);		*x=(a-r.left)*(xmax-xmin)/(r.right-r.left)+xmin;		*y=(b-r.bottom)*(ymax-ymin)/(r.top-r.bottom)+ymin;	#else		*x=(a-(*qd.thePort).portRect.left)*(xmax-xmin)/((*qd.thePort).portRect.right-(*qd.thePort).portRect.left)+xmin;		*y=(b-(*qd.thePort).portRect.bottom)*(ymax-ymin)/((*qd.thePort).portRect.top-(*qd.thePort).portRect.bottom)+ymin;	#endif	if(*x<xmin||*x>xmax||*y<ymin||*y>ymax) return 0;	else return 1; }void DrawAxes() {	int a=0,b=0;		ToPixel(xmin,0,&a,&b);	MoveTo(a,b);	ToPixel(xmax,0,&a,&b);	LineTo(a,b);	ToPixel(0,ymin,&a,&b);	MoveTo(a,b);	ToPixel(0,ymax,&a,&b);	LineTo(a,b); }void DrawMarks(float dx,float dy,int lo,int hi) {	float t,f1,f2;	int a,b;	dx=fabs(dx);	dy=fabs(dy);	f1=dx*floor((xmin<xmax?xmin:xmax)/dx);	f2=dx*ceil((xmin<xmax?xmax:xmin)/dx);	for(t=f1;t<=f2;t+=dx)	{		ToPixel(t,0,&a,&b);		MoveTo(a,b-hi);		LineTo(a,b+lo); }	f1=dy*floor((ymin<ymax?ymin:ymax)/dy);	f2=dy*ceil((ymin<ymax?ymax:ymin)/dy);	for(t=f1;t<=f2;t+=dy)	{		ToPixel(0,t,&a,&b);		MoveTo(a-lo,b);		LineTo(a+hi,b); }	return; }void PlotClear() {	int a,b,c,d;	Rect r;		ToPixel(xmin,ymin,&a,&b);	ToPixel(xmax,ymax,&c,&d);	r.top=d;	r.left=a;	r.bottom=b;	r.right=c;	EraseRect(&r); }void PlotMove(float x,float y) {	int a,b;	ToPixel(x,y,&a,&b);	MoveTo(a,b); }void PlotPt(float x,float y) {	int a,b;		ToPixel(x,y,&a,&b);	MoveTo(a,b);	LineTo(a,b); }void PlotLine(float x,float y) {	int a,b;		ToPixel(x,y,&a,&b);	LineTo(a,b); }void PlotStr(float x,float y,char *s) {	int a,b;	unsigned char *s2;		ToPixel(x,y,&a,&b);	MoveTo(a,b);	s2=PascalString(s);	if(s2)	{		TextSize(9);		DrawString(s2);		free(s2); }	return; }void ShowLimits() {	int a,b,i;	char *s;	unsigned char *ps;		s=EmptyString();	if(!s) return;	i=0;	s[i++]='(';	i+=sprintf(s+i,"%1.2f",xmin);	s[i++]=',';	i+=sprintf(s+i,"%1.2f",ymin);	s[i++]=')';	ps=PascalString(s);	if(ps)	{		TextSize(9);		ToPixel(xmin,ymin,&a,&b);		a+=10;		b-=10;		MoveTo(a,b);		DrawString(ps);		free(ps);	}	i=0;	s[i++]='(';	i+=sprintf(s+i,"%1.2f",xmax);	s[i++]=',';	i+=sprintf(s+i,"%1.2f",ymax);	s[i++]=')';	s[i++]='\0';	ps=PascalString(s);	if(ps)	{		ToPixel(xmax,ymax,&a,&b);		a-=6*i;		b+=20;		MoveTo(a,b);		DrawString(ps);		free(ps); }	free(s);		return; }void PlotFn(float (*fn)(float),float dx) {	int a,b;	float x;		ToPixel(xmin,(*fn)(xmin),&a,&b);	MoveTo(a,b);	for(x=xmin;x<xmax;x+=dx) {		ToPixel(x,(*fn)(x),&a,&b);		LineTo(a,b); }	return; }void PlotInt(float (*fn)(float),float x0,float dx) {	float x,y;	int a,b;		y=0;	ToPixel(x0,0,&a,&b);	MoveTo(a,b);	for(x=x0-dx;x>=xmin;x-=dx)	{		y-=(*fn)(x+dx/2)*dx;		ToPixel(x,y,&a,&b);		LineTo(a,b); }	y=0;	ToPixel(x0,0,&a,&b);	MoveTo(a,b);	for(x=x0+dx;x<=xmax;x+=dx) {		y+=(*fn)(x-dx/2)*dx;		ToPixel(x,y,&a,&b);		LineTo(a,b); }	return; }void PlotData(float *data,int n,float xmin,float xmax,int style) {	int i,a,b,b0;	float x;		// style 1 is bars, 2 is dots, 3 is line		ToPixel(xmin,data[0],&a,&b);	MoveTo(a,b);	for(i=0;i<n;i++)	{		x=(xmax-xmin)*i/(n-1)+xmin;		ToPixel(x,0,&a,&b0);		ToPixel(x,data[i],&a,&b);		switch(style)	{			case 1:				MoveTo(a,b0);				break;			case 2:				MoveTo(a,b);				break;			case 3:				break; }		LineTo(a,b); }	return; }void PlotData2(float *data,float *x,int n,int style) {	int i,a,b,b0;	// style 1 is bars, 2 is dots, 3 is line	ToPixel(x[0],data[0],&a,&b);	MoveTo(a,b);	for(i=0;i<n;i++)	{		ToPixel(x[i],0,&a,&b0);		ToPixel(x[i],data[i],&a,&b);		switch(style)	{			case 1:				MoveTo(a,b0);				break;			case 2:				MoveTo(a,b);				break;			case 3:				break; }		LineTo(a,b); }	return; }void PlotData3(float *x,float *y,int *ct,int col) {	int i,j,a,b;	char c;	Rect r;	c='a';	for(j=0;j<col;j++) {		if(j==0) SetColor('2');		else if(j==1) SetColor('5');		else if(j==2) SetColor('6');		else SetColor(c++);		for(i=0;i<ct[j];i++) {			ToPixel(x[col*i+j],y[col*i+j],&a,&b);			r.left=a;			r.top=b;			r.right=a+10;			r.bottom=b+10;			PaintOval(&r); }}	return; }	
