home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Fred Fish Collection 1.5
/
ffcollection-1-5-1992-11.iso
/
ff_disks
/
300-399
/
ff391.lzh
/
ListPlot
/
Csrc
/
plotting.c
< prev
Wrap
C/C++ Source or Header
|
1990-10-27
|
25KB
|
1,165 lines
/*
* plotting.c
*
* plotting routines.
*
*/
#include <stdio.h>
#include <errno.h>
extern int errno;
#include <assert.h>
#include <string.h>
#include <ctype.h>
#include <signal.h>
#include "datatypes.h"
void ErrorExit();
#ifndef min
# define min(A,B) A<B? A : B
#endif
#ifndef max
# define max(A,B) A>B? A : B
#endif
extern bool GraphicsInProgress;
/* GoldenRatio = (1+Sqrt(5))/2 */
#define GOLDENRATIO 1.6180339887499
#define ASPECTRATIO 1.0/GOLDENRATIO
extern VALUE V_AngularUnit;
extern VALUE V_AnnotationScale;
extern VALUE V_AspectRatio;
extern VALUE V_Boxed;
extern VALUE V_Domain;
extern VALUE V_Gridding;
extern VALUE V_LabelScale;
extern VALUE V_LineColor;
extern VALUE V_LineStyle;
extern VALUE V_Orientation;
extern VALUE V_Origin;
extern VALUE V_PlotColor;
extern VALUE V_PlotDevice;
extern VALUE V_PlotJoined;
extern VALUE V_PlotPoints;
extern VALUE V_PlotTitle;
extern VALUE V_PlotType;
extern VALUE V_PointScale;
extern VALUE V_PointSymbol;
extern VALUE V_PolarVariable;
extern VALUE V_Range;
extern VALUE V_SubPages;
extern VALUE V_SupplyAbscissa;
extern VALUE V_TitleScale;
extern VALUE V_UseInputFile;
extern VALUE V_Verbose;
extern VALUE V_ViewPort;
extern VALUE V_XLabel;
extern VALUE V_XTick;
extern VALUE V_YLabel;
extern VALUE V_YTick;
char *DeviceTypes[] = {
"amiga",
"printer",
"iff",
"hp",
"aegis",
"postscript",
(char *)NULL
};
typedef struct line_style {
int ls_type;
int ls_nelms;
int *ls_space;
int *ls_mark;
} LINESTYLE;
LIST LineStyleList;
LINESTYLE *LineStyles; int NLineStyles;
int *PointCodes, NPointCodes;
int space0 = 0, mark0 = 0, space1 = 1500, mark1 = 1500;
RECT UserRect;
RECT ViewPort = { 0.1,0.1, 0.9,0.9 };
RECT WorldRect = {0.0,0.0, 1.0,1.0};
void
ListPlot(Data, NTuples, TupleSize)
FLOAT **Data;
int NTuples, TupleSize;
{
void InitializeDevice();
void InitializePlottingEnv();
#ifdef ANSI_C
void Plot2D(FLOAT **, int , int );
void PolarPlot(FLOAT **, int , int );
#else
void Plot2D();
void PolarPlot();
#endif
InitializeDevice();
GraphicsInProgress = TRUE;
InitializePlottingEnv(Data, NTuples, TupleSize);
if (Vstrcmp(V_PlotType,"polar")) {
PolarPlot(Data, NTuples, TupleSize);
} else {
Plot2D(Data, NTuples, TupleSize);
}
plend();
}
void
InitializeDevice()
{
register int i;
register char *DeviceStr;
plorient(Vstrcmp(V_Orientation, "portrait")? 1 : 0);
plselect(stdout); /* write to stdout */
DeviceStr = V_PlotDevice.val_u.udt_string;
for (i=0; DeviceTypes[i]; i++)
if (strcmp(DeviceStr, DeviceTypes[i]) == 0) {
plbeg(
i+1, /* device code */
(int)V_SubPages.val_u.udt_interval.int_lo, /* nx */
(int)V_SubPages.val_u.udt_interval.int_hi /* ny */
);
return;
}
fprintf(stderr,"(InitializeDevice) Unknown device type: %s\n", DeviceStr);
ErrorExit();
}
void
InitializePlottingEnv(Data, NTuples, TupleSize)
FLOAT **Data;
int NTuples;
int TupleSize;
{
int i, j;
FLOAT *Ptr;
void InitLineStyles();
void InitPointCodes();
/* viewport */
ViewPort = VtoRect(V_ViewPort);
/* user window */
UserRect.XMin = MAX_FLOAT;
UserRect.YMin = MAX_FLOAT;
UserRect.XMax = -MAX_FLOAT;
UserRect.YMax = -MAX_FLOAT;
if (VtoBoolean(V_SupplyAbscissa)) {
UserRect.XMin = 0.0;
UserRect.XMax = (FLOAT)(NTuples-1);
} else {
for (i=0; i<NTuples; i++) {
if (Data[i][0] < UserRect.XMin)
UserRect.XMin = Data[i][0];
if (Data[i][0] > UserRect.XMax)
UserRect.XMax = Data[i][0];
}
}
for (i=0; i<NTuples; i++)
for (j=TupleSize-1,Ptr= &Data[i][1]; j>0; --j,Ptr++) {
if (*Ptr < UserRect.YMin)
UserRect.YMin = *Ptr;
if (*Ptr > UserRect.YMax)
UserRect.YMax = *Ptr;
}
/* font scaling */
/* plot type */
/* grid */
/* line styles */
InitLineStyles();
/* line colors */
/* point symbols */
InitPointCodes();
/* window type */
/* X label */
/* Y label */
/* Plot title */
/* aspect ratio */
}
#define isMark(C) (((C) == 'M' || (C) == 'm')? TRUE : FALSE)
#define isSpace(C) (((C) == 'S' || (C) == 's')? TRUE : FALSE)
#define MarkLength(C) (C) == 'M'? 1000 : 250
#define SpaceLength(C) (C) == 'S'? 1000 : 250
#define MAX_MARKS 32
void
DecodeLineStyle(StyleStr, Mark, Space, N)
char *StyleStr;
int **Mark;
int **Space;
int *N;
{
register char *S;
int macc, sacc;
int i, j, k;
int mark[MAX_MARKS];
int space[MAX_MARKS];
bool ProcessingMark;
/*
* 'S' = 1000 micron space
* 's' = 250 micron space
* 'M' = 1000 micron line
* 'm' = 250 micron line
*/
ProcessingMark = TRUE; /* to satisfy some compilers */
if (isMark(*StyleStr))
ProcessingMark = TRUE;
else if (isSpace(*StyleStr))
ProcessingMark = FALSE;
else {
fprintf(stderr,"(DecodeLineStyle) Invalid Line style: \"%s\"\n", StyleStr);
ErrorExit();
}
memset((char *)mark, 0, MAX_MARKS * sizeof(int));
memset((char *)space, 0, MAX_MARKS * sizeof(int));
for (macc=0,sacc=0,i=0,j=0,S=StyleStr ; *S && i<MAX_MARKS && j<MAX_MARKS; ++S) {
if (isMark(*S) && ProcessingMark) {
macc += MarkLength(*S);
} else if (isMark(*S) && !ProcessingMark) {
space[j++] = sacc;
macc = MarkLength(*S);
ProcessingMark = TRUE;
} else if (isSpace(*S) && ProcessingMark) {
mark[i++] = macc;
sacc = SpaceLength(*S);
ProcessingMark = FALSE;
} else if (isSpace(*S) && !ProcessingMark) {
sacc += SpaceLength(*S);
} else if (isspace(*S)) {
continue;
} else {
fprintf(stderr,"(DecodeLineStyle) Invalid line style code '%c' in \"%s\"\n", *S, StyleStr);
ErrorExit();
}
}
if (ProcessingMark)
mark[i++] = macc;
else
space[j++] = sacc;
k = max(i,j);
if (((*Mark) = (int *)calloc(k, sizeof(int))) == (int *)NULL) {
perror("(DecodeLineStyle) ");
ErrorExit();
}
if (((*Space) = (int *)calloc(k, sizeof(int))) == (int *)NULL) {
perror("(DecodeLineStyle) ");
ErrorExit();
}
for (i=0; i<k; i++) {
(*Mark)[i] = mark[i];
(*Space)[i] = space[i];
}
*N = k;
}
void
InitLineStyles()
{
int i;
LATOM *A;
LINESTYLE *LS;
int *Mark, *Space;
int N;
#ifdef ANSI_C
LINESTYLE *LSAlloc(int , int *, int *);
#else
LINESTYLE *LSAlloc();
#endif
LineStyleList.list_n = 0;
LineStyleList.list_head = (LATOM *)NULL;
LineStyleList.list_tail = (LATOM *)NULL;
LS = LSAlloc(0, (int *)NULL, (int *)NULL);
Append(&LineStyleList, (generic *)LS);
for (i=1,A=V_LineStyle.val_u.udt_set.list_head; A; A=A->la_next,i++) {
DecodeLineStyle(
(char *)A->la_p,
&Mark,
&Space,
&N
);
LS = LSAlloc(N, Mark, Space);
Append(&LineStyleList, (generic *)LS);
}
NLineStyles = i;
if ((LineStyles = (LINESTYLE *)calloc(NLineStyles, sizeof(LINESTYLE))) == (LINESTYLE *)NULL) {
perror("(InitLineStyles) ");
ErrorExit();
}
for (i=0,A=LineStyleList.list_head; A; A=A->la_next,i++) {
LineStyles[i].ls_mark = ((LINESTYLE *)(A->la_p))->ls_mark;
LineStyles[i].ls_space = ((LINESTYLE *)(A->la_p))->ls_space;
LineStyles[i].ls_nelms = ((LINESTYLE *)(A->la_p))->ls_nelms;
}
}
LINESTYLE *
LSAlloc(n, Mark, Space)
int n;
int *Mark, *Space;
{
register LINESTYLE *LS;
if ((LS = (LINESTYLE *)calloc(1, sizeof(LINESTYLE))) == (LINESTYLE *)NULL) {
perror("(LSAlloc) ");
assert(LS != (LINESTYLE *)NULL);
exit(errno);
}
LS->ls_mark = Mark;
LS->ls_space = Space;
LS->ls_nelms = n;
return(LS);
}
void
InitPointCodes()
{
register LATOM *A;
register int i;
extern int *PointCodes, NPointCodes;
extern VALUE V_PointSymbol;
if (!isSet(V_PointSymbol)) {
NPointCodes = 0;
return;
}
/* count # codes */
for (i=0,A=V_PointSymbol.val_u.udt_set.list_head; A; A=A->la_next, i++)
;
NPointCodes = i;
if (NPointCodes == 0)
return;
if ((PointCodes = (int *)calloc(NPointCodes, sizeof(int))) == (int *)NULL) {
perror("(InitPointCodes) ");
assert(PointCodes != (int *)NULL);
ErrorExit();
}
for (i=0,A=V_PointSymbol.val_u.udt_set.list_head; A; A=A->la_next, i++) {
PointCodes[i] = atoi((char *)A->la_p);
}
}
void
Plot2D(Data, NTuples, TupleSize)
FLOAT **Data;
int NTuples;
int TupleSize;
{
int i, j;
FLOAT *X, *Y;
FLOAT x, y;
FLOAT x0, y0;
FLOAT xtick, ytick;
FLOAT Xmin,Xmax, Ymin,Ymax;
FLOAT MedianX, StdDevX;
FLOAT MedianY, StdDevY;
int nxsub, nysub;
bool AutoRange, AutoDomain;
bool LogX, LogY;
char Xopt[16], Yopt[16];
#ifdef ANSI_C
void StatisticsOfX(
FLOAT **,
int,
int ,
FLOAT *,
FLOAT *
);
void StatisticsOfY(
FLOAT **,
int,
int ,
FLOAT *,
FLOAT *
);
double log10(double);
#else
void StatisticsOfX();
void StatisticsOfY();
double log10();
#endif
pladv(0);
ViewPort = VtoRect(V_ViewPort);
if (isString(V_AspectRatio)) {
/* automatic --> STRETCH */
plvpor(ViewPort.XMin, ViewPort.XMax, ViewPort.YMin, ViewPort.YMax);
/*debug
plvsta();
debug*/
} else {
assert(isDbl(V_AspectRatio));
plvasp(VtoDbl(V_AspectRatio));
}
LogX = (Vstrcmp(V_PlotType, "loglin") || Vstrcmp(V_PlotType,"loglog"))?
TRUE : FALSE;
LogY = (Vstrcmp(V_PlotType, "linlog") || Vstrcmp(V_PlotType,"loglog"))?
TRUE : FALSE;
/* window bounds */
AutoDomain = FALSE;
if (isString(V_Domain) && Vstrcmp(V_Domain, "All")) {
/* all points */
Xmin = UserRect.XMin;
Xmax = UserRect.XMax;
} else if (isString(V_Domain) && Vstrcmp(V_Domain,"Automatic")) {
/* automatic */
AutoDomain = TRUE;
StatisticsOfX(Data, NTuples, TupleSize, &MedianX, &StdDevX);
x = MedianX - 3.0*StdDevX;
Xmin = UserRect.XMin < x? x : UserRect.XMin;
x = MedianX + 3.0*StdDevX;
Xmax = UserRect.XMax > x? x : UserRect.XMax;
} else {
assert(isInterval(V_Domain));
Xmin = V_Domain.val_u.udt_interval.int_lo;
Xmax = V_Domain.val_u.udt_interval.int_hi;
}
if (LogX) {
if (Xmin == 0.0 || Xmax == 0.0) {
/* error */
fprintf(stderr,"ListPlot: Trying to find log10(0) in data! Stop.\n");
ErrorExit();
}
Xmin = log10((double)Xmin);
Xmax = log10((double)Xmax);
}
AutoRange = FALSE;
if (isString(V_Range) && Vstrcmp(V_Range, "All")) {
/* all */
Ymin = UserRect.YMin;
Ymax = UserRect.YMax;
} else if (isString(V_Range) && Vstrcmp(V_Range,"Automatic")) {
/* automatic */
AutoRange = TRUE;
StatisticsOfY(Data, NTuples, TupleSize, &MedianY, &StdDevY);
y = MedianY - 3.0*StdDevY;
Ymin = UserRect.YMin < y? y : UserRect.YMin;
y = MedianY + 3.0*StdDevY;
Ymax = UserRect.YMax > y? y : UserRect.YMax;
} else {
assert(isInterval(V_Range));
Ymin = V_Range.val_u.udt_interval.int_lo;
Ymax = V_Range.val_u.udt_interval.int_hi;
}
if (LogY) {
if (Ymin == 0.0 || Ymax == 0.0) {
/* error */
fprintf(stderr,"ListPlot: Trying to find log10(0) in data! Stop.\n");
ErrorExit();
}
Ymin = log10((double)Ymin);
Ymax = log10((double)Ymax);
}
plwind(
Xmin,
Xmax,
Ymin,
Ymax
);
plschr(0., VtoDbl(V_AnnotationScale));
/* X and Y ticks */
if (isString(V_XTick)) {
/* automatic */
xtick = 0.;
nxsub = 0;
} else {
xtick = V_XTick.val_u.udt_interval.int_lo;
if (LogX) xtick = log10((double)xtick);
nxsub = V_XTick.val_u.udt_interval.int_hi;
}
if (isString(V_YTick)) {
/* automatic */
ytick = 0.;
nysub = 0;
} else {
ytick = V_YTick.val_u.udt_interval.int_lo;
if (LogY) ytick = log10((double)ytick);
nysub = V_YTick.val_u.udt_interval.int_hi;
}
/* Axis options */
Xopt[0] = (char)NULL;
Yopt[0] = (char)NULL;
if (isBoolean(V_Boxed) && VtoBoolean(V_Boxed)) {
strcat(Xopt, "bc");
strcat(Yopt, "bc");
} else if (isString(V_Boxed)) {
if (Vstrchr(V_Boxed, 'b'))
strcat(Xopt, "b");
if (Vstrchr(V_Boxed, 't'))
strcat(Xopt, "c");
if (Vstrchr(V_Boxed, 'r'))
strcat(Yopt, "c");
if (Vstrchr(V_Boxed, 'l'))
strcat(Yopt, "b");
} else {
;
}
if (LogX)
strcat(Xopt, "l");
if (LogY)
strcat(Yopt, "l");
strcat(Xopt, "nst");
strcat(Yopt, "nstv");
if (isString(V_Origin) && Vstrcmp(V_Origin, "Median")) {
if (AutoDomain == FALSE) {
StatisticsOfX(Data,NTuples,TupleSize,&MedianX,&StdDevX);
}
if (AutoRange == FALSE) {
StatisticsOfY(Data,NTuples,TupleSize,&MedianY,&StdDevY);
}
plaxes(
MedianX,MedianY,
Xopt, xtick, nxsub,
Yopt, ytick,nysub
);
} else if (isInterval(V_Origin)) {
x0 = V_Origin.val_u.udt_interval.int_lo;
y0 = V_Origin.val_u.udt_interval.int_hi;
plaxes(
x0,y0,
Xopt, xtick, nxsub,
Yopt, ytick,nysub
);
} else if (isString(V_Origin) && Vstrcmp(V_Origin, "Automatic")) {
plbox(Xopt, xtick, nxsub, Yopt, ytick,nysub);
} else {
plbox(Xopt, xtick, nxsub, Yopt, ytick,nysub);
}
/* gridding */
if (VtoBoolean(V_Gridding)) {
/* gridding on */
plstyl(1, &mark1, &space1);
plbox("g", xtick, nxsub, "g", ytick,nysub);
plstyl(0, &mark0, &space0);
}
/* plot curves */
if ((X = (FLOAT *)calloc(NTuples, sizeof(FLOAT))) == (FLOAT *)NULL) {
perror("(Plot2D) ");
ErrorExit();
}
if ((Y = (FLOAT *)calloc(NTuples, sizeof(FLOAT))) == (FLOAT *)NULL) {
perror("(Plot2D) ");
ErrorExit();
}
if (VtoBoolean(V_SupplyAbscissa)) {
for (i=0; i<NTuples; i++)
X[i] = LogX? log10((double)(i+1)) : (FLOAT)i;
} else {
for (i=0; i<NTuples; i++)
X[i] = LogX? log10((double)Data[i][0]) : Data[i][0];
}
for (i=1; i<TupleSize; i++) {
if (NLineStyles > 0) {
/* use user-supplied patterns */
plstyl(
LineStyles[(i-1)%NLineStyles].ls_nelms,
LineStyles[(i-1)%NLineStyles].ls_mark,
LineStyles[(i-1)%NLineStyles].ls_space
);
} else {
pllsty((i-1)%8 + 1);
}
plcol(i);
for (j=0; j<NTuples; j++)
Y[j] = LogY? log10((double)Data[j][i]) : Data[j][i];
if (VtoBoolean(V_PlotJoined))
plline(NTuples, X, Y);
if (VtoBoolean(V_PlotPoints)) {
plschr(0., VtoDbl(V_PointScale));
pllsty(1);
if (NPointCodes > 0) {
plpoin(NTuples, X, Y, PointCodes[(i-1)%NPointCodes]);
} else {
plpoin(NTuples, X, Y, i);
}
}
}
/* restore line styles etc... */
pllsty(1);
plcol(1);
plschr(0., VtoDbl(V_LabelScale));
pllab(VtoString(V_XLabel), VtoString(V_YLabel), "");
plschr(0., VtoDbl(V_TitleScale));
pllab("","", VtoString(V_PlotTitle));
}
#define DTR(D) (double)((D)*3.1415927/180.0)
void
PolarPlot(Data, NTuples, TupleSize)
FLOAT **Data;
int NTuples;
int TupleSize;
{
int i, j;
FLOAT *A, *R;
FLOAT x, y;
FLOAT xtick, ytick;
FLOAT atick, rtick;
FLOAT Xmin,Xmax, Ymin,Ymax;
FLOAT r, rmax, ang, amax;
FLOAT MedianX, StdDevX;
FLOAT MedianY, StdDevY;
FLOAT da;
FLOAT x0,y0, xn,yn;
double pi;
char s[32];
int nxsub, nysub, nrsub, nasub;
bool InRadians, XisAngular;
bool AutoDomain, AutoRange;
#ifdef ANSI_C
void StatisticsOfX(
FLOAT **,
int ,
int ,
FLOAT *,
FLOAT *
);
void StatisticsOfY(
FLOAT **,
int ,
int ,
FLOAT *,
FLOAT *
);
double log10(double); double fabs();
double sqrt(), sin(), cos(), atan();
#else
void StatisticsOfX();
void StatisticsOfY();
double log10(); double fabs();
double sqrt(), sin(), cos(), atan();
#endif
pi = 4.0 * atan((double)1.0);
InRadians = Vstrcmp(V_AngularUnit, "degrees")? FALSE : TRUE;
XisAngular = Vstrcmp(V_PolarVariable,"angle")? TRUE : FALSE;
pladv(0);
if (isString(V_AspectRatio)) {
/* automatic --> STRETCH */
plvasp(1.0);
} else {
assert(isDbl(V_AspectRatio));
plvasp(VtoDbl(V_AspectRatio));
}
/* window bounds */
AutoDomain = FALSE;
if (isString(V_Domain) && Vstrcmp(V_Domain, "All")) {
/* all points */
Xmin = UserRect.XMin;
Xmax = UserRect.XMax;
} else if (isString(V_Domain) && Vstrcmp(V_Domain,"Automatic")) {
/* automatic */
AutoDomain = TRUE;
StatisticsOfX(Data, NTuples, TupleSize, &MedianX, &StdDevX);
x = MedianX - 3.0*StdDevX;
Xmin = UserRect.XMin < x? x : UserRect.XMin;
x = MedianX + 3.0*StdDevX;
Xmax = UserRect.XMax > x? x : UserRect.XMax;
} else {
assert(isInterval(V_Domain));
Xmin = V_Domain.val_u.udt_interval.int_lo;
Xmax = V_Domain.val_u.udt_interval.int_hi;
}
AutoRange = FALSE;
if (isString(V_Range) && Vstrcmp(V_Range, "All")) {
/* all */
Ymin = UserRect.YMin;
Ymax = UserRect.YMax;
} else if (isString(V_Range) && Vstrcmp(V_Range,"Automatic")) {
/* automatic */
AutoRange = TRUE;
StatisticsOfY(Data, NTuples, TupleSize, &MedianY, &StdDevY);
y = MedianY - 3.0*StdDevY;
Ymin = UserRect.YMin < y? y : UserRect.YMin;
y = MedianY + 3.0*StdDevY;
Ymax = UserRect.YMax > y? y : UserRect.YMax;
} else {
assert(isInterval(V_Range));
Ymin = V_Range.val_u.udt_interval.int_lo;
Ymax = V_Range.val_u.udt_interval.int_hi;
}
rmax = XisAngular? Ymax : Xmax;
plwind(
-1.3*rmax,
1.3*rmax,
-1.3*rmax,
1.3*rmax
);
/* X and Y ticks */
if (isString(V_XTick)) {
/* automatic */
xtick = XisAngular? (InRadians? pi/6.0 : 30.0) : 0.25 * rmax;
nxsub = 4;
} else {
xtick = V_XTick.val_u.udt_interval.int_lo;
nxsub = V_XTick.val_u.udt_interval.int_hi;
}
if (isString(V_YTick)) {
/* automatic */
ytick = XisAngular? 0.25 * rmax : (InRadians? pi/6.0 : 30.0);
nysub = 4;
} else {
ytick = V_YTick.val_u.udt_interval.int_lo;
nysub = V_YTick.val_u.udt_interval.int_hi;
}
rtick = XisAngular? ytick : xtick;
atick = XisAngular? xtick : ytick;
nasub = XisAngular? nxsub : nysub;
nrsub = XisAngular? nysub : nxsub;
amax = InRadians? 2.0 * pi : 360.0;
/* Axis options */
if (VtoBoolean(V_Gridding)) {
/* draw circles */
plstyl(0, &mark1, space1);
/* circular ticks */
for (i=0,r=(rtick/nrsub); r<rmax; r += (rtick/nrsub),i++) {
da = i%nrsub? 0.05 * atick : 0.1 * atick;
for (ang=0; ang<amax; ang += atick) {
x0 = r * cos(InRadians? ang-da : DTR(ang-da));
y0 = r * sin(InRadians? ang-da : DTR(ang-da));
xn = r * cos(InRadians? ang+da : DTR(ang+da));
yn = r * sin(InRadians? ang+da : DTR(ang+da));
pljoin(x0,y0,xn,yn);
}
}
#ifdef CIRCULAR_TICKS
/* major circles */
for (r=rtick; r<rmax; r += rtick) {
x0 = r; y0 = 0.0;
for (ang=1.0; ang<=360.0; ang++) {
xn = r * cos((double)(DTR(ang)));
yn = r * sin((double)(DTR(ang)));
pljoin(x0,y0,xn,yn);
x0 = xn; y0 = yn;
}
}
#endif
/* draw spokes */
for (i=0,ang=0.0; ang<amax; ang += (atick/nasub),i++) {
xn = rmax * cos(InRadians? ang : DTR(ang));
yn = rmax * sin(InRadians? ang : DTR(ang));
if (i%nasub == 0) {
pljoin((FLOAT)0.0,(FLOAT)0.0,xn,yn);
} else {
pljoin(xn,yn,1.05*xn,1.05*yn);
}
}
}
/* write angle labels */
plschr(0., VtoDbl(V_AnnotationScale));
j = amax / atick;
for (ang=0.0,i=0; i<j; ang += atick,i++) {
if (InRadians) {
xn = rmax * cos((double)ang);
yn = rmax * sin((double)ang);
if (fabs(ang-(2.0*pi)) > 1.0e-2)
sprintf(s, "%.2f #gp", (float)ang/pi);
} else {
xn = rmax * cos((double)DTR(ang));
yn = rmax * sin((double)DTR(ang));
sprintf(s, "%d", (int)(ang+0.5));
}
if (xn >= 0)
plptex(xn,yn,xn,yn,-0.15, s);
else
plptex(xn,yn,-xn,-yn,1.15, s);
}
plstyl(0, &mark0, &space0);
/* plot curves */
if ((A = (FLOAT *)calloc(NTuples, sizeof(FLOAT))) == (FLOAT *)NULL) {
perror("(Plot2D) ");
ErrorExit();
}
if ((R = (FLOAT *)calloc(NTuples, sizeof(FLOAT))) == (FLOAT *)NULL) {
perror("(Plot2D) ");
ErrorExit();
}
if (VtoBoolean(V_SupplyAbscissa)) {
for (i=0; i<NTuples; i++)
if (XisAngular)
A[i] = i*2.0*pi/(NTuples-1);
else
R[i] = i*rmax/(NTuples-1);
} else {
for (i=0; i<NTuples; i++)
if (XisAngular)
A[i] = InRadians? Data[i][0] : DTR(Data[i][0]);
else
R[i] = Data[i][0];
}
for (i=1; i<TupleSize; i++) {
if (NLineStyles > 0) {
/* use user-supplied patterns */
plstyl(
LineStyles[(i-1)%NLineStyles].ls_nelms,
LineStyles[(i-1)%NLineStyles].ls_mark,
LineStyles[(i-1)%NLineStyles].ls_space
);
} else {
pllsty((i-1)%8);
}
plcol(i);
/* get and convert data if necessary */
if (InRadians && !XisAngular)
for (j=0; j<NTuples; j++)
A[j] = Data[j][i];
else if ((!InRadians) && !XisAngular)
for (j=0; j<NTuples; j++)
A[j] = DTR(Data[j][i]);
else
for (j=0; j<NTuples; j++)
R[j] = Data[j][i];
/* convert to cartesian A<->X R<->Y*/
for (j=0; j<NTuples; j++) {
x0 = R[j] * cos(A[j]);
y0 = R[j] * sin(A[j]);
A[j] = x0;
R[j] = y0;
}
if (VtoBoolean(V_PlotJoined)) {
x0 = A[0];
y0 = R[0];
for (j=1; j<NTuples; j++) {
pljoin(A[j-1], R[j-1], A[j],R[j]);
}
}
if (VtoBoolean(V_PlotPoints)) {
plschr(0., VtoDbl(V_PointScale));
pllsty(1);
if (NPointCodes > 0) {
plpoin(NTuples, A, R, PointCodes[(i-1)%NPointCodes]);
} else {
plpoin(NTuples, A, R, i);
}
}
}
/* restore line styles etc... */
pllsty(1);
plcol(1);
plschr(0., VtoDbl(V_LabelScale));
pllab(VtoString(V_XLabel), VtoString(V_YLabel), "");
plschr(0., VtoDbl(V_TitleScale));
pllab("","", VtoString(V_PlotTitle));
}
void
StatisticsOfX(Data, NTuples,TupleSize, Median, StdDev)
FLOAT **Data;
int NTuples;
int TupleSize;
FLOAT *Median;
FLOAT *StdDev;
{
#ifdef ANSI_C
FLOAT MedianOfX();
FLOAT StdDevOfX();
/*debug
FLOAT MedianOfX(FLOAT **Data,int NTuples,int TupleSize);
FLOAT StdDevOfX(FLOAT **Data,int NTuples,int TupleSize);
debug*/
#else
FLOAT MedianOfX();
FLOAT StdDevOfX();
#endif
*StdDev = StdDevOfX(Data,NTuples,TupleSize);
*Median = MedianOfX(Data,NTuples,TupleSize);
}
void
StatisticsOfY(Data, NTuples,TupleSize, Median, StdDev)
FLOAT **Data;
int NTuples;
int TupleSize;
FLOAT *Median;
FLOAT *StdDev;
{
#ifdef ANSI_C
FLOAT MedianOfY();
FLOAT StdDevOfY();
/*debug
FLOAT MedianOfY(FLOAT **Data,int NTuples,int TupleSize);
FLOAT StdDevOfY(FLOAT **Data,int NTuples,int TupleSize);
debug*/
#else
FLOAT MedianOfY();
FLOAT StdDevOfY();
#endif
*StdDev = StdDevOfY(Data,NTuples,TupleSize);
*Median = MedianOfY(Data,NTuples,TupleSize);
}
FLOAT
StdDevOfX(Data,NTuples,TupleSize)
FLOAT **Data;
int NTuples;
int TupleSize;
{
int i;
FLOAT StdDev, x;
FLOAT var, sum, mean;
double sqrt(), fabs();
if (VtoBoolean(V_SupplyAbscissa)) {
return((FLOAT)(NTuples*NTuples)/12.0);
}
sum = 0.0;
for (i=0; i<NTuples; i++)
sum += Data[i][0];
mean = sum / NTuples;
var = 0.0;
for (i=0; i<NTuples; i++) {
x = fabs((double)(Data[i][0] - mean));
var += x * x;
}
var /= (NTuples-1);
StdDev = sqrt((double)var);
return(StdDev);
}
FLOAT
StdDevOfY(Data,NTuples,TupleSize)
FLOAT **Data;
int NTuples;
int TupleSize;
{
int i,j,D;
FLOAT StdDev, x;
FLOAT var, sum, mean;
FLOAT n;
double sqrt(), fabs();
D = VtoBoolean(V_SupplyAbscissa) ? 0 : 1;
n = NTuples * (TupleSize-D);
sum = 0.0;
for (i=0; i<NTuples; i++)
for (j=D; j<TupleSize; j++) {
sum += Data[i][j];
}
mean = sum / n;
var = 0.0;
for (i=0; i<NTuples; i++)
for (j=D; j<TupleSize; j++) {
x = fabs((double)(Data[i][j] - mean));
var += x * x;
}
var /= (n-1);
StdDev = sqrt((double)var);
return(StdDev);
}
#define BIG 1.0e30
#define AFAC 1.5
#define AMP 1.5
FLOAT
MedianOfX(Data,NTuples,TupleSize)
FLOAT **Data;
int NTuples;
int TupleSize;
/* an iterative computation of the median...
* Code taken from Numerical Recipes..
*/
{
int np, nm, i;
FLOAT xx,xp,xm,sumx,sum,eps,stemp,dum,ap,am,aa,a;
FLOAT Median;
double fabs();
if (VtoBoolean(V_SupplyAbscissa))
return((FLOAT)(0.5*NTuples));
/* first estimate */
a = 0.5 * (Data[0][0] + Data[NTuples-1][0]);
eps = fabs((double)(Data[NTuples-1][0] - Data[0][0]));
am = -(ap=BIG);
for (;;) {
sum = sumx = 0.0;
np = nm = 0; /* # point above and below median */
xm = -(xp = BIG);
for (i=0; i<NTuples; i++) {
xx = Data[i][0];
if (xx != a) {
if (xx > a) {
++np;
if (xx < xp) xp = xx;
} else if (xx < a) {
++nm;
if (xx > xm) xm = xx;
}
sum += dum=1.0/(eps+fabs((double)(xx-a)));
sumx += xx * dum;
}
}
stemp = (sumx / sum) - a;
if ((np-nm) >= 2) {
/* guess is too low make another pass */
am = a;
aa = stemp < 0.0? xp : xp + stemp*AMP;
if (aa > ap) aa = 0.5*(a+ap);
eps = AFAC * fabs((double)(aa-a));
a = aa;
} else if ((nm-np) >= 2) {
/* guess is too high make another pass */
ap = a;
aa = stemp > 0.0? xm : xm+stemp*AMP;
if (aa < am) aa = 0.5*(a+am);
eps = AFAC*fabs((double)(aa-a));
a = aa;
} else { /* got it */
if (NTuples%2 == 0) {
Median = 0.5*(np==nm? xp+xm : np>nm? a+xp : xm+a);
} else {
Median = np == nm? a : np>nm? xp : xm;
}
return(Median);
}
}
}
FLOAT
MedianOfY(Data,N,M)
FLOAT **Data;
int N;
int M;
/* an iterative computation of the median...
* Code taken from Numerical Recipes..
*/
{
int n, np, nm, i,j,D;
FLOAT xx,xp,xm,sumx,sum,eps,stemp,dum,ap,am,aa,a;
FLOAT Median;
double fabs();
D = VtoBoolean(V_SupplyAbscissa) ? 0 : 1;
n = N * (M-D);
/* first estimate */
a = 0.5 * (Data[0][D] + Data[N-1][M-1]);
eps = fabs((double)(Data[N-1][M-1] - Data[0][D]));
am = -(ap=BIG);
for (;;) {
sum = sumx = 0.0;
np = nm = 0; /* # point above and below median */
xm = -(xp = BIG);
for (i=0; i<N; i++) {
for (j=D; j<M; j++) {
xx = Data[i][j];
if (xx != a) {
if (xx > a) {
++np;
if (xx < xp) xp = xx;
} else if (xx < a) {
++nm;
if (xx > xm) xm = xx;
}
sum += dum=1.0/(eps+fabs((double)(xx-a)));
sumx += xx * dum;
}
}
}
stemp = (sumx / sum) - a;
if ((np-nm) >= 2) {
/* guess is too low make another pass */
am = a;
aa = stemp < 0.0? xp : xp + stemp*AMP;
if (aa > ap) aa = 0.5*(a+ap);
eps = AFAC * fabs((double)(aa-a));
a = aa;
} else if ((nm-np) >= 2) {
/* guess is too high make another pass */
ap = a;
aa = stemp > 0.0? xm : xm+stemp*AMP;
if (aa < am) aa = 0.5*(a+am);
eps = AFAC*fabs((double)(aa-a));
a = aa;
} else { /* got it */
if (n%2 == 0) {
Median = 0.5*(np==nm? xp+xm : np>nm? a+xp : xm+a);
} else {
Median = np == nm? a : np>nm? xp : xm;
}
return(Median);
}
}
}