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.