home *** CD-ROM | disk | FTP | other *** search
- /*
- * hippoplotps.c - Postscript routines for displaying hippo ntuples.
- *
- * Copyright (C) 1991 The Board of Trustees of The Leland Stanford
- * Junior University. All Rights Reserved.
- *
- * $Header: /nfs/ebnextk/LocalSources/hippo/RCS/hippoplotNeXT.c,v 3.4 1992/03/12 02:07:32 rensing Rel $
- *
- * by jonas karlsson, at SLAC, August 1990
- * split up by Paul Rensing, Feb 28,1991
- * modified by M. Gravina, March 28, 1991
- */
-
- #include <string.h>
- #include <stdlib.h>
- #include <math.h>
- #include <appkit/graphics.h>
- #include <appkit/color.h>
- #include <dpsclient/psops.h>
- #include <dpsclient/wraps.h>
- #include <dpsclient/dpsclient.h>
- #include "hippo.h"
- #include "hippoplotNeXT.h"
- #include "hippoutil.h"
-
- /* find offset to matrix element */
- #define INDEX(row, column, totcols) ((row) * (totcols) + (column))
-
- #define MIN(x, y) (((x) > (y)) ? (y) : (x))
-
- /* following copied from <appkit/View.h> */
- /* look out of changes in future releases */
- extern short NXDrawingStatus;
-
- /* NXDrawingStatus values */
-
- #define NX_DRAWING 1 /* we're drawing */
- #define NX_PRINTING 2 /* we're printing */
- #define NX_COPYING 3 /* we're copying to the scrap */
-
- /*
- * maximum number of point to use in userpaths
- */
- #define MAXNPTS_SCREEN 1000
- #define MAXNPTS_PRINT 500
-
- /* various globals */
-
- rectangle outerRect; /* Outer rectangle in device units */
- rectangle innerRect; /* inner (ie plotting area) rectangle in device units */
- rectangle userRect; /* ditto in user units */
- float bbox[4]; /* bounding box required by DPSDoUserPath */
- float xScale, yScale; /* used for getting into user coords from device coords */
-
- int initPlot_NeXT(rectangle *rect1, rectangle *rect2, rectangle *rect3)
- {
- /* Save rectangle pointers for global use */
- memcpy((char *) &outerRect, (const char *)rect1, sizeof(rectangle) );
- memcpy((char *) &innerRect, (const char *)rect2, sizeof(rectangle) );
- memcpy((char *) &userRect, (const char *)rect3, sizeof(rectangle) );
-
- xScale = innerRect.size.width / userRect.size.width;
- yScale = innerRect.size.height / userRect.size.height;
-
- /* specify bounding box (add a small margin for safety) */
- bbox[0] = userRect.origin.x -
- (innerRect.origin.x - outerRect.origin.x)/xScale;
- bbox[1] = userRect.origin.y -
- (innerRect.origin.y - outerRect.origin.y)/yScale;
- bbox[2] = userRect.origin.x + userRect.size.width +
- (outerRect.size.width+outerRect.origin.x -
- (innerRect.origin.x+innerRect.size.width))/xScale;
- bbox[3] = userRect.origin.y + userRect.size.height +
- (outerRect.size.height+outerRect.origin.y -
- (innerRect.origin.y+innerRect.size.height))/yScale;
-
- return 0;
- }
-
- int drawLine_NeXT(float *coords, int nCoords, linestyle_t ls)
- {
- char ops[3] = { dps_moveto, 0, dps_lineto };
- int repeatCount; /* this number + 32 must be < 255 */
- /* to display and < 127 for printing */
- /* to fit in 1 char */
- float *co;
- int count;
- float ctm_matrix[6] = {1.0/xScale, 0.0, 0.0, 1.0/yScale, 0.0, 0.0 };
-
- if ( NXDrawingStatus == NX_DRAWING )
- repeatCount = 220;
- else
- repeatCount = 92; /* work around apparent bug */
- PSgsave();
- /* PSsetlinewidth(0.15); NeXT's magic number for fast drawing */
- /* in case going to Linotronic (R) */
-
- /* get into user coords */
- PStranslate (innerRect.origin.x, innerRect.origin.y);
- PSscale (xScale, yScale);
- PStranslate (-userRect.origin.x, -userRect.origin.y);
-
- /*
- * the following rather messy code is needed because PostScript
- * uses just 1 character for a repeat counter (specified as
- * 'excess 32'). Using the repeat method means we don't have to
- * malloc some variable length array for the ops, and then free
- * it after use.
- */
- co = coords;
- do
- {
- if (nCoords > repeatCount) count = repeatCount;
- else count = nCoords;
- /*
- * use DPSDoUserPathWithMatrix to take care of funny effect when
- * you have unequal scaling.
- */
- ops[1] = 32 + count - 1;
- DPSDoUserPathWithMatrix(co, 2*count, dps_float, ops, 3,
- bbox, dps_ustroke, ctm_matrix);
- co += 2*(count - 1);
- nCoords -= (count - 1);
- }
- while (nCoords > 1); /* 1 because we always back up 1 point */
- /* to connect the segments */
-
- PSgrestore();
- return 0;
- }
-
-
-
- int drawPoints_NeXT(float *coords, int nCoords, plotsymbol_t symbol,
- float symbolSize)
- {
-
- int ci, oi, i;
- int filled=0;
- int count;
- int maxnpts;
- float *cArray;
- char *oArray;
- float xPointSide, yPointSide;
- float xHalfPointSide, yHalfPointSide;
- float ctm_matrix[6] = {1.0/xScale, 0.0, 0.0, 1.0/yScale, 0.0, 0.0 };
-
- if ( NXDrawingStatus == NX_DRAWING )
- maxnpts = MAXNPTS_SCREEN;
- else
- maxnpts = MAXNPTS_PRINT;
-
- if (symbol == SOLIDSQUARE)
- filled = 1;
-
- if (filled) maxnpts /= 5;
-
- xPointSide = symbolSize / xScale;
- yPointSide = symbolSize / yScale;
- xHalfPointSide = xPointSide / 2.0;
- yHalfPointSide = yPointSide / 2.0;
-
- PSgsave();
- /* PSsetlinewidth(0.15); NeXT's magic number for fast drawing */
-
- /* get into user coords */
- PStranslate (innerRect.origin.x, innerRect.origin.y);
- PSscale (xScale, yScale);
- PStranslate (-userRect.origin.x, -userRect.origin.y);
-
- if (nCoords > maxnpts) i = maxnpts;
- else i = nCoords;
- if ((cArray = (float *) malloc( 8*i * sizeof(float) )) == NULL)
- {
- h_error("drawPoints_NeXT - memory exceeded ");
- return -1;
- }
-
- if ((oArray = (char *) malloc( 5*i * sizeof(char) )) == NULL)
- {
- h_error("drawPoints_NeXT - memory exceeded ");
- return -1;
- }
-
- do
- {
- if (nCoords > maxnpts) count = maxnpts;
- else count = nCoords;
-
- ci = oi = 0;
-
- switch (symbol)
- {
- case SQUARE:
- case SOLIDSQUARE:
- for (i = 0; i < count; i++)
- {
- cArray[ci++] = *coords++ - xHalfPointSide;
- cArray[ci++] = *coords++ - yHalfPointSide;
- oArray[oi++] = dps_moveto;
-
- cArray[ci++] = +xPointSide;
- cArray[ci++] = +0.0;
- oArray[oi++] = dps_rlineto;
-
- cArray[ci++] = +0.0;
- cArray[ci++] = +yPointSide;
- oArray[oi++] = dps_rlineto;
-
- cArray[ci++] = -xPointSide;
- cArray[ci++] = +0.0;
- oArray[oi++] = dps_rlineto;
- oArray[oi++] = dps_closepath;
- }
- break;
-
- case PLUS:
- for (i = 0; i < count; i++)
- {
- cArray[ci++] = *coords++ - xHalfPointSide;
- cArray[ci++] = *coords++;
- oArray[oi++] = dps_moveto;
-
- cArray[ci++] = +xPointSide;
- cArray[ci++] = +0.0;
- oArray[oi++] = dps_rlineto;
-
- cArray[ci++] = -xHalfPointSide;
- cArray[ci++] = +yHalfPointSide;
- oArray[oi++] = dps_moveto;
-
- cArray[ci++] = 0.0;
- cArray[ci++] = -yPointSide;
- oArray[oi++] = dps_rlineto;
- }
- break;
-
- case TIMES:
- for (i = 0; i < count; i++)
- {
- cArray[ci++] = *coords++ - xHalfPointSide;
- cArray[ci++] = *coords++ - yHalfPointSide;
- oArray[oi++] = dps_moveto;
-
- cArray[ci++] = +xPointSide;
- cArray[ci++] = +yPointSide;
- oArray[oi++] = dps_rlineto;
-
- cArray[ci++] = 0.0;
- cArray[ci++] = +yPointSide;
- oArray[oi++] = dps_moveto;
-
- cArray[ci++] = -xPointSide;
- cArray[ci++] = -yPointSide;
- oArray[oi++] = dps_rlineto;
- }
- break;
-
- default:
- break;
- }
-
- /*
- * use DPSDoUserPathWithMatrix to take care of funny effect when
- * you have unequal scaling. Applies to line widths and patterns,
- * so not useful for filled symbols.
- */
- if (filled)
- DPSDoUserPath(cArray, ci, dps_float, oArray, oi, bbox,
- dps_ufill);
- else
- DPSDoUserPathWithMatrix(cArray, ci, dps_float, oArray, oi, bbox,
- dps_ustroke,ctm_matrix);
-
- nCoords -= count;
- }
- while (nCoords > 0);
-
- free (cArray);
- free (oArray);
- PSgrestore();
-
- return 0;
- }
-
-
- int drawYError_NeXT(float *coords, float *errorYs, int nCoords)
- {
- #define ERRORCAPSIZE 2.0
-
- int ci, oi, i;
- int count;
- int maxnpts;
- float *cArray;
- char *oArray;
- float halfErrorCap = ERRORCAPSIZE/xScale * 0.5;
- float x, ylo, yhi;
- float ctm_matrix[6] = {1.0/xScale, 0.0, 0.0, 1.0/yScale, 0.0, 0.0 };
-
- if ( NXDrawingStatus == NX_DRAWING )
- maxnpts = MAXNPTS_SCREEN;
- else
- maxnpts = MAXNPTS_PRINT;
-
- if (nCoords > maxnpts) i = maxnpts;
- else i = nCoords;
- if ((cArray = (float *) malloc (12 * i * sizeof(float))) == NULL)
- {
- h_error("drawYError_NeXT - memory exceeded ");
- return -1;
- }
-
- if ((oArray = (char *) malloc (6 * i * sizeof(char))) == NULL)
- {
- h_error("drawYError_NeXT - memory exceeded ");
- return -1;
- }
-
- PSgsave();
- /* PSsetlinewidth(0.15); NeXT's magic number for fast drawing */
-
- /* get into user coords */
- PStranslate (innerRect.origin.x, innerRect.origin.y);
- PSscale (xScale, yScale);
- PStranslate (-userRect.origin.x, -userRect.origin.y);
-
- do
- {
- if (nCoords > maxnpts) count = maxnpts;
- else count = nCoords;
-
- ci = oi = 0;
-
- for (i = 0; i < count; i++)
- {
- x = *coords++; /* x coord */
- coords++; /* skip over this y coord - not needed */
- yhi = *errorYs++; /* y of high end of error bar */
- ylo = *errorYs++; /* y of low end of error bar */
-
- cArray[ci++] = x;
- cArray[ci++] = ylo;
- oArray[oi++] = dps_moveto; /* move to mid bottom */
-
- cArray[ci++] = x;
- cArray[ci++] = yhi;
- oArray[oi++] = dps_lineto; /* line to mid top */
-
- cArray[ci++] = x - halfErrorCap;
- cArray[ci++] = yhi;
- oArray[oi++] = dps_moveto; /* move to top left */
-
- cArray[ci++] = x + halfErrorCap;
- cArray[ci++] = yhi;
- oArray[oi++] = dps_lineto; /* line to top right */
-
- cArray[ci++] = x - halfErrorCap;
- cArray[ci++] = ylo;
- oArray[oi++] = dps_moveto; /* move to bottom left */
-
- cArray[ci++] = x + halfErrorCap;
- cArray[ci++] = ylo;
- oArray[oi++] = dps_lineto; /* line to bottom right */
- }
-
- DPSDoUserPathWithMatrix(cArray, ci, dps_float, oArray, oi, bbox,
- dps_ustroke, ctm_matrix);
- nCoords -= count;
- }
- while (nCoords > 0);
-
- PSgrestore();
-
- free (cArray);
- free (oArray);
- return 0;
- }
-
-
- int drawXError_NeXT(float *coords, float *errorXs, int nCoords)
- {
- int ci, oi, i;
- int count;
- int maxnpts;
- float *cArray;
- char *oArray;
- float halfErrorCap = ERRORCAPSIZE/yScale * 0.5;
- float y, xlo, xhi;
- float ctm_matrix[6] = {1.0/xScale, 0.0, 0.0, 1.0/yScale, 0.0, 0.0 };
-
- if ( NXDrawingStatus == NX_DRAWING )
- maxnpts = MAXNPTS_SCREEN;
- else
- maxnpts = MAXNPTS_PRINT;
-
- if (nCoords > maxnpts) i = maxnpts;
- else i = nCoords;
- if ((cArray = (float *) malloc (12 * i * sizeof(float))) == NULL)
- {
- h_error("drawXError_NeXT - memory exceeded ");
- return -1;
- }
-
- if ((oArray = (char *) malloc (6 * i * sizeof(char))) == NULL)
- {
- h_error("drawXError_NeXT - memory exceeded ");
- return -1;
- }
-
- PSgsave();
- /* PSsetlinewidth(0.15); NeXT's magic number for fast drawing */
-
- /* get into user coords */
- PStranslate (innerRect.origin.x, innerRect.origin.y);
- PSscale (xScale, yScale);
- PStranslate (-userRect.origin.x, -userRect.origin.y);
-
- do
- {
- if (nCoords > maxnpts) count = maxnpts;
- else count = nCoords;
-
- ci = oi = 0;
-
- for (i = 0; i < count; i++)
- {
- coords++; /* skip over this x coord - not needed */
- y = *coords++; /* y coord */
- xhi = *errorXs++; /* x of high end of error bar */
- xlo = *errorXs++; /* x of low end of error bar */
-
- cArray[ci++] = xlo;
- cArray[ci++] = y;
- oArray[oi++] = dps_moveto; /* move to mid bottom */
-
- cArray[ci++] = xhi;
- cArray[ci++] = y;
- oArray[oi++] = dps_lineto; /* line to mid top */
-
- cArray[ci++] = xlo;
- cArray[ci++] = y - halfErrorCap;
- oArray[oi++] = dps_moveto; /* move to top left */
-
- cArray[ci++] = xlo;
- cArray[ci++] = y + halfErrorCap;
- oArray[oi++] = dps_lineto; /* line to top right */
-
- cArray[ci++] = xhi;
- cArray[ci++] = y - halfErrorCap;
- oArray[oi++] = dps_moveto; /* move to bottom left */
-
- cArray[ci++] = xhi;
- cArray[ci++] = y + halfErrorCap;
- oArray[oi++] = dps_lineto; /* line to bottom right */
- }
-
- DPSDoUserPathWithMatrix(cArray, ci, dps_float, oArray, oi, bbox,
- dps_ustroke, ctm_matrix);
- nCoords -= count;
- }
- while (nCoords > 0);
-
- PSgrestore();
-
- free (cArray);
- free (oArray);
- return 0;
- }
-
- int drawYTicks_NeXT( float *y, int nt, float tickwidth, int side )
- {
- int ci, oi, i;
- float *cArray;
- char *oArray;
- float start;
- float ctm_matrix[6] = {1.0/xScale, 0.0, 0.0, 1.0/yScale, 0.0, 0.0 };
-
- tickwidth /= xScale;
-
- if (side == 0)
- start = userRect.origin.x;
- else
- start = userRect.origin.x + userRect.size.width - tickwidth;
-
- if ((cArray = (float *) malloc (4 * nt * sizeof(float))) == NULL)
- {
- h_error("drawYTicks_NeXT - memory exceeded ");
- return -1;
- }
-
- if ((oArray = (char *) malloc (2 * nt * sizeof(char))) == NULL)
- {
- h_error("drawYTicks_NeXT - memory exceeded ");
- return -1;
- }
-
- PSgsave();
-
- /* get into user coords */
- PStranslate (innerRect.origin.x, innerRect.origin.y);
- PSscale (xScale, yScale);
- PStranslate (-userRect.origin.x, -userRect.origin.y);
-
- ci = oi = 0;
-
- for (i = 0; i < nt; i++)
- {
- cArray[ci++] = start;
- cArray[ci++] = y[i];
- oArray[oi++] = dps_moveto;
-
- cArray[ci++] = tickwidth;
- cArray[ci++] = 0.0;
- oArray[oi++] = dps_rlineto;
- }
- DPSDoUserPathWithMatrix(cArray, ci, dps_float, oArray, oi, bbox,
- dps_ustroke, ctm_matrix);
- PSgrestore();
-
- free(cArray);
- free(oArray);
-
- return 0;
- }
-
- int drawXTicks_NeXT( float *y, int nt, float tickwidth, int side )
- {
- int ci, oi, i;
- float *cArray;
- float start;
- char *oArray;
- float ctm_matrix[6] = {1.0/xScale, 0.0, 0.0, 1.0/yScale, 0.0, 0.0 };
-
- tickwidth /= yScale;
-
- if (side == 0)
- start = userRect.origin.y;
- else
- start = userRect.origin.y + userRect.size.height - tickwidth;
-
- if ((cArray = (float *) malloc (4 * nt * sizeof(float))) == NULL)
- {
- h_error("drawYTicks_NeXT - memory exceeded ");
- return -1;
- }
-
- if ((oArray = (char *) malloc (2 * nt * sizeof(char))) == NULL)
- {
- h_error("drawYTicks_NeXT - memory exceeded ");
- return -1;
- }
-
- PSgsave();
-
- /* get into user coords */
- PStranslate (innerRect.origin.x, innerRect.origin.y);
- PSscale (xScale, yScale);
- PStranslate (-userRect.origin.x, -userRect.origin.y);
-
- ci = oi = 0;
-
- for (i = 0; i < nt; i++)
- {
- cArray[ci++] = y[i];
- cArray[ci++] = start;
- oArray[oi++] = dps_moveto;
-
- cArray[ci++] = 0.0;
- cArray[ci++] = tickwidth;
- oArray[oi++] = dps_rlineto;
- }
- DPSDoUserPathWithMatrix(cArray, ci, dps_float, oArray, oi, bbox,
- dps_ustroke, ctm_matrix);
- PSgrestore();
-
- free(cArray);
- free(oArray);
-
- return 0;
- }
-
- int drawMag_NeXT(float x, float y, int mag, float fontSize)
- {
- char str[10];
-
- PSselectfont("Helvetica",fontSize);
- PSmoveto( x, y );
- PSshow("x10");
- PSrmoveto( 0.0, 0.5*fontSize );
- sprintf(str,"%d",mag);
- PSshow(str);
-
- return 0;
- }
-
-
- int drawText_NeXT(char *string, float x, float y, float fontSize,
- float rotation, char xAlign, char yAlign)
- {
- float yStep = 0.0;
-
- switch (yAlign)
- {
- case 'C':
- case 'c':
- yStep = 0.4;
- break;
-
- case 'T':
- case 't':
- yStep = 0.8;
- break;
- }
-
- switch (xAlign)
- {
- case 'C':
- case 'c':
- drawTextPS( string, x, y, fontSize, rotation, 0.5, yStep,
- "Helvetica" );
- break;
-
- case 'R':
- case 'r':
- drawTextPS( string, x, y, fontSize, rotation, 1.0, yStep,
- "Helvetica" );
- break;
-
- case 'L':
- case 'l':
- default:
- drawTextPS( string, x, y, fontSize, rotation, 0.0, yStep,
- "Helvetica" );
- break;
- }
-
- return 0;
- }
-
-
-
- int drawColor2D_NeXT(int nXBins, int nYBins, rectangle *marginRect,
- float *data, float binMin, float binMax, int useColor )
- {
- int iBin, iYBin;
- int totBins = nXBins * nYBins;
- float xlo = marginRect->origin.x;
- float xhi = xlo + marginRect->size.width;
- float ylo = marginRect->origin.y;
- float yhi = ylo + marginRect->size.height;
- float deltaX = (xhi - xlo) / nXBins;
- float deltaY = (yhi - ylo) / nYBins;
- NXRect *rects;
- int iRect, nRects;
- int rectChunk = 30; /* >40 rects at a time seems to overflow PS */
- float *grays;
- float colorScale, blueHue, magHue, saturation, brightness;
- float grayScale, nearWhite = 0.9;
- float xCoord, yCoord;
- int i;
- NXColor myColor;
- float myHue;
-
- /*
- * alloc space for every rect,
- * even though we will only draw the non-zero ones
- */
- if ((rects = (NXRect *) malloc (totBins * sizeof (NXRect))) == NULL)
- {
- h_error("drawColor2D_NeXT - memory exceeded ");
- return -1;
- }
-
- if ((grays = (float *) malloc (totBins * sizeof (float))) == NULL)
- {
- h_error("drawColor2D_NeXT - memory exceeded ");
- return -1;
- }
-
- /*
- * this routine leaves color in unpredictable state,
- * so we need a gsave/grestore
- */
- PSgsave();
-
- if (binMin == binMax)
- grayScale = 1.0;
- else
- grayScale = nearWhite / (binMax - binMin);
- xCoord = xlo;
- yCoord = ylo;
- iYBin = 0;
- iRect = 0;
- for (iBin = 0; iBin < totBins; iBin++)
- {
- /* bins are arranged as bins[x][y] with y changing fastest */
- if (data[iBin] != 0)
- {
- NXSetRect (&rects[iRect], xCoord, yCoord, deltaX, deltaY);
- /*
- * we set the grey value to the range:
- * black (most) to nearWhite (least)
- */
- grays[iRect] = (binMax - data[iBin]) * grayScale;
- iRect ++;
- }
- yCoord += deltaY;
- iYBin++;
- if ( iYBin == nYBins)
- {
- iYBin = 0;
- yCoord = ylo;
- xCoord += deltaX;
- }
- }
-
- if (! useColor)
- {
- /* do the greyscale version */
- for (i = 0; i < iRect; i += rectChunk)
- {
- nRects = rectChunk;
- if ((iRect - i) < rectChunk) nRects = (iRect - i);
- NXRectFillListWithGrays (&rects[i], &grays[i], nRects);
- }
- }
- else
- {
- /* do the color version */
-
- /* set background to black */
- NXSetColor (NX_COLORBLACK);
- NXRectFill ((NXRect *) marginRect);
-
- /* establish the color scale */
- NXConvertColorToHSB (NX_COLORBLUE, &blueHue,
- &saturation, &brightness);
- NXConvertColorToHSB (NX_COLORMAGENTA, &magHue,
- &saturation, &brightness);
-
- /*
- * start at magenta (hot), increase to 1.0,
- * then wraparound to 0.0 and up to blue (cold)
- */
- colorScale = (1.0 - magHue + blueHue) / nearWhite;
-
- for (i=0; i < iRect; i++)
- {
- myHue = magHue + (grays[i] * colorScale);
- if (myHue > 1.0) myHue = myHue - 1.0;
- myColor = NXConvertHSBToColor (myHue, 1.0, 1.0);
- NXSetColor (myColor);
- NXRectFill (&rects[i]);
- }
- }
- free (rects);
- free (grays);
-
- /*
- * color/gray is left unpredictable, so we need a gsave/grestore
- */
- PSgrestore();
- return 0;
- }
-
-
- int drawLego2D_NeXT(rectangle *marginRect)
- {
- /* set fontsize to 0.5 * top margin, with a max of 24.0 points */
- float fontHeight= 0.2 * marginRect->origin.y;
- if (fontHeight > 24.0) fontHeight = 24.0;
-
- drawText_NeXT("Not implemented yet.",
- marginRect->origin.x + marginRect->size.width*0.5,
- marginRect->origin.y + marginRect->size.height*0.5,
- fontHeight,0.0,'c','c');
- return 0;
- }
-
- int shade_NeXT(float xlow, float xhigh, float ylow, float yhigh )
- {
- NXRect myRect;
-
- PSgsave();
- /* PSsetalpha(0.0);*/
- PSsetgray(0.6);
- NXSetRect(&myRect, xlow, ylow, (xhigh-xlow),(yhigh-ylow));
- NXRectFill(&myRect);
- PSgrestore();
-
- return 0;
- }
-
-