This is hplotPS.c in view mode; [Download] [Up]
/* * hippoplotPS.c - Postscript routines for displaying hippo ntuples. * * Copyright (C) 1991 The Board of Trustees of The Leland Stanford * Junior University. All Rights Reserved. * * $Id: hplotPS.c,v 5.0 1993/08/17 21:55:51 rensing Exp $ * * by Paul Rensing, Apr. 8, 1992 */ #include <string.h> #include <stdlib.h> #include <math.h> #include "hippo.h" #include "h3D.h" #include "hplotPS.h" #include "hutil.h" #define MIN(x, y) (((x) > (y)) ? (y) : (x)) #define YPADDING(disp) ((disp)->drawRect.size.height*0.01) /* various globals */ GLOB_QUAL const char hippoplotPS_c_rcsid[] = "$Id: hplotPS.c,v 5.0 1993/08/17 21:55:51 rensing Exp $"; GLOB_QUAL const char hippoplotPS_h_rcsid[] = _HIPPOPLOTPS_H_RCSID_; /* * other constants */ #define PI 3.1415926536 #define TWOPI (2.0*PI) #define HALFPI (PI/2.0) #define MAXNPTS_PRINT 500 static struct { float xScale; float yScale; float xMarg; float yMarg; float margWidth; float margHeight; float xOrig; float yOrig; float xMax; float yMax; } data; static float ctm_matrix[6] = {0.0,0.0,0.0,0.0,0.0,0.0}; static FILE *outfile = stdout; static int inPage = 0; static int nPages = 0; /* * External C Functions */ int drawText(char *s, float x, float y, float fontsize, float angle, char xp, char yp ); /* * Internal C Functions */ static void drawSides_PS(display disp, int inside); static void drawWireFrame_PS(display disp); static void drawMesh_PS(display disp); static void drawTextVar(char *message, float x, float y, float fontSize, float rotation, float xAlignStep, float yAlignStep, char *fontName); int initDrvr_PS( FILE *fl ) { outfile = fl; fprintf(outfile,"%%!PS-Adobe-2.0\n"); fprintf(outfile,"%%%%Creator: hippoplotamus\n"); fprintf(outfile,"%%%%Pages: (atend) 1\n"); fprintf(outfile,"%%%%BoundingBox: (atend)\n"); fprintf(outfile,"%%%%EndComments\n"); fprintf(outfile,"\n\n"); fprintf(outfile,"%% Add emulation of selectfont if needed\n"); fprintf(outfile,"%% taken from PS Lang. Ref. Manual, Appendix D.4\n"); fprintf(outfile,"/*SF {\n"); fprintf(outfile," exch findfont exch\n"); fprintf(outfile, " dup type /arraytype eq {makefont}{scalefont} ifelse setfont\n"); fprintf(outfile,"} bind def\n"); fprintf(outfile,"\n"); fprintf(outfile,"/languagelevel where\n"); fprintf(outfile," {pop languagelevel} {1} ifelse\n"); fprintf(outfile, "2 lt {/SF /*SF load def}{/SF /selectfont load def} ifelse\n"); return 0; } int endDrvr_PS( void ) { endPage_PS(); fprintf(outfile,"%%%%Pages: %d %d\n",nPages,nPages); return 0; } int initPlot_PS( rectangle *draw, rectangle *margin, rectangle *user ) { data.xScale = margin->size.width/user->size.width; data.yScale = margin->size.height/user->size.height; data.xMarg = margin->origin.x; data.yMarg = margin->origin.y; data.margWidth = margin->size.width; data.margHeight = margin->size.height; data.xOrig = user->origin.x; data.yOrig = user->origin.y; data.xMax = user->origin.x + user->size.width; data.yMax = user->origin.y + user->size.height; ctm_matrix[0] = 1.0/data.xScale; ctm_matrix[3] = 1.0/data.yScale; inPage = 1; fprintf(outfile,"%%\n%%\n"); return 0; } int endPage_PS( void ) { if (inPage) { fprintf(outfile,"showpage\n"); fprintf(outfile,"%%\n%%\n"); } inPage = 0; return 0; } int drawLine_PS(float *coords, int nCoords, linestyle_t linest) { int i; int repeatCount; /* this number + 32 must be < 255 */ /* to display and < 127 for printing */ /* to fit in 1 char */ float *co; int count; fprintf(outfile,"%% drawLine_PS\n"); repeatCount = 92; /* work around apparent bug */ fprintf(outfile,"gsave "); /* get into user coords */ fprintf(outfile,"%f %f translate ",data.xMarg, data.yMarg); fprintf(outfile,"%f %f scale ",data.xScale, data.yScale); fprintf(outfile,"%f %f translate\n", -data.xOrig, -data.yOrig); switch (linest) { default: case SOLID: fprintf(outfile,"[] 0 setdash\n"); break; case DOT: fprintf(outfile,"[3 5] 0 setdash\n"); break; case DASH: fprintf(outfile,"[5 3] 0 setdash\n"); break; case DOTDASH: fprintf(outfile,"[5 3 1 3] 0 setdash\n"); break; } co = coords; do { if (nCoords > repeatCount) count = repeatCount; else count = nCoords; fprintf(outfile,"gsave\nnewpath systemdict begin\n"); fprintf(outfile,"%f %f moveto\n",*co,*(co+1)); co += 2; for (i=1; i<count; i++, co += 2) fprintf(outfile,"%f %f lineto\n",*co, *(co+1)); fprintf(outfile,"end\n[%f %f %f %f %f %f] concat\n", ctm_matrix[0],ctm_matrix[1],ctm_matrix[2], ctm_matrix[3],ctm_matrix[4],ctm_matrix[5]); fprintf(outfile,"stroke grestore\n"); co -= 2; /* back up to connect segments */ nCoords -= (count - 1); } while (nCoords > 1); /* 1 because we always back up 1 point */ /* to connect the segments */ fprintf(outfile,"grestore\n"); return 0; } int drawPoints_PS(float *coords, int nCoords, plotsymbol_t symbol, float symbolSize) { int i; int filled=0; int count; int maxnpts; float xPointSide, yPointSide; float xHalfPointSide, yHalfPointSide; fprintf(outfile,"%% drawPoints_PS\n"); maxnpts = MAXNPTS_PRINT; if (symbol == SOLIDSQUARE) filled = 1; if (filled) maxnpts /= 5; xPointSide = symbolSize / data.xScale; yPointSide = symbolSize / data.yScale; xHalfPointSide = xPointSide / 2.0; yHalfPointSide = yPointSide / 2.0; fprintf(outfile,"gsave\n"); /* get into user coords */ fprintf(outfile,"%f %f translate ", data.xMarg, data.yMarg); fprintf(outfile,"%f %f scale ", data.xScale, data.yScale); fprintf(outfile,"%f %f translate\n", -data.xOrig, -data.yOrig); if (nCoords > maxnpts) i = maxnpts; else i = nCoords; do { if (nCoords > maxnpts) count = maxnpts; else count = nCoords; fprintf(outfile,"gsave\nnewpath systemdict begin\n"); switch (symbol) { case SQUARE: case SOLIDSQUARE: for (i = 0; i < count; i++) { fprintf(outfile,"%f %f moveto\n", *coords - xHalfPointSide, *(coords+1) - yHalfPointSide); coords += 2; fprintf(outfile,"%f %f rlineto\n", xPointSide, 0.0); fprintf(outfile,"%f %f rlineto\n", 0.0, yPointSide); fprintf(outfile,"%f %f rlineto\n", -xPointSide, 0.0); fprintf(outfile,"closepath\n"); } break; case PLUS: for (i = 0; i < count; i++) { fprintf(outfile,"%f %f moveto\n", *coords - xHalfPointSide, *(coords+1)); coords += 2; fprintf(outfile,"%f %f rlineto\n", xPointSide, 0.0); fprintf(outfile,"%f %f rmoveto\n", -xHalfPointSide, yHalfPointSide); fprintf(outfile,"%f %f rlineto\n", 0.0, -yPointSide); } break; case TIMES: for (i = 0; i < count; i++) { fprintf(outfile,"%f %f moveto\n", *coords - xHalfPointSide, *(coords+1) - yHalfPointSide); coords += 2; fprintf(outfile,"%f %f rlineto\n", xPointSide, yPointSide); fprintf(outfile,"%f %f rmoveto\n", 0.0, yPointSide); fprintf(outfile,"%f %f rlineto\n", xPointSide, -yPointSide); } break; default: break; } if (filled) { fprintf(outfile,"end\n"); fprintf(outfile,"fill grestore\n"); } else { fprintf(outfile,"end\n[%f %f %f %f %f %f] concat\n", ctm_matrix[0],ctm_matrix[1],ctm_matrix[2], ctm_matrix[3],ctm_matrix[4],ctm_matrix[5]); fprintf(outfile,"stroke grestore\n"); } nCoords -= count; } while (nCoords > 0); fprintf(outfile,"grestore\n"); return 0; } int drawYError_PS(float *coords, float *errorYs, int nCoords) { #define ERRORCAPSIZE 2.0 int i; int count; int maxnpts; float x, yhi, ylo; float halfErrorCap = ERRORCAPSIZE/data.xScale * 0.5; fprintf(outfile,"%% drawYError_PS\n"); maxnpts = MAXNPTS_PRINT; if (nCoords > maxnpts) i = maxnpts; else i = nCoords; fprintf(outfile,"gsave\n"); /* get into user coords */ fprintf(outfile,"%f %f translate ", data.xMarg, data.yMarg); fprintf(outfile,"%f %f scale ", data.xScale, data.yScale); fprintf(outfile,"%f %f translate\n", -data.xOrig, -data.yOrig); do { if (nCoords > maxnpts) count = maxnpts; else count = nCoords; fprintf(outfile,"gsave\nnewpath systemdict begin\n"); 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 */ fprintf(outfile,"%f %f moveto\n",x,ylo); fprintf(outfile,"%f %f lineto\n",x,yhi); fprintf(outfile,"%f %f moveto\n", x - halfErrorCap, yhi); fprintf(outfile,"%f %f lineto\n", x + halfErrorCap, yhi); fprintf(outfile,"%f %f moveto\n", x - halfErrorCap, ylo); fprintf(outfile,"%f %f lineto\n", x + halfErrorCap, ylo); } fprintf(outfile,"end\n[%f %f %f %f %f %f] concat\n", ctm_matrix[0],ctm_matrix[1],ctm_matrix[2], ctm_matrix[3],ctm_matrix[4],ctm_matrix[5]); fprintf(outfile,"stroke grestore\n"); nCoords -= count; } while (nCoords > 0); fprintf(outfile,"grestore\n"); return 0; } int drawXError_PS(float *coords, float *errorXs, int nCoords) { int i; int count; int maxnpts; float halfErrorCap = ERRORCAPSIZE/data.yScale * 0.5; float y, xlo, xhi; fprintf(outfile,"%% drawXError_PS\n"); maxnpts = MAXNPTS_PRINT; if (nCoords > maxnpts) i = maxnpts; else i = nCoords; fprintf(outfile,"gsave\n"); /* get into user coords */ fprintf(outfile,"%f %f translate ", data.xMarg, data.yMarg); fprintf(outfile,"%f %f scale ", data.xScale, data.yScale); fprintf(outfile,"%f %f translate\n", -data.xOrig, -data.yOrig); do { if (nCoords > maxnpts) count = maxnpts; else count = nCoords; fprintf(outfile,"gsave\nnewpath systemdict begin\n"); 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 */ fprintf(outfile,"%f %f moveto\n",xlo,y); fprintf(outfile,"%f %f lineto\n",xhi,y); fprintf(outfile,"%f %f moveto\n", xlo, y - halfErrorCap); fprintf(outfile,"%f %f lineto\n", xlo, y + halfErrorCap); fprintf(outfile,"%f %f moveto\n", xhi, y - halfErrorCap); fprintf(outfile,"%f %f lineto\n", xhi, y + halfErrorCap); } fprintf(outfile,"end\n[%f %f %f %f %f %f] concat\n", ctm_matrix[0],ctm_matrix[1],ctm_matrix[2], ctm_matrix[3],ctm_matrix[4],ctm_matrix[5]); fprintf(outfile,"stroke grestore\n"); nCoords -= count; } while (nCoords > 0); fprintf(outfile,"grestore\n"); return 0; } int drawYTicks_PS( float *y, int nt, float tickwidth, int side ) { int i; float start; tickwidth /= data.xScale; fprintf(outfile,"%% drawYTicks_PS\n"); if (side == 0) start = data.xOrig; else start = data.xMax - tickwidth; fprintf(outfile,"gsave\n"); /* get into user coords */ fprintf(outfile,"%f %f translate ", data.xMarg, data.yMarg); fprintf(outfile,"%f %f scale ", data.xScale, data.yScale); fprintf(outfile,"%f %f translate\n",-data.xOrig, -data.yOrig); fprintf(outfile,"newpath systemdict begin\n"); for (i = 0; i < nt; i++) { fprintf(outfile,"%f %f moveto ", start, y[i] ); fprintf(outfile,"%f %f rlineto\n", tickwidth, 0.0 ); } fprintf(outfile,"end\n[%f %f %f %f %f %f] concat\n", ctm_matrix[0],ctm_matrix[1],ctm_matrix[2], ctm_matrix[3],ctm_matrix[4],ctm_matrix[5]); fprintf(outfile,"stroke\n"); fprintf(outfile,"grestore\n"); return 0; } int drawXTicks_PS( float *y, int nt, float tickwidth, int side ) { int i; float start; tickwidth /= data.yScale; fprintf(outfile,"%% drawXTicks_PS\n"); if (side == 0) start = data.yOrig; else start = data.yMax - tickwidth; fprintf(outfile,"gsave\n"); /* get into user coords */ fprintf(outfile,"%f %f translate ", data.xMarg, data.yMarg); fprintf(outfile,"%f %f scale ", data.xScale, data.yScale); fprintf(outfile,"%f %f translate\n", -data.xOrig, -data.yOrig); fprintf(outfile,"newpath systemdict begin\n"); for (i = 0; i < nt; i++) { fprintf(outfile,"%f %f moveto ", y[i], start ); fprintf(outfile,"%f %f rlineto\n", 0.0, tickwidth ); } fprintf(outfile,"end\n[%f %f %f %f %f %f] concat\n", ctm_matrix[0],ctm_matrix[1],ctm_matrix[2], ctm_matrix[3],ctm_matrix[4],ctm_matrix[5]); fprintf(outfile,"stroke\n"); fprintf(outfile,"grestore\n"); return 0; } int drawMag_PS(float x, float y, int mag, float fontSize) { char str[10]; fprintf(outfile,"%% drawMag_PS\n"); fprintf(outfile,"(Helvetica) %f SF\n",fontSize); fprintf(outfile,"%f %f moveto\n", x, y ); fprintf(outfile,"(x10) show"); fprintf(outfile,"%f %f rmoveto\n", 0.0, 0.5*fontSize ); sprintf(str,"%d",mag); fprintf(outfile,"(%s) show\n", str); return 0; } int drawText_PS(char *string, float x, float y, float fontSize, float rotation, char xAlign, char yAlign) { float xStep = 0.0, yStep = 0.0; fprintf(outfile,"%% drawText_PS\n"); switch (yAlign) { case 'C': case 'c': yStep = 0.4; break; case 'T': case 't': yStep = 0.8; break; } switch (xAlign) { case 'C': case 'c': xStep = 0.5; break; case 'R': case 'r': xStep = 1.0; break; } fprintf(outfile,"gsave\n"); fprintf(outfile,"(Helvetica) %f SF\n", fontSize); fprintf(outfile,"%f %f translate %f rotate\n",x,y,rotation); fprintf(outfile,"(%s) stringwidth pop\n", string); fprintf(outfile,"%f neg mul %f moveto\n",xStep,-fontSize*yStep); fprintf(outfile,"(%s) show\n",string); fprintf(outfile,"grestore\n"); return 0; } int drawColor2D_PS(int nXBins, int nYBins, float binMin, float binMax, float *bins, int useColor ) { int iYBin; int totBins = nXBins * nYBins; float deltaX = data.margWidth / nXBins; float deltaY = data.margHeight / nYBins; float grayScale, nearWhite = 0.9; float xCoord, yCoord; int i, count; int maxnpts = 30; fprintf(outfile,"%% drawColor2D_PS\n"); /* * this routine leaves color in unpredictable state, * so we need a gsave/grestore */ fprintf(outfile,"gsave\n"); if (binMin == binMax) grayScale = 1.0; else grayScale = nearWhite / (binMax - binMin); xCoord = data.xMarg; yCoord = data.yMarg; iYBin = 0; do { if (totBins > maxnpts) count = maxnpts; else count = totBins; for (i = 0; i < count; i++) { /* bins are arranged as bins[x][y] with y changing fastest */ fprintf(outfile,"newpath systemdict begin\n"); fprintf(outfile,"%f setgray\n", (binMax - *bins)*grayScale); fprintf(outfile,"%f %f moveto %f %f rlineto\n", xCoord, yCoord, deltaX, 0.0 ); fprintf(outfile,"%f %f rlineto %f %f rlineto closepath\n", 0.0, deltaY, -deltaX, 0.0 ); fprintf(outfile,"end fill\n"); bins++; yCoord += deltaY; iYBin++; if ( iYBin == nYBins) { iYBin = 0; yCoord = data.yMarg; xCoord += deltaX; } } totBins -= count; } while (totBins > 0); fprintf(outfile,"grestore\n"); return 0; } int drawScatter3D_PS(display disp, float *coords, int nCoords) { threeD_t *threeD; static int inside = 1, outside = 0; float x, y; float fontSize; char string[80]; int i; int filled=0; int count; int maxnpts; float symSize; float *newCoords; float xPointSide, yPointSide; float xHalfPointSide, yHalfPointSide; if (disp->threeDWorkArea == NULL) h3D_init3D(disp); threeD = disp->threeDWorkArea; /* set local pointer */ fprintf(outfile,"%% drawScatter3D_PS\n"); if (disp->plotSymbol == SOLIDSQUARE) filled = 1; maxnpts = MAXNPTS_PRINT; if (filled) maxnpts /= 5; /* Check that correct 'user space' is set */ if (disp->doScatter) { h3D_checkPointScale(disp, nCoords); } /* * Get into user plotting space, ie (-1,-1) to (+1,+1) * This is the user 3D space after going through the transformation to 2D */ fprintf(outfile,"gsave\n"); fprintf(outfile,"0.0 setlinewidth\n"); fprintf(outfile,"%f %f translate\n", disp->drawRect.origin.x, disp->drawRect.origin.y); fprintf(outfile,"%f %f scale\n", disp->drawRect.size.width/2.0, disp->drawRect.size.height/2.0); fprintf(outfile,"1.0 1.0 translate\n"); /* * Now do transformations */ if (disp->doCube && disp->flags.drawAxes) { h3D_transformCube(disp); drawSides_PS(disp, inside); } if (disp->doScatter) { if (threeD->reCalculateScatterPoints) { h3D_checkAllocScatterResults(disp, nCoords); h3D_renderXYPS(disp, coords); threeD->reCalculateScatterPoints = 0; } newCoords = threeD->scatterResults; symSize = disp->symbolSize*(2.0/disp->drawRect.size.width); xPointSide = symSize; yPointSide = symSize; xHalfPointSide = xPointSide / 2.0; yHalfPointSide = yPointSide / 2.0; if (nCoords > maxnpts) i = maxnpts; else i = nCoords; do { if (nCoords > maxnpts) count = maxnpts; else count = nCoords; fprintf(outfile,"gsave\nnewpath systemdict begin\n"); switch (disp->plotSymbol) { case SQUARE: case SOLIDSQUARE: for (i = 0; i < count; i++) { fprintf(outfile,"%f %f moveto\n", *newCoords - xHalfPointSide, *(newCoords+1) - yHalfPointSide); newCoords += 2; fprintf(outfile,"%f %f rlineto\n", xPointSide, 0.0); fprintf(outfile,"%f %f rlineto\n", 0.0, yPointSide); fprintf(outfile,"%f %f rlineto\n", -xPointSide, 0.0); fprintf(outfile,"closepath\n"); } break; case PLUS: for (i = 0; i < count; i++) { fprintf(outfile,"%f %f moveto\n", *newCoords - xHalfPointSide, *(newCoords+1)); newCoords += 2; fprintf(outfile,"%f %f rlineto\n", xPointSide, 0.0); fprintf(outfile,"%f %f rmoveto\n", -xHalfPointSide, yHalfPointSide); fprintf(outfile,"%f %f rlineto\n", 0.0, -yPointSide); } break; case TIMES: for (i = 0; i < count; i++) { fprintf(outfile,"%f %f moveto\n", *newCoords - xHalfPointSide, *(newCoords+1) - yHalfPointSide); newCoords += 2; fprintf(outfile,"%f %f rlineto\n", xPointSide, yPointSide); fprintf(outfile,"%f %f rmoveto\n", 0.0, yPointSide); fprintf(outfile,"%f %f rlineto\n", xPointSide, -yPointSide); } break; default: break; } if (filled) { fprintf(outfile,"end\n"); fprintf(outfile,"fill grestore\n"); } else { fprintf(outfile,"end\n[%f %f %f %f %f %f] concat\n", ctm_matrix[0],ctm_matrix[1],ctm_matrix[2], ctm_matrix[3],ctm_matrix[4],ctm_matrix[5]); fprintf(outfile,"stroke grestore\n"); } nCoords -= count; } while (nCoords > 0); } if (disp->doCube && disp->flags.drawAxes) { drawSides_PS(disp, outside); } fprintf(outfile,"grestore\n"); if (disp->flags.drawTitles) { fontSize = disp->drawRect.size.width*0.05; fontSize = MIN(fontSize, (disp->drawRect.size.height - disp->marginRect.size.height - 2*YPADDING(disp) - (disp->marginRect.origin.y-disp->drawRect.origin.y))); x = disp->marginRect.origin.x + 0.5 * disp->marginRect.size.width; y = disp->drawRect.origin.y + disp->drawRect.size.height - YPADDING(disp); h_expandLabel(string,disp->title,80,disp); if (fontSize > disp->marginRect.size.width/strlen(string)*2) { fontSize = disp->drawRect.size.width/strlen(string)*2; x = disp->drawRect.origin.x + 0.5 * disp->drawRect.size.width; } drawText(string, x, y, fontSize, 0.0, 'c', 't'); } return 0; } static void drawSides_PS(display disp, int inside) { threeD_t *threeD; int side, p, q, r, s; int insideVisible, showFace; int i; static int corners[4][4] = {0, 1, 5, 4, 1, 2, 6, 5, 2, 3, 7, 6, 3, 0, 4, 7}; static int leftmostChoices[4][2] = {3, 2, 0, 3, 1, 0, 2, 1}; int firstChoice, secondChoice; int doFirstChoice; float *tickU, *tickV, *tickU2, *tickV2; float tickLength = 0.03; float tickFontSize=0.05, strShift, labelFontSize=0.08; char *font = "Times-Roman"; float labelX, labelY, labelShift = 0.14, labelAngle; float labelRotation; char string[80]; threeD = disp->threeDWorkArea; /* set local pointer */ /* figure out whose left edge to put the tick marks on */ firstChoice = leftmostChoices[threeD->preferredFace][0]; secondChoice = leftmostChoices[threeD->preferredFace][1]; doFirstChoice = 0; for (side = 0; side < 4; side++) { p = corners[side][0]; q = corners[side][1]; r = corners[side][2]; s = corners[side][3]; insideVisible = 0; if (threeD->cubeV[q] > threeD->cubeV[p]) { if (threeD->cubeU[s] > (threeD->cubeU[p] + (threeD->cubeV[s] - threeD->cubeV[p]) * (threeD->cubeU[r] - threeD->cubeU[p]) / (threeD->cubeV[r] - threeD->cubeV[p]))) { insideVisible = 1; } } else { if (threeD->cubeU[p] > (threeD->cubeU[q] + (threeD->cubeV[p] - threeD->cubeV[q]) * (threeD->cubeU[s] - threeD->cubeU[q]) / (threeD->cubeV[s] - threeD->cubeV[q]))) { insideVisible = 1; } } showFace = (inside) ? insideVisible : !insideVisible; if (showFace) { fprintf(outfile,"0.0 setgray\n"); fprintf(outfile,"%f %f moveto\n", threeD->cubeU[p], threeD->cubeV[p]); fprintf(outfile,"%f %f lineto\n", threeD->cubeU[q], threeD->cubeV[q]); fprintf(outfile,"%f %f lineto\n", threeD->cubeU[r], threeD->cubeV[r]); fprintf(outfile,"%f %f lineto\n", threeD->cubeU[s], threeD->cubeV[s]); fprintf(outfile,"closepath\n"); fprintf(outfile,"stroke\n"); /* now do the inside and outside tick marks */ if (!disp->doSpeedy) { if (inside) { if (threeD->nZTicks > 0) { if (side == firstChoice) doFirstChoice = 1; fprintf(outfile,"gsave\n"); fprintf(outfile,"[.005 .01] 0 setdash\n"); /* point to correct ticks for these 2 verticals */ tickU = &threeD->zTickU[p * threeD->nZTicks]; tickV = &threeD->zTickV[p * threeD->nZTicks]; tickU2 = &threeD->zTickU[q * threeD->nZTicks]; tickV2 = &threeD->zTickV[q * threeD->nZTicks]; for (i = 0; i < threeD->nZTicks; i++) { fprintf(outfile,"%f %f moveto\n", tickU[i], tickV[i]); fprintf(outfile,"%f %f lineto\n", tickU2[i], tickV2[i]); } fprintf(outfile,"stroke\n"); fprintf(outfile,"grestore\n"); /* remove setdash */ } } else { /* do base ticks for outside face */ p = corners[side][0]; if (p == 0 || p == 2) { if (threeD->nXTicks > 0) { /* point to correct set * of x ticks for this * base line */ tickU = &threeD->xTickU[(p / 2) * threeD->nXTicks]; tickV = &threeD->xTickV[(p / 2) * threeD->nXTicks]; for (i = 0; i < threeD->nXTicks; i++) { fprintf(outfile,"%f %f moveto\n", tickU[i], tickV[i]); fprintf(outfile,"%f %f rlineto\n", 0.0, -tickLength); if (disp->theta < -HALFPI || disp->theta > HALFPI) { strShift = 0.5 * (1.0 + sin(disp->theta)); } else { strShift = 0.5 * (1.0 - sin(disp->theta)); } drawTextVar(threeD->xLabels[i], tickU[i], (tickV[i]-tickLength-0.04), tickFontSize, 0.0, strShift, 0.0, font); } fprintf(outfile,"stroke\n"); if (disp->flags.drawTitles) { labelAngle = atan2((tickV[threeD->nXTicks-1]-tickV[0]), (tickU[threeD->nXTicks-1]-tickU[0])); if (disp->theta < -HALFPI || disp->theta > HALFPI) labelAngle-=PI; if (labelAngle < TWOPI) labelAngle+=TWOPI; labelX = tickU[0] + (tickU[threeD->nXTicks-1]-tickU[0])/2.0 + labelShift*sin(labelAngle); labelY = tickV[0] + (tickV[threeD->nXTicks-1]-tickV[0])/2.0 - labelShift*cos(labelAngle); labelRotation = labelAngle *180.0/PI; h_expandLabel(string,disp->xAxis.label,80,disp); drawText(string, labelX, labelY, labelFontSize, labelRotation, 'C', 'T'); } } } else { if (threeD->nYTicks > 0) { /* point to correct y ticks for this base line */ tickU = &threeD->yTickU[(p / 2) * threeD->nYTicks]; tickV = &threeD->yTickV[(p / 2) * threeD->nYTicks]; for (i = 0; i < threeD->nYTicks; i++) { fprintf(outfile,"%f %f moveto\n", tickU[i], tickV[i]); fprintf(outfile,"%f %f rlineto\n", 0.0, -tickLength); if (disp->theta < 0.0) { strShift = 0.5 * (1.0 - cos(disp->theta)); } else { strShift = 0.5 * (1.0 + cos(disp->theta)); } drawTextVar(threeD->yLabels[i], tickU[i], (tickV[i]-tickLength-0.04), tickFontSize, 0.0, strShift, 0.0, font); } fprintf(outfile,"stroke\n"); if (disp->flags.drawTitles) { labelAngle = atan2((tickV[threeD->nYTicks-1]-tickV[0]), (tickU[threeD->nYTicks-1]-tickU[0])); if (disp->theta > 0.0) labelAngle-=PI; if (labelAngle < TWOPI) labelAngle+=TWOPI; labelX = tickU[0] + (tickU[threeD->nYTicks-1]-tickU[0])/2.0 + labelShift*sin(labelAngle); labelY = tickV[0] + (tickV[threeD->nYTicks-1]-tickV[0])/2.0 - labelShift*cos(labelAngle); labelRotation = labelAngle *180.0/PI; h_expandLabel(string,disp->yAxis.label,80,disp); drawText(string, labelX, labelY, labelFontSize, labelRotation, 'C', 'T'); } } } } } } } /* now the tick marks on the leftmost vertical */ if (!disp->doSpeedy) { if (threeD->nZTicks > 0) { if (inside) { if (doFirstChoice) { side = firstChoice; } else { side = secondChoice; } q = corners[side][1]; /* point to correct set of ticks for this vertical */ tickU = &threeD->zTickU[q * threeD->nZTicks]; tickV = &threeD->zTickV[q * threeD->nZTicks]; for (i = 0; i < threeD->nZTicks; i++) { fprintf(outfile,"%f %f moveto\n", tickU[i], tickV[i]); fprintf(outfile,"%f %f rlineto\n", -tickLength, 0.0); drawTextVar(threeD->zLabels[i], (tickU[i]-tickLength-0.01), tickV[i], tickFontSize, 0.0, 1.0, 0.0, font); } fprintf(outfile,"stroke\n"); if ((disp->graphtype == THREEDSCATTER) && disp->flags.drawTitles) { labelX = tickU[0] + (tickU[threeD->nZTicks-1]-tickU[0])/2.0 - labelShift; labelY = tickV[0] + (tickV[threeD->nZTicks-1]-tickV[0])/2.0; labelAngle = atan2((tickV[0]-tickV[threeD->nZTicks-1]), (tickU[0]-tickU[threeD->nZTicks-1]))*180.0/PI; h_expandLabel(string,disp->zAxis.label,80,disp); drawText(string, labelX, labelY, labelFontSize, labelAngle, 'C', 'T'); } } } } return; } /* * Draw a 'wire-frame' lego plot in the given drawing space */ static void drawWireFrame_PS(display disp) { threeD_t *threeD; float *p, *q, *u, *v; int i; threeD = disp->threeDWorkArea; /* set local pointer */ u = threeD->legoResults[0]; v = threeD->legoResults[1]; for (i = 0; i < threeD->nLegoPoints; i += 8) { p = &u[i]; q = &v[i]; fprintf(outfile,"%f %f moveto\n", p[0], q[0]); fprintf(outfile,"%f %f lineto\n", p[1], q[1]); fprintf(outfile,"%f %f lineto\n", p[2], q[2]); fprintf(outfile,"%f %f lineto\n", p[3], q[3]); fprintf(outfile,"%f %f lineto\n", p[0], q[0]); fprintf(outfile,"%f %f lineto\n", p[4], q[4]); fprintf(outfile,"%f %f lineto\n", p[5], q[5]); fprintf(outfile,"%f %f lineto\n", p[6], q[6]); fprintf(outfile,"%f %f lineto\n", p[7], q[7]); fprintf(outfile,"%f %f lineto\n", p[4], q[4]); fprintf(outfile,"%f %f moveto\n", p[1], q[1]); fprintf(outfile,"%f %f lineto\n", p[5], q[5]); fprintf(outfile,"%f %f moveto\n", p[2], q[2]); fprintf(outfile,"%f %f lineto\n", p[6], q[6]); fprintf(outfile,"%f %f moveto\n", p[3], q[3]); fprintf(outfile,"%f %f lineto\n", p[7], q[7]); } return; } /* * Draw a mesh surface through the to centers of each 'lego' */ static void drawMesh_PS(display disp) { threeD_t *threeD; float *p, *q, *u, *v; int i, j, k; threeD = disp->threeDWorkArea; /* set local pointer */ u = threeD->legoResults[0]; v = threeD->legoResults[1]; for (i = 0; i < disp->bins.xAxis.nBins; i++) { k = i * 8 * disp->bins.yAxis.nBins; p = &u[k]; q = &v[k]; fprintf(outfile,"%f %f moveto\n",((p[4]+p[6])/2.0),((q[4]+q[6])/2.0)); for (j = 1; j < disp->bins.yAxis.nBins; j++) { p = &u[k + j * 8]; q = &v[k + j * 8]; fprintf(outfile,"%f %f lineto\n",((p[4]+p[6])/2.0),((q[4]+q[6])/2.0)); } } for (j = 0; j < disp->bins.yAxis.nBins; j++) { k = j * 8; p = &u[k]; q = &v[k]; fprintf(outfile,"%f %f moveto\n",((p[4]+p[6])/2.0),((q[4]+q[6])/2.0)); for (i = 1; i < disp->bins.xAxis.nBins; i++) { p = &u[k + i * 8 * disp->bins.yAxis.nBins]; q = &v[k + i * 8 * disp->bins.yAxis.nBins]; fprintf(outfile,"%f %f lineto\n",((p[4]+p[6])/2.0),((q[4]+q[6])/2.0)); } } return; } int drawLego2D_PS(display disp) { threeD_t *threeD; int i; static int corners0[4][8] = {3, 0, 4, 7, 0, 1, 5, 4, 0, 1, 5, 4, 1, 2, 6, 5, 1, 2, 6, 5, 2, 3, 7, 6, 2, 3, 7, 6, 3, 0, 4, 7}; static int corners1[4][8] = {0, 1, 5, 4, 3, 0, 4, 7, 1, 2, 6, 5, 0, 1, 5, 4, 2, 3, 7, 6, 1, 2, 6, 5, 3, 0, 4, 7, 2, 3, 7, 6}; int *cornerIndex; int thisCorner, nearTopCorner, farTopCorner; static int inside = 1, outside = 0; float *x, *y; float titleX, titleY; float fontSize; char string[80]; if (disp->threeDWorkArea == NULL) h3D_init3D(disp); threeD = disp->threeDWorkArea; /* set local pointer */ fprintf(outfile,"%% drawLego2D_PS\n"); fprintf(outfile,"0.0 setlinewidth\n"); /* Check that correct 'user space' is set */ if (disp->doFill || disp->doWireFrame || disp->doMesh){ h3D_checkBinScale(disp); } /* * Get into user plotting space, ie (-1,-1) to (+1,+1) * This is the user 3D space after going through the transformation to 2D */ fprintf(outfile,"gsave\n"); fprintf(outfile,"%f %f translate\n", disp->drawRect.origin.x, disp->drawRect.origin.y); fprintf(outfile,"%f %f scale\n", disp->drawRect.size.width/2.0, disp->drawRect.size.height/2.0); fprintf(outfile,"1.0 1.0 translate\n"); /* * Now do transformations and drawing */ if (disp->doCube && disp->flags.drawAxes) { h3D_transformCube(disp); drawSides_PS(disp, inside); } if (disp->doFill && !disp->doSpeedy) { h3D_transformLego(disp); /* draw the blocks, starting from farthest */ for (i = threeD->numBlocks - 1; i >= 0; i--) { x = threeD->blockPointer[i]->xData; y = threeD->blockPointer[i]->yData; thisCorner = threeD->blockPointer[i]->nearCorner; if (y[4] > y[0]) { /* might as well skip drawing the zero bins */ if (thisCorner == threeD->preferredFace) { cornerIndex = &corners0[thisCorner][0]; } else { cornerIndex = &corners1[thisCorner][0]; } fprintf(outfile,"%f %f moveto\n", x[cornerIndex[0]], y[cornerIndex[0]]); fprintf(outfile,"%f %f lineto\n", x[cornerIndex[1]], y[cornerIndex[1]]); fprintf(outfile,"%f %f lineto\n", x[cornerIndex[2]], y[cornerIndex[2]]); fprintf(outfile,"%f %f lineto\n", x[cornerIndex[3]], y[cornerIndex[3]]); fprintf(outfile,"closepath\n"); fprintf(outfile,"%f setgray\n", disp->color[cornerIndex[0]]); if (disp->doWireFrame) { fprintf(outfile,"gsave fill grestore 0.0 setgray stroke\n"); } else { fprintf(outfile,"fill\n"); } fprintf(outfile,"%f %f moveto\n", x[cornerIndex[4]], y[cornerIndex[4]]); fprintf(outfile,"%f %f lineto\n", x[cornerIndex[5]], y[cornerIndex[5]]); fprintf(outfile,"%f %f lineto\n", x[cornerIndex[6]], y[cornerIndex[6]]); fprintf(outfile,"%f %f lineto\n", x[cornerIndex[7]], y[cornerIndex[7]]); fprintf(outfile,"closepath\n"); fprintf(outfile,"%f setgray\n", disp->color[cornerIndex[4]]); if (disp->doWireFrame) { fprintf(outfile,"gsave fill grestore 0.0 setgray stroke\n"); } else { fprintf(outfile,"fill\n"); } } /* determine if top is visible */ nearTopCorner = thisCorner + 4; farTopCorner = nearTopCorner + 2; if (farTopCorner > 7) farTopCorner -= 4; if (y[farTopCorner] > y[nearTopCorner]) { fprintf(outfile,"%f %f moveto\n", x[4], y[4]); fprintf(outfile,"%f %f lineto\n", x[5], y[5]); fprintf(outfile,"%f %f lineto\n", x[6], y[6]); fprintf(outfile,"%f %f lineto\n", x[7], y[7]); fprintf(outfile,"closepath\n"); fprintf(outfile,"%f setgray\n", disp->color[4]); if (disp->doWireFrame) { fprintf(outfile,"gsave fill grestore 0.0 setgray stroke\n"); } else { fprintf(outfile,"fill\n"); } } } } /* end of doFill */ else if (disp->doWireFrame || (disp->doFill && !disp->doSpeedy)) { h3D_transformWireFrame(disp); drawWireFrame_PS(disp); } if (disp->doMesh) { h3D_transformMesh(disp); drawMesh_PS(disp); } if (disp->doCube && disp->flags.drawAxes) { drawSides_PS(disp, outside); } fprintf(outfile,"grestore\n"); if (disp->flags.drawTitles) { fontSize = disp->drawRect.size.width*0.05; fontSize = MIN(fontSize, (disp->drawRect.size.height - disp->marginRect.size.height - 2*YPADDING(disp) - (disp->marginRect.origin.y-disp->drawRect.origin.y))); titleX = disp->marginRect.origin.x + 0.5 * disp->marginRect.size.width; titleY = disp->drawRect.origin.y + disp->drawRect.size.height - YPADDING(disp); h_expandLabel(string,disp->title,80,disp); if (fontSize > disp->marginRect.size.width/strlen(string)*2) { fontSize = disp->drawRect.size.width/strlen(string)*2; titleX = disp->drawRect.origin.x + 0.5 * disp->drawRect.size.width; } drawText(string, titleX, titleY, fontSize, 0.0, 'c', 't'); } return 0; } int shade_PS(float xlow, float xhigh, float ylow, float yhigh ) { fprintf(outfile,"%% shade_PS\n"); fprintf(outfile,"gsave\n"); /* PSsetalpha(0.0);*/ fprintf(outfile,"%f setgray\n", 0.6); fprintf(outfile,"newpath systemdict begin\n"); fprintf(outfile,"%f %f moveto %f %f rlineto\n", xlow, ylow, xhigh-xlow, 0.0 ); fprintf(outfile,"%f %f rlineto %f %f rlineto closepath\n", 0.0, yhigh-ylow, xlow-xhigh, 0.0 ); fprintf(outfile,"end\n"); fprintf(outfile,"fill grestore\n"); return 0; } /* * drawTextVar - draw Text with specified rotation and positioning. */ static void drawTextVar(char *message, float x, float y, float fontSize, float rotation, float xAlignStep, float yAlignStep, char *fontName) { fprintf(outfile,"gsave\n"); fprintf(outfile,"(%s) %f selectfont\n", fontName, fontSize); fprintf(outfile,"%f %f translate\n", x, y); fprintf(outfile,"%f rotate\n", rotation); fprintf(outfile,"(%s) dup stringwidth pop\n", message); fprintf(outfile,"%f neg mul %f %f neg mul moveto show\n", xAlignStep, fontSize, yAlignStep); fprintf(outfile,"grestore\n"); return; }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.