ftp.nice.ch/pub/next/science/mathematics/hippoplotamus.2.0.s.tar.gz#/hippo2.0/hdisplay.c

This is hdisplay.c in view mode; [Download] [Up]

/*
 * hippodisplay.c - display parameter routines for hippo.
 *
 * Copyright (C)  1991  The Board of Trustees of The Leland Stanford
 * Junior University.  All Rights Reserved.
 *
 * $Id: hdisplay.c,v 5.0 1993/08/17 21:54:44 rensing Exp $
 *
 * by jonas karlsson, at SLAC, August 1990
 *  split up by Paul Rensing, Feb 28,1991
 */

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <ctype.h>
#include <float.h>

#include "hippo.h"
#include "h3D.h"
#include "hutil.h"
#include "hdata.h"

GLOB_QUAL const char hippodisplay_c_rcsid[] = 
     "$Id: hdisplay.c,v 5.0 1993/08/17 21:54:44 rensing Exp $";

#define WINDWIDTH 500.0
#define WINDHEIGHT 500.0
#define TOPMARGIN 40.0		/* 1 inch margins */
#define BOTTOMMARGIN 80.0
#define LEFTMARGIN 80.0
#define RIGHTMARGIN 40.0
#ifdef THINK_C
/* can't do arithmetic with constants *8-( */
#define WWMINUSLR 380.0
#define WHMINUSTB 380.0
#else
#define WWMINUSLR (WINDWIDTH-LEFTMARGIN-RIGHTMARGIN)
#define WHMINUSTB (WINDHEIGHT-TOPMARGIN-BOTTOMMARGIN)
#endif

/*
 * bug fix for IBM & THINKC: FLT_MAX calls a function, so it can't be used
 *  to initialize global variables.
 */
#ifdef VM
#define FLOT_MAX 7.2e75
#else
#if defined THINK_C || (! defined __STDC__ && defined ultrix)
#define FLOT_MAX 3.4e38
#else
#define FLOT_MAX FLT_MAX
#endif
#endif


#define BININDEX(x, y, z, xs, ys) ((xs) * (ys) * (z) + (x) * (ys) + y)

display h_newDisp( graphtype_t type )
{
     display disp = NULL;
     /*
      * use this as the starting point
      */
     static display_t firstdisp = 
     {
	  NULL,			/* ntuple */
	  0,			/* revision number */
	  NULL,			/* ntFile */
	  1,			/* dimension */
	  HISTOGRAM,		/* graphtype */
	  BOX,			/* drawtype */
          {1,1,0,1,0,0,0,0},	/* flags */
	  NULL,			/* title */
          {{0,0,0,0},		/* bin flags */
	   {50,-1.0,1.0,0.0,0.0},	/* bins xAxis */
	   {50,-1.0,1.0,0.0,0.0},	/* bins yAxis */
		NULL,			/* pointer to bin data */
		NULL,			/* pointer to variances */
	   {{0.0,0.0,0.0},{0.0,0.0,0.0},{0.0,0.0,0.0}},	/* totals */
		FLOT_MAX,-FLOT_MAX,	/* binMin, binMax */
		0,			/* binAlloc */
		0,			/* ndata */
	  },				/* struct bins */
	  
          {-1.0,1.0,NULL,
	   {0,1,TOPBOTTOM,PLOTBOTTOM,PLOTBOTTOM,1,0,0},
		 5.0,0.0,0.0,1.0,0},    /* xaxis */
           {-1.0,1.0,NULL,
	    {0,1,LEFTRIGHT,PLOTLEFT,PLOTLEFT,1,0,0},
		 5.0,0.0,0.0,1.0,0},	/* yaxis */
           {-1.0,1.0,NULL,
	    {0,1,LEFTRIGHT,PLOTLEFT,PLOTLEFT,1,0,0},
		 5.0,0.0,0.0,1.0,0},	/* zaxis */
	  
	  SOLIDSQUARE,		/* plot symbol */
	  2.0,			/* plot symbol size */
	  SOLID,		/* line style */
          {0,-1,-1,-1,-1,-1},	/* bindings to n-tuple variable */
          {{0, 0},{WINDWIDTH,WINDHEIGHT}}, /* draw window */
          {{LEFTMARGIN,BOTTOMMARGIN}, /* margin rectangle */
	      {WWMINUSLR,WHMINUSTB}},
	  NULL,			/* nt_cut */
	  NULL,			/* bin_func */
	  NULL,			/* plot_func */
	  SOLID,		/* func Sum line style */
	  NULL,			/* bin to color transfer function */
	  NULL,			/* pointer to 3D plot workarea or null */
	  0.0,0.0,2.0,		/* theta, phi, and distance for 3D */
	  1,0,0,0,0,0,		/* doCube etc flags */
          0.60, 0.20, 0.00, 0.40, 0.90   /* greys for lego plots */
     };

     
     if ( (disp = (display) malloc( sizeof(display_t)) ) == NULL )
     {
	  h_error("Unable to allocate memory for display structure");
	  goto error;
     }


     memcpy(disp,&firstdisp,sizeof(display_t));

     disp->graphtype = type;

     /*
      * set titles and axis labels
      */
     if (h_setTitle(disp,"%t") != 0)
     {
	  h_error("Unable to set title");
	  goto error;
     }
     if (h_setAxisLabel(disp,XAXIS,"%x") != 0)
     {
	  h_error("Unable to set xAxis label");
	  goto error;
     }
     if (disp->graphtype != LEGOPLOT)
     {
          if (h_setAxisLabel(disp,ZAXIS,"%z") != 0)
          {
	       h_error("Unable to set zAxis label");
	       goto error;
          }
     }
     else
     {
	  if (h_setAxisLabel(disp,ZAXIS,"Entries / (%dx*%dy) bin") != 0)
	  {
	       h_error("Unable to set zAxis label");
	       goto error;
	  }
     }
     if (disp->graphtype != HISTOGRAM)
     {
	if (h_setAxisLabel(disp,YAXIS,"%y") != 0)
	{
	    h_error("Unable to set yAxis label");
	    goto error;
	}
     }
     else
     {
	  if (h_setAxisLabel(disp,YAXIS,"Entries / %dx bin") != 0)
	  {
	       h_error("Unable to set yAxis label");
	       goto error;
	  }
     }	  

     /*
      * other details
      */
     switch (disp->graphtype)
     {
     case HISTOGRAM:
	  break;

     case XYPLOT:
     case STRIPCHART:
	  disp->drawtype = POINT + LINE;
	  disp->dim = 2;
	  disp->binding.y = 1;
	  break;

     case COLORPLOT:
	  disp->dim = 2;
	  disp->binding.y = 1;
	  disp->drawtype = NONE;
	  break;

     case LEGOPLOT:
	  disp->dim = 2;
	  disp->binding.y = 1;
	  disp->drawtype = NONE;
	  disp->bins.xAxis.nBins = 20; 
	  disp->bins.yAxis.nBins = 20;
	  disp->doMesh = 1;
	  disp->doCube = 1;
     	  h3D_init3D(disp);
	  break;

     case SCATTERPLOT:
	  disp->dim = 2;
	  disp->binding.y = 1;
	  disp->drawtype = POINT;
	  break;

     case THREEDSCATTER:
	  disp->dim = 3;
	  disp->binding.y = 1;
	  disp->binding.z = 2;
	  disp->drawtype = POINT;
	  disp->symbolSize = 2.0;
	  disp->doScatter = 1;
	  disp->doCube = 1;
     	  h3D_init3D(disp);
	  break;
     }
     
     return disp;

 error:
     if (disp != NULL) h_freeDisp(disp);
     return NULL;
}


display h_copyDisp(display olddisp)
{
     display disp = NULL;
     func_id fid;
          
     if (olddisp == NULL) goto error;
     
     if ( (disp = (display) malloc( sizeof(display_t)) ) == NULL )
     {
	  h_error("Unable to allocate memory for display structure");
	  goto error;
     }
     
     memcpy(disp,olddisp,sizeof(display_t));

     /*
      * set all pointers to NULL so we don't free something in case of error
      */
     disp->ntFile = NULL;
     disp->bins.data = NULL;
     disp->bins.variance = NULL;
     disp->title = NULL;
     disp->xAxis.label = NULL;
     disp->yAxis.label = NULL;
     disp->zAxis.label = NULL;
     disp->nt_cut = NULL;
     disp->bin_func = NULL;
     disp->plot_func = NULL;
     disp->binToColor = NULL;
     
     /*
      * Allocate space and copy title and labels
      */
     if (h_setTitle(disp,olddisp->title) != 0)
     {
	  h_error("Unable to set title");
	  goto error;
     }
     if (h_setAxisLabel(disp,XAXIS,olddisp->xAxis.label) != 0)
     {
	  h_error("Unable to set xAxis label");
	  goto error;
     }
     if (h_setAxisLabel(disp,YAXIS,olddisp->yAxis.label) != 0)
     {
	  h_error("Unable to set yAxis label");
	  goto error;
     }
     if (h_setAxisLabel(disp,ZAXIS,olddisp->zAxis.label) != 0)
     {
	  h_error("Unable to set zAxis label");
	  goto error;
     }

     /*
      * Copy over cuts and plot functions
      */
     fid = NULL;
     while ((fid = h_nextCut(olddisp,fid)))
	  h_addUserCut(disp, fid->name, fid->paramBlk, fid->blkSize );
     fid = NULL;
     while ((fid = h_nextPlotFunc(olddisp,fid)))
	  h_addPlotFunc(disp, fid->name, fid->paramBlk, fid->blkSize,
			fid->lineStyle );

     /*
      * copy ntFile if it exists.
      */
     if (olddisp->flags.ntByReference || olddisp->ntFile != NULL)
	  h_setNtByRef(disp,olddisp->flags.ntByReference,
		       olddisp->ntFile);
     
     disp->bins.flags.dirty = 0;
     disp->bins.ndata = 0;
     disp->bins.binAlloc = 0;
     
     return disp;

 error:
     if (disp != NULL) h_freeDisp( disp );
     return NULL;
}


int h_freeDisp( display disp )
{
     func_id c,next;
     
     if (disp == NULL) return 0;
     
     if (disp->bins.data != NULL)     free( disp->bins.data );
     if (disp->bins.variance != NULL) free( disp->bins.variance );
     if (disp->title != NULL)         free( disp->title );
     if (disp->xAxis.label != NULL)   free( disp->xAxis.label );
     if (disp->yAxis.label != NULL)   free( disp->yAxis.label );
     if (disp->zAxis.label != NULL)   free( disp->zAxis.label );

     if (disp->ntFile != NULL)   free( disp->ntFile );
     
     /*
      * free the lists of functions
      */
     c = disp->nt_cut;
     while (c != NULL)
     {
	  next = c->next;

	  /* if this is standard function, free parameter block */
	  if (c->funcPtr == h_cut_lt || c->funcPtr == h_cut_gt || 
	      c->funcPtr == h_cut_le || c->funcPtr == h_cut_ge || 
	      c->funcPtr == h_cut_inside || c->funcPtr == h_cut_outside || 
	      c->funcPtr == h_cut_in_incl || c->funcPtr == h_cut_out_incl )
	       free(c->paramBlk);

	  free(c);
	  c = next;
     }

     c = disp->bin_func;
     while (c != NULL)
     {
	  next = c->next;
	  free(c);
	  c = next;
     }

     c = disp->plot_func;
     while (c != NULL)
     {
	  next = c->next;
	  free(c);
	  c = next;
     }
     
     free( disp );
     
     return 0;
}

int h_bindNtuple(display disp, ntuple nt)
{
     char string[80];
     
     if (disp == NULL)
	  return -1;
     
     if (disp->tuple == nt)
	  return 0;
     
     if (nt == NULL) 
     {
	  /*
	   * user is removing reference to ntuple.
	   * pick up the title and labels before removing reference.
	   */
	  h_expandLabel( string, disp->title, 80, disp );
	  h_setTitle( disp, string );
	  h_expandLabel( string, disp->xAxis.label, 80, disp );
	  h_setAxisLabel( disp, XAXIS, string );
	  h_expandLabel( string, disp->yAxis.label, 80, disp );
	  h_setAxisLabel( disp, YAXIS, string );
	  h_expandLabel( string, disp->zAxis.label, 80, disp );
	  h_setAxisLabel( disp, ZAXIS, string );

	  disp->tuple = nt;
	  return 0;
     }
	
     /*
      * first, check if there are enough columns
      */
     if (disp->graphtype != HISTOGRAM && nt->ndim <= 1)
	  return -1;
     
     disp->tuple = nt;
     
     disp->bins.flags.dirty = 1;
     disp->nt_rev = -1;
     
     /* 
      * check axis bindings
      */
     switch (disp->graphtype)
     {
     default:
	  if (disp->binding.y >= disp->tuple->ndim ||
	      disp->binding.y < 0)
	       disp->binding.y = 0;
     case HISTOGRAM:
	  if (disp->binding.x >= disp->tuple->ndim ||
	      disp->binding.x < 0)
	       disp->binding.x = 0;
     }
     if (disp->binding.weight >= disp->tuple->ndim) return -1;
     
     return 0;
}


int h_setNtByRef( display disp, int flag, const char *filenm )
{
     int i;
     
     if (disp == NULL) return -1;
     
     disp->flags.ntByReference = flag;
     
     if (disp->ntFile != NULL)
     {
	  free(disp->ntFile);
	  disp->ntFile = NULL;
     }
     
     if (filenm == NULL || (i=strlen(filenm)) == 0) return 0;
     
     if ( (disp->ntFile = (char *)malloc((i+1)*sizeof(char))) == NULL)
     {
	  h_error("Unable to allocate space for ntFile name");
	  return -1;
     }
     strncpy(disp->ntFile,filenm,i);
     
     return 0;
}


int h_setLogAxis(display disp, binding_t axis, int onOff)
{
     if (disp == NULL) return -1;

     
     switch (axis)
     {
     case XAXIS:
	  if (disp->graphtype == HISTOGRAM || 
	      disp->graphtype == COLORPLOT || disp->graphtype == LEGOPLOT)
	       return -1;
	  disp->xAxis.flags.log = onOff;
	  break;
     case YAXIS:
	  if (disp->graphtype == COLORPLOT || disp->graphtype == LEGOPLOT)
	       return -1;
	  disp->yAxis.flags.log = onOff;
	  break;
     case ZAXIS:
	  if (disp->graphtype == COLORPLOT || disp->graphtype == LEGOPLOT)
	       return -1;
	  disp->zAxis.flags.log = onOff;
	  break;
     default:
	  return -1;
     }
     return 0;
}

int h_getLogAxis(display disp, binding_t axis)
{
     if (disp == NULL) return -1;
     
     switch (axis)
     {
     case XAXIS:
	  return disp->xAxis.flags.log;
     case YAXIS:
	  return disp->yAxis.flags.log;
     case ZAXIS:
	  return disp->zAxis.flags.log;
     default:
	  return -1;
     }
}


int h_setAutoScale(display disp, binding_t axis, int onOff)
{
     if (disp == NULL) return -1;
     
     switch (axis)
     {
     case XAXIS:
	  disp->xAxis.flags.autoScale = onOff;
	  break;
     case YAXIS:
	  disp->yAxis.flags.autoScale = onOff;
	  break;
     case ZAXIS:
	  disp->zAxis.flags.autoScale = onOff;
	  break;
     default:
	  return -1;
     }
     return 0;
}

int h_getAutoScale(display disp, binding_t axis)
{
     if (disp == NULL) return -1;
     
     switch (axis)
     {
     case XAXIS:
	  return disp->xAxis.flags.autoScale;
     case YAXIS:
	  return disp->yAxis.flags.autoScale;
     case ZAXIS:
	  return disp->zAxis.flags.autoScale;
     default:
	  return -1;
     }
}
     

int h_setDispType(display disp, graphtype_t type)
{
     if (disp == NULL) return -1;
     if ( disp->tuple == NULL ) return -1;
     
     disp->graphtype = type;

     switch (disp->graphtype)
     {
     case HISTOGRAM:
	  disp->dim = 1;
	  disp->bins.flags.dirty = 1;
	  break;
	  
     case XYPLOT:
     case STRIPCHART:
	  disp->dim = 1;
	  break;
	  
     case SCATTERPLOT:
     case LEGOPLOT:
	  disp->dim = 2;
	  disp->bins.flags.dirty = 1;
	  break;

     case COLORPLOT:
     case THREEDSCATTER:
	  disp->dim = 2;
	  break;
	  
     }
     
     /*
      * now, check if binding is consistent
      */
     /* display dimension */
     if (disp->graphtype != HISTOGRAM && disp->tuple->ndim <= 1)
	  return -1;
     
     /* axis bindings */
     switch (disp->graphtype)
     {
     default:
	  if (disp->binding.y >= disp->tuple->ndim ||
	      disp->binding.y < 0)
	       disp->binding.y = 0;
     case HISTOGRAM:
	  if (disp->binding.x >= disp->tuple->ndim ||
	      disp->binding.x < 0)
	       disp->binding.x = 0;
     }
     if (disp->binding.weight >= disp->tuple->ndim) return -1;

     /*
      * remove bins if they are useless
      */
     if (disp->graphtype == XYPLOT || disp->graphtype == STRIPCHART 
	 || disp->graphtype == SCATTERPLOT)
     {
	  if (disp->bins.data != NULL)
	  {
	       free(disp->bins.data);
	       disp->bins.data = NULL;
	  }
	  if (disp->bins.variance != NULL)
	  {
	       free(disp->bins.variance);
	       disp->bins.variance = NULL;
	  }
	  disp->bins.binAlloc = 0;
     }
     	  
     return 0;
}


int h_setDrawType(display disp, drawtype_t type)
{
     if (disp == NULL) return -1;
     
     disp->drawtype = type;
     return 0;
}

int h_orDrawType(display disp, drawtype_t type)
{
     if (disp == NULL) return -1;
     
     disp->drawtype |= type;
     return 0;
}


int h_bind(display disp, binding_t axis, int dataDim)
{
     if (disp == NULL) return -1;
     
     if (disp->tuple != NULL && dataDim > disp->tuple->ndim)
	  return -1;
     
     switch (axis)
     {
     case XAXIS:
	  if (disp->binding.x != dataDim && dataDim >= 0)
	  {
	       disp->binding.x = dataDim;
	       disp->bins.flags.dirty = 1;
	  }
	  break;
     case YAXIS:
	  if (disp->binding.y != dataDim && dataDim >= 0)
	  {
	       disp->binding.y = dataDim;
	       disp->bins.flags.dirty = 1;
	  }
	  break;
     case ZAXIS:
	  if (disp->binding.z != dataDim && dataDim >= 0)
	  {
	       disp->binding.z = dataDim;
	       disp->bins.flags.dirty = 1;
	  }
	  break;
     case WEIGHT:
	  if (disp->binding.weight != dataDim)
	  {
	       disp->binding.weight = dataDim;
	       disp->bins.flags.dirty = 1;
	  }
	  break;
     case XERROR:
	  if (disp->binding.xerror != dataDim)
	  {
	       disp->binding.xerror = dataDim;
	       disp->bins.flags.dirty = 1;
	  }
	  break;
     case YERROR:
	  if (disp->binding.yerror != dataDim)
	  {
	       disp->binding.yerror = dataDim;
	       disp->bins.flags.dirty = 1;
	  }
	  break;
     }
     
     return 0;
}

int h_getBinding( display disp, binding_t axis )
{
     if (disp == NULL) return -1;
     
     /* note: some tolower routines are dumb, so check first */
     switch (axis)
     {
     case XAXIS:
	  return disp->binding.x;
	  
     case YAXIS:
	  return disp->binding.y;
	  
     case ZAXIS:
	  return disp->binding.z;
	  
     case WEIGHT:
	  return disp->binding.weight;
	  
     case XERROR:
	  return disp->binding.xerror;
	  
     case YERROR:
	  return disp->binding.yerror;
	  
     default:
	  return -1;
     }
}


int h_bindMany(display disp, int n, ...)
{
     va_list argPtr;
     int i, d;
     binding_t axis;
     
     va_start(argPtr, n);
     
     for (i = 0; i < n; i++) 
     {
	  axis = va_arg(argPtr, binding_t );
	  d = va_arg(argPtr, int);
	  if (h_bind(disp,axis,d) != 0) 
	  {
	       va_end(argPtr);
	       return -1;
	  }
     }
     
     va_end(argPtr);
     
     return 0;
}


int h_setBinWidth(display disp, binding_t axis, float width)
{
     if (disp == NULL) return -1;
     if (width <= 0) return -1;
     
     if (disp->bins.flags.fixed && 
	 (disp->graphtype == HISTOGRAM || disp->graphtype == LEGOPLOT
	  || disp->graphtype == COLORPLOT) ) return -1;
     
     switch (axis)
     {
     case XAXIS:
	  disp->bins.xAxis.nBins =
	       floor((disp->xAxis.high - disp->xAxis.low) / width + 0.5);
	  disp->xAxis.high = disp->xAxis.low + disp->bins.xAxis.nBins*width;
	  disp->bins.xAxis.high = disp->xAxis.high;
	  disp->xAxis.flags.autoScale = 0;
	  break;

     case YAXIS:
	  disp->bins.yAxis.nBins =
	       floor((disp->yAxis.high - disp->yAxis.low) / width + 0.5);
	  disp->yAxis.high = disp->yAxis.low + disp->bins.yAxis.nBins*width;
	  disp->bins.yAxis.high = disp->yAxis.high;
	  disp->yAxis.flags.autoScale = 0;
	  break;

     default:
	  return -1;
     }
     
     disp->bins.flags.dirty = 1;
     
     return 0;
}

float h_getBinWidth(display disp, binding_t axis)
{
     if (disp == NULL) return -1;
     
     switch (axis )
     {
     case XAXIS:
	  return (disp->xAxis.high - disp->xAxis.low) / disp->bins.xAxis.nBins;
     case YAXIS:
	  return (disp->yAxis.high - disp->yAxis.low) / disp->bins.yAxis.nBins;
     default:
	  return -1;
     }
}


int h_setBinNum(display disp, binding_t axis, int n)
{
     if (disp == NULL || n<1) return -1;
     
     if (disp->bins.flags.fixed && 
	 (disp->graphtype == HISTOGRAM || disp->graphtype == LEGOPLOT
	  || disp->graphtype == COLORPLOT) ) return -1;
     
     switch (axis )
     {
     case XAXIS:
	  if (disp->bins.xAxis.nBins != n)
	  {
	       disp->bins.xAxis.nBins = n;
	       disp->bins.flags.dirty = 1;
	  }
	  break;
     case YAXIS:
	  if (disp->bins.yAxis.nBins != n)
	  {
	       disp->bins.yAxis.nBins = n;
	       disp->bins.flags.dirty = 1;
	  }
	  break;
     default:
	  return -1;
     }
     
     return 0;
}

int h_getBinNum( display disp, binding_t axis )
{
     if (disp == NULL) return -1;
     
     switch (axis )
     {
     case XAXIS:
	  return disp->bins.xAxis.nBins;
	  break;
     case YAXIS:
	  return disp->bins.yAxis.nBins;
	  break;
     default:
	  return -1;
     }
}


int h_setRange(display disp, binding_t axis, float low, float high)
{
     int Auto = 0;
     
     if (disp->bins.flags.fixed && 
	 (disp->graphtype == HISTOGRAM || disp->graphtype == LEGOPLOT
	  || disp->graphtype == COLORPLOT) ) return -1;
     
     if (low >= high)
     {
	  Auto = 1;
	  high = low + 1.0;
     }
     
     if (disp == NULL) return -1;
     
     switch (axis )
     {
     case XAXIS:
	  if (disp->xAxis.low != low || disp->xAxis.high != high)
	  {
	       disp->xAxis.low = low;
	       disp->xAxis.high = high;
	       disp->bins.xAxis.low = low;
	       disp->bins.xAxis.high = high;
	       disp->xAxis.flags.autoScale = Auto;
	       disp->bins.flags.dirty = 1;
	  }
	  break;
     case YAXIS:
	  if (disp->yAxis.low != low || disp->yAxis.high != high)
	  {
	       disp->yAxis.low = low;
	       disp->yAxis.high = high;
	       disp->bins.yAxis.low = low;
	       disp->bins.yAxis.high = high;
	       disp->yAxis.flags.autoScale = Auto;
	       disp->bins.flags.dirty = 1;
	  }
	  break;
     case ZAXIS:
	  if (disp->zAxis.low != low || disp->zAxis.high != high)
	  {
	       disp->zAxis.low = low;
	       disp->zAxis.high = high;
	       disp->zAxis.flags.autoScale = Auto;
	       disp->bins.flags.dirty = 1;
	  }
	  break;
     default:
	  return -1;
     }
     
     
     return 0;
}


int h_getRange(display disp, binding_t axis, float *low, float *high)
{
     if (disp == NULL) return -1;
     
     switch (axis )
     {
     case XAXIS:
	  *low = disp->xAxis.low;
	  *high = disp->xAxis.high;
	  break;
     case YAXIS:
	  *low = disp->yAxis.low;
	  *high = disp->yAxis.high;
	  break;
     case ZAXIS:
	  *low = disp->zAxis.low;
	  *high = disp->zAxis.high;
	  break;
     default:
	  return -1;
     }
     
     return 0;
}


int h_getBinExtreme( display disp, float *min, float *max )
{
     if (disp == NULL) return -1;
     *min = disp->bins.binMin;
     *max = disp->bins.binMax;
     return 0;
}


int h_dispSize( display disp )
{
     int i = 0;
     func_id p;
     
     i += 4;			/* magic number */
     i += (strlen(STRUCT_VERSION)/4 + 2)*4;
     i += sizeof( display_t  )+8;
     i += (strlen(disp->title)/4 + 2)*4;
     i += (strlen(disp->ntFile)/4 + 2)*4;
     if (disp->bins.flags.fixed)
	  i += 2 * (disp->bins.binAlloc * sizeof(float) + 4);

     i += (strlen(disp->xAxis.label)/4 + 2)*4;
     i += (strlen(disp->yAxis.label)/4 + 2)*4;
     i += (strlen(disp->zAxis.label)/4 + 2)*4;

     for (p=disp->nt_cut; p!=NULL; p=p->next )
     {
	  i += sizeof(func_id_t) + 4;
	  i += p->blkSize * sizeof(double) + 4;
     }
     for (p=disp->bin_func; p!=NULL; p=p->next )
     {
	  i += sizeof(func_id_t) + 4;
	  i += p->blkSize * sizeof(double) + 4;
     }
     for (p=disp->plot_func; p!=NULL; p=p->next )
     {
	  i += sizeof(func_id_t) + 4;
	  i += p->blkSize * sizeof(double) + 4;
     }
     for (p=disp->binToColor; p!=NULL; p=p->next )
     {
	  i += sizeof(func_id_t) + 4;
	  i += p->blkSize * sizeof(double) + 4;
     }

     i += 100;			/* just in case */
      
     return i;
}

	  

void h_autoScale( display disp )
{
   /* 
    * do autoscaling of bins if requested.
    */
   if ( disp == NULL || disp->tuple == NULL || disp->tuple->ndata == 0)
       return;


   switch (disp->dim)
   {
#ifdef junk
   case 3:
      if (disp->zAxis.flags.autoScale)
      {
	 disp->zAxis.low = disp->tuple->nlow[disp->binding.z];
	 disp->zAxis.high = disp->tuple->nhigh[disp->binding.z];
	 if (disp->graphtype == SCATTERPLOT || disp->graphtype == XYPLOT
	     || disp->graphtype == STRIPCHART)
	      h_adjustAxis(&(disp->zAxis.low), &(disp->zAxis.high), 
			   0, disp->zAxis.flags.log);
	 else
	      h_adjustAxis(&(disp->zAxis.low), &(disp->zAxis.high),
			   disp->zAxis.nBins, disp->zAxis.flags.log );
	 disp->bins.flags.dirty = 1;
      }
#endif
   case 2:
      if (disp->yAxis.flags.autoScale)
      {
	 disp->yAxis.low = disp->tuple->nlow[disp->binding.y];
	 disp->yAxis.high = disp->tuple->nhigh[disp->binding.y];
	 if (disp->yAxis.high <= disp->yAxis.low + FLT_EPSILON*4) 
	      disp->yAxis.high = disp->yAxis.low + 1.0;
	 
	 if (disp->graphtype == SCATTERPLOT || disp->graphtype == XYPLOT
	     || disp->graphtype == STRIPCHART)
	      h_adjustAxis(&(disp->yAxis.low), &(disp->yAxis.high),
			   0, disp->yAxis.flags.log);
	 else
	      h_adjustAxis(&(disp->yAxis.low), &(disp->yAxis.high),
			   disp->bins.yAxis.nBins, disp->yAxis.flags.log );
	 disp->bins.flags.dirty = 1;
      }
   case 1:
      if (disp->xAxis.flags.autoScale)
      {
	 disp->xAxis.low = disp->tuple->nlow[disp->binding.x];
	 disp->xAxis.high = disp->tuple->nhigh[disp->binding.x];
	 if (disp->xAxis.high <= disp->xAxis.low + FLT_EPSILON*4) 
	      disp->xAxis.high = disp->xAxis.low + 1.0;

	 if (disp->graphtype == SCATTERPLOT || disp->graphtype == XYPLOT
	     || disp->graphtype == STRIPCHART)
	      h_adjustAxis(&(disp->xAxis.low), &(disp->xAxis.high), 
			   0, disp->xAxis.flags.log );
	 else
	      h_adjustAxis(&(disp->xAxis.low), &(disp->xAxis.high),
			   disp->bins.xAxis.nBins, disp->xAxis.flags.log );
	 disp->bins.flags.dirty = 1;
      }
   }
   
   return;
}



int h_ptToBin(display disp, float f, binding_t axis)
{
     float bwin = 0;
     int underBin = 0;
     
     switch (axis)
     {
     case XAXIS:
	  bwin = ((float) disp->bins.xAxis.nBins) /
	       (float) (disp->xAxis.high - disp->xAxis.low) ;
	  underBin = disp->xAxis.low * bwin - 1;
	  break;
     case YAXIS:
	  bwin = ((float) disp->bins.yAxis.nBins) /
	       (float) (disp->yAxis.high - disp->yAxis.low) ;
	  underBin = disp->yAxis.low * bwin - 1;
	  break;
     default:
	  return -1;
     }	  
     return (floor(f * bwin) - underBin - 1);
}


float h_binVal(display disp, ...)
{
     va_list argPtr;
     int i;
#ifndef __STDC__
     static
#endif
     int bin[3]={0,0,0};
     
     if (disp->bins.ndata == 0) return 0;
     
     va_start(argPtr, disp);
     
     for (i = 0; i < disp->dim; i++) bin[i] = va_arg(argPtr, int);
     
     va_end(argPtr);
     
     return disp->bins.data[BININDEX(bin[0], bin[1], bin[2],
				     disp->bins.xAxis.nBins, 
				     ( (disp->dim > 1) ? 
				      disp->bins.yAxis.nBins : 1) )];
}


/* 
 * conversion routines :
 */
float h_wPtTogPt(display disp, float wPt, binding_t axis)
{
     switch (axis )
     {
     case XAXIS:
	  return  (((wPt - disp->marginRect.origin.x)
		    / disp->marginRect.size.width)
		   * (disp->xAxis.high - disp->xAxis.low) 
		   + disp->xAxis.low);
	  break;
	  
     case YAXIS:
	  return  (((wPt - disp->marginRect.origin.y)
		    / disp->marginRect.size.height)
		   * (disp->yAxis.high - disp->yAxis.low) 
		   + disp->yAxis.low);
	  break;
	  
     default:
	  return -1;
     }
}


float h_gPtTowPt(display disp, float gPt, binding_t axis)
{
     switch (axis )
     {
     case XAXIS:
	  return (((gPt - disp->xAxis.low)
		   / (disp->xAxis.high - disp->xAxis.low))
		  * disp->marginRect.size.width
		  + disp->marginRect.origin.x);
	  break;
	  
     case YAXIS:
	  return (((gPt - disp->yAxis.low)
		   / (disp->yAxis.high - disp->yAxis.low))
		  * disp->marginRect.size.height
		  + disp->marginRect.origin.y);
	  break;
	  
     default:
	  return -1;
     }
}


int h_setDrawRect(display disp, rectangle *rect)
{
     if (disp == NULL) return -1;
     
     memcpy (&disp->drawRect, rect, sizeof(rectangle));
     return 0;
}

int h_setMarginRect(display disp, rectangle *rect)
{
     if (disp == NULL) return -1;
     
     memcpy (&disp->marginRect, rect, sizeof(rectangle));
     return 0;
}


int h_getDrawRect(display disp, rectangle *rect)
{
     if (disp == NULL) return -1;
     
     memcpy (rect, &disp->drawRect, sizeof(rectangle));
     
     if (rect->size.width != 0 && rect->size.height != 0)
	  return 0;
     else
	  return -1;
}

int h_getMarginRect(display disp, rectangle *rect)
{
     if (disp == NULL) return -1;
     
     memcpy (rect, &disp->marginRect, sizeof(rectangle));
     
     if (rect->size.width != 0 && rect->size.height != 0)
	  return 0;
     else
	  return -1;
}


int h_setTitle(display disp, const char *title)
{
     int l;
     
     if (disp == NULL) return -1;
     if (title == NULL) return -1;
     
     l = strlen(title);
     if (disp->title != NULL) free(disp->title);
     if ( (disp->title=(char *)malloc((l+1)*sizeof(char)) )==NULL)
     {
	  h_error("Unable to allocate memory for title");
	  return -1;
     }
     
     return strcpy(disp->title, title) ? 0 : -1;
}

int h_setAxisLabel(display disp, binding_t axis, const char *title)
{
     int l;
     char *p;
     
     if (disp == NULL || title == NULL) return -1;
     
     l = strlen(title);
     if ( (p=(char *)malloc((l+1)*sizeof(char)) )==NULL)
     {
	  h_error("Unable to allocate memory for title");
	  return -1;
     }
     l = strcpy(p, title) ? 0: -1;
     
     switch (axis)
     {
     case XAXIS:
	  if (disp->xAxis.label != NULL) free(disp->xAxis.label);
	  disp->xAxis.label = p;
	  break;
     case YAXIS:
	  if (disp->yAxis.label != NULL) free(disp->yAxis.label);
	  disp->yAxis.label = p;
	  break;
     case ZAXIS:
	  if (disp->zAxis.label != NULL) free(disp->zAxis.label);
	  disp->zAxis.label = p;
	  break;
     default:
	  free(p);
	  l = -1;
     }
     
     return l;
}

const char *h_getAxisLabel( display disp, binding_t axis )
{
     if (disp == NULL) return NULL;
     switch (axis)
     {
     case XAXIS:
	  return disp->xAxis.label;
     case YAXIS:
	  return disp->yAxis.label;
     case ZAXIS:
	  return disp->zAxis.label;
     default:
	  return NULL;
     }
}

/*
 * Set/get flags specifying location of axis frills (label, ticks, scale)
 */
int h_setTickLocation( display disp, binding_t axis, plotloc_t location )
{
     switch (axis)
     {
     case XAXIS:
	  disp->xAxis.flags.tickLocation = location;
	  break;
     case YAXIS:
	  disp->yAxis.flags.tickLocation = location;
	  break;
     case ZAXIS:
	  disp->zAxis.flags.tickLocation = location;
	  break;
     default:
	  return -1;
     }
     return 0;
}
int h_setScaleLocation( display disp, binding_t axis, plotloc_t location )
{
     switch (axis)
     {
     case XAXIS:
	  disp->xAxis.flags.scaleLocation = location;
	  break;
     case YAXIS:
	  disp->yAxis.flags.scaleLocation = location;
	  break;
     case ZAXIS:
	  disp->zAxis.flags.scaleLocation = location;
	  break;
     default:
	  return -1;
     }
     return 0;
}
int h_setLabelLocation( display disp, binding_t axis, plotloc_t location )
{
     switch (axis)
     {
     case XAXIS:
	  disp->xAxis.flags.labelLocation = location;
	  break;
     case YAXIS:
	  disp->yAxis.flags.labelLocation = location;
	  break;
     case ZAXIS:
	  disp->zAxis.flags.labelLocation = location;
	  break;
     default:
	  return -1;
     }
     return 0;
}

plotloc_t h_getTickLocation( display disp, binding_t axis )
{
     switch (axis)
     {
     case XAXIS:
	  return disp->xAxis.flags.tickLocation;
     case YAXIS:
	  return disp->yAxis.flags.tickLocation;
     case ZAXIS:
	  return disp->zAxis.flags.tickLocation;
     default:
	  return -1;
     }
     return 0;
}
plotloc_t h_getScaleLocation( display disp, binding_t axis )
{
     switch (axis)
     {
     case XAXIS:
	  return disp->xAxis.flags.scaleLocation;
     case YAXIS:
	  return disp->yAxis.flags.scaleLocation;
     case ZAXIS:
	  return disp->zAxis.flags.scaleLocation;
     default:
	  return -1;
     }
     return 0;
}
plotloc_t h_getLabelLocation( display disp, binding_t axis )
{
     switch (axis)
     {
     case XAXIS:
	  return disp->xAxis.flags.labelLocation;
     case YAXIS:
	  return disp->yAxis.flags.labelLocation;
     case ZAXIS:
	  return disp->zAxis.flags.labelLocation;
     default:
	  return -1;
     }
     return 0;
}
int h_setScaleFontSize( display disp, binding_t axis, float fontSize )
{
     switch (axis)
     {
     case XAXIS:
	  disp->xAxis.scaleFontSize = fontSize;
	  break;
     case YAXIS:
	  disp->yAxis.scaleFontSize = fontSize;
	  break;
     case ZAXIS:
	  disp->zAxis.scaleFontSize = fontSize;
	  break;
     default:
	  return -1;
     }
     return 0;
}
float h_getScaleFontSize( display disp, binding_t axis )
{
     switch (axis)
     {
     case XAXIS:
	  return disp->xAxis.scaleFontSize;
     case YAXIS:
	  return disp->yAxis.scaleFontSize;
     case ZAXIS:
	  return disp->zAxis.scaleFontSize;
     default:
	  return -1;
     }
     return 0;
}

int h_setTickLength( display disp, binding_t axis, float f )
{
     switch (axis)
     {
     case XAXIS:
	  disp->xAxis.tickLength = f;
	  break;
     case YAXIS:
	  disp->yAxis.tickLength = f;
	  break;
     case ZAXIS:
	  disp->zAxis.tickLength = f;
	  break;
     default:
	  return -1;
     }
     return 0;
}
float h_getTickLength( display disp, binding_t axis )
{
     switch (axis)
     {
     case XAXIS:
	  return disp->xAxis.tickLength;
     case YAXIS:
	  return disp->yAxis.tickLength;
     case ZAXIS:
	  return disp->zAxis.tickLength;
     default:
	  return -1;
     }
     return 0;
}


/*
 * Functions dealing with cuts.
 */

func_id h_addCut( display disp, const char *cutfunc, int cut_dim, 
		 double val1, ... )
{
     va_list argPtr;
     void *fptr;
     double *parm;
     int nval;
     typedef int (*cutf)(float *,double *);
	  
     
     /*
      * check that the cut variable is in ntuple.
      */
     if (cut_dim < 0 || cut_dim >= disp->tuple->ndim)
     {
	  h_error("h_addCut: Column used for cut is not in the ntuple");
	  return NULL;
     }
	  
     /*
      * determine the function
      */
     fptr = h_fNameSrch(cutfunc);
     if (fptr==h_cut_le || 
	 fptr==h_cut_lt || 
	 fptr==h_cut_ge || 
	 fptr==h_cut_gt )
	  nval = 2;
     else if (fptr==h_cut_inside || 
	      fptr==h_cut_outside || 
	      fptr==h_cut_in_incl || 
	      fptr==h_cut_out_incl )
	  nval = 3;
     else
     {
	  h_error("h_addCut: function is not supported by hippo.");
	  h_error("h_addCut: use the user-function routines.");
	  return NULL;
     }

     /* 
      * build the parameter list
      */
     if ( (parm=(double *)malloc(nval*sizeof(double))) == NULL)
     {
	  h_error("Could not allocate cut parameter block.");
	  return NULL;
     }
     parm[0] = (double) cut_dim;
     parm[1] = val1;
     if (nval > 2)
     {
	  va_start(argPtr, val1);
	  parm[2] = va_arg(argPtr, double );
	  va_end(argPtr);
     }
	  
     /*
      * now it looks like a user cut!
      */
     return h_addUserCut(disp, cutfunc, parm, nval );
}

int h_changeCut( display disp, func_id cut, double val1, ... )
{
     va_list argPtr ;
     
     double *f;
     int i;

     if (cut==NULL) return 0;
     
     f = (double *) cut->paramBlk;
     f[1] = val1;
     if (cut->blkSize >2)
     {
	  va_start(argPtr, val1);
	  for (i=2; i<cut->blkSize; i++)
	       f[i] = va_arg(argPtr, double);
	  va_end(argPtr);
     }
     
     /*
      * bins are now dirty.
      */
     disp->bins.flags.dirty = 1;
     
     return 0;
}

int h_deleteCut( display disp, func_id cut )
{
     func_id c,c_p=NULL;
     
     if (disp == NULL || cut == NULL) return 0;
     
     c = disp->nt_cut;
     
     while (c!=cut && c!=NULL) 
     {
	  c_p = c;
	  c = c->next;
     }
     
     if (c!=NULL)
     {
	  if (c_p!=NULL) 
	       c_p->next = c->next;
	  else
	       disp->nt_cut = c->next;
	  free(c);
     }
     else
	  return 0;
     
     /*
      * bins are now dirty.
      */
     disp->bins.flags.dirty = 1;
     
     return 0;
}

func_id h_addUserCut( display disp, const char *cutfunc, double *paramBlk,
		    int nParam )
{
     func_id newcut,nextf;
     
     /*
      * allocate a new cut.
      */
     if ( (newcut = (func_id) malloc(sizeof(func_id_t))) == NULL)
     {
	  h_error("Could not allocate cut structure.");
	  return NULL;
     }

     /*
      * initialize all the fields of the new cut.
      */
     strncpy(newcut->name, cutfunc, FUNCNAMELEN);
     if ( (newcut->funcPtr = h_fNameSrch(newcut->name))
	 == NULL)
     {
	  h_error("h_addUserCut - function is not registered.");
	  h_error("use h_funcReg");
	  free(newcut);
	  return NULL;
     }

     newcut->blkSize = nParam;
     newcut->paramBlk = (void *) paramBlk;
     
     nextf = disp->nt_cut;
     disp->nt_cut = newcut;
     newcut->next = nextf;

     /*
      * bins are now dirty.
      */
     disp->bins.flags.dirty = 1;
     
     return newcut;
}

func_id h_nextCut( display disp, func_id thiscut )
{
     if (disp == NULL) return NULL;

     if (thiscut == NULL) return disp->nt_cut;

     return thiscut->next;
}


/*
 * overplot function routines
 */
func_id h_addPlotFunc(display disp, const char *plotfunc, double *paramBlk,
		      int nParam, linestyle_t ls )
{
     func_id newpfunc,nextf;
     
     /*
      * allocate a new cut.
      */
     if ( (newpfunc = (func_id) malloc(sizeof(func_id_t))) == NULL)
     {
	  h_error("Could not allocate cut structure.");
	  return NULL;
     }

     /*
      * initialize all the fields of the new cut.
      */
     strncpy(newpfunc->name, plotfunc, FUNCNAMELEN);
     if ( (newpfunc->funcPtr = h_fNameSrch(newpfunc->name))
	 == NULL)
     {
	  h_error("h_addPlotFunc - function is not registered.");
	  h_error("use h_funcReg");
	  free(newpfunc);
	  return NULL;
     }

     newpfunc->blkSize = nParam;
     newpfunc->paramBlk = (void *)paramBlk;
     newpfunc->lineStyle = ls;
     
     nextf = disp->plot_func;
     disp->plot_func = newpfunc;
     newpfunc->next = nextf;

     return newpfunc;
}

func_id h_nextPlotFunc( display disp, func_id thispfunc )
{
     if (disp == NULL) return NULL;

     if (thispfunc == NULL) return disp->plot_func;

     return thispfunc->next;
}

int h_deletePlotFunc( display disp, func_id pfunc )
{
     func_id c,c_p=NULL;
     
     if (disp == NULL || pfunc == NULL) return 0;
     
     c = disp->plot_func;
     
     while (c!=pfunc && c!=NULL) 
     {
	  c_p = c;
	  c = c->next;
     }
     
     if (c!=NULL)
     {
	  if (c_p!=NULL) 
	       c_p->next = c->next;
	  else
	       disp->plot_func = c->next;
	  free(c);
     }
     else
	  return 0;
	       
     return 0;
}

/*
 * function to get xy and scatter plot xy moments, also correlation
 */
void h_getXYMoments (display disp, float *xmoments, float *ymoments, float *r)
{
    int 	npts, i;
    float 	*xylist;
    struct 	maxs max;
    float 	ax, ay, sxx = 0.0, syy = 0.0, sxy = 0.0;
     
    for (i=0; i<3; i++) {
     	xmoments[i] = 0.0;
     	ymoments[i] = 0.0;
    }
    npts = getScatData( disp, &xylist, &max );
    if (npts == 0) return;

    xmoments[0] = npts;
    ymoments[0] = npts;
    xmoments[1] = max.xsum;
    ymoments[1] = max.ysum;
    xmoments[2] = max.x2sum;
    ymoments[2] = max.y2sum;

    ax = max.xsum / npts;
    ay = max.ysum / npts;
    
    sxy = max.xysum - (max.xsum * max.ysum / npts);
    sxx = max.x2sum - (max.xsum * max.xsum / npts);
    syy = max.y2sum - (max.ysum * max.ysum / npts);
    *r = sxy / sqrt(sxx*syy);
    

    free( xylist );
    return;
}




These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.