home *** CD-ROM | disk | FTP | other *** search
- Path: sparky!uunet!cs.utexas.edu!zaphod.mps.ohio-state.edu!darwin.sura.net!jvnc.net!netnews.upenn.edu!bohr.physics.upenn.edu!raines
- From: raines@bohr.physics.upenn.edu (Paul Raines)
- Newsgroups: comp.lang.tcl
- Subject: Addition xygraph features (long)
- Keywords: graph
- Message-ID: <98997@netnews.upenn.edu>
- Date: 24 Nov 92 01:45:52 GMT
- Sender: news@netnews.upenn.edu
- Lines: 898
- Nntp-Posting-Host: bohr.physics.upenn.edu
-
- I have added a few addition features to xygraph:
- - a complete cross hair cursor
- - a ghost box for efficient zoom box making or
- object selection
- - an added option to the insert procedure to read
- data from a file
-
- I have also changed xygraph so that it does not ignore points
- outside the limits but draws as far as the border toward the
- point when in line mode.
-
- Three files are included below:
- graph.diff - the diff file to patch graph.c
- test.tk - a simple tk program to test the new features
- test.spe - a sample data file of short values
-
- test.tk and test.spe must be in the same directory to work. You
- can change the location of pish at the top of test.tk for your site.
-
- CROSS HAIR:
- pathName crosshair x-coord y-coord
- This procedure places a cross hair with the intersection at the
- given screen coordinates. Calling it with coordinates off the graph
- window will erase the crosshair (preferably use -10 -10 or at least
- negative numbers). Using "crosshair off" will also work. There are
- still some cases where on a graph redraw, a crosshair will get left
- on the screen. I am working on it.
-
- GHOST BOX:
- pathname ghostbox x-coord1 y-coord1 x-coord2 y-coord2
- This procedure draws a dotted line box with the two given
- points as opposite corners. The box will stay there until the
- graph is redrawn or ghostbox is called again with the same points.
- No internal variables are kept as to the last position of the ghost
- box so you have to explicitly erase it. This allows your to draw
- as many as you like in case you are using it to mark several selections
- on the graph.
-
- READ FILE:
- -bfile "filename datatype offset numpoints pttype ?xstart xstep?"
- This option to the insert procedure tells xygraph to get its values
- from filenamea file with the specified structure.
- filename - name of file to open
- datatype - one of hist, xdata, ydata, xydata
- offset - number of bytes to skip as a header
- numpoints - number of points to read from file
- pttype - one of short, long, float, double (how points stored)
- xstart - starting value for x (hist only)
- xstep - stepping value for x (hist only)
-
- xstart and xstep must be specified for hist data and must not be for
- the others. The program will complain if xstep is zero. The hist
- data type reads the y-values from the file and creates the x-values
- knowing xstart, xstep, and numpoints. The actual storage is double
- that of numpoints since it creates a stepping graph (see example).
-
- The changes to graph.c were written on a SGI running IRIX 4.0.5 which
- is SYS5. I haven't made any attempts at portability so if you have
- a change, send it to me. I would also appreciate suggestions.
-
- ################################ graph.diff #################################
- 67,71d66
- < #include <sys/types.h> /* PAUL: needed for file I/O */
- < #include <sys/stat.h>
- < #include <fcntl.h>
- < #include <unistd.h>
- <
- 92,102d86
- < #define XDATA 0 /* PAUL: file read data type*/
- < #define YDATA 1
- < #define XYDATA 2
- < #define HIST 3
- <
- < #define D_SHORT 0 /* PAUL: file read point C-type*/
- < #define D_LONG 1
- < #define D_FLOAT 2
- < #define D_DOUBLE 3
- <
- <
- 214,216d197
- < /* PAUL: procedure to read data from file into widget*/
- < static int FileVectorParseProc _ANSI_ARGS_((ClientData clientData,
- < Tcl_Interp *interp, Tk_Window tkwin, char *value, char *widgRec, int offset));
- 218d198
- <
- 309,314d288
- < /* PAUL: */
- < static Tk_CustomOption FileVectorOption =
- < {
- < FileVectorParseProc, TwinVectorPrintProc, NULL
- < };
- <
- 370,372d343
- < /* PAUL: */
- < {TK_CONFIG_CUSTOM, "-bfile", "bFile", (char *)NULL,
- < NULL, 0, XYGRAPH_MASK, &FileVectorOption},
- 537,539d507
- < GC compgc; /* PAUL: complement gc for crosshair */
- < int chx, chy; /* PAUL: old crosshair coordinates */
- < GC boxgc; /* PAUL: complement gc for box */
- 805,916d772
- < * Additional routines written by Paul Raines
- < * ---------------------------------------------------------------------- */
- < /* PAUL -----------------------------------------------------------------
- < * move crosshair cursor
- < */
- < static int
- < MoveCrossHair(interp, graphPtr, screenX, screenY)
- < Tcl_Interp *interp; /* Interpreter */
- < Graph *graphPtr; /* Graph widget record */
- < char *screenX; /* String representing screen x coordinate */
- < char *screenY; /* String representing Screen y coordinate */
- < {
- < Tk_Window tkwin = graphPtr->tkwin;
- < Drawable draw;
- < int sx, sy; /* Convert integer screen coordinates */
- <
- < if ((tkwin == NULL) || !Tk_IsMapped(tkwin))
- < return;
- <
- < /* Reset width/height */
- < graphPtr->width = Tk_Width(graphPtr->tkwin);
- < graphPtr->height = Tk_Height(graphPtr->tkwin);
- < draw = (Drawable) Tk_WindowId(tkwin);
- <
- < /* Get screen coords from string arguments and check */
- < if (Tcl_GetInt(interp, screenX, &sx) != TCL_OK ||
- < Tcl_GetInt(interp, screenY, &sy) != TCL_OK) {
- < return TCL_ERROR;
- < }
- < if (sx < 0 || sx > graphPtr->width ||
- < sy < 0 || sy > graphPtr->height) {
- < sx = sy = -10;
- < }
- <
- < /*
- < * remove old cross hairs (complement)....
- < */
- < if (graphPtr->chx != -10) {
- < XDrawLine(Tk_Display(tkwin),draw,graphPtr->compgc,
- < graphPtr->chx,0,graphPtr->chx,graphPtr->height);
- < XDrawLine(Tk_Display(tkwin),draw,graphPtr->compgc,
- < 0,graphPtr->chy,graphPtr->width,graphPtr->chy);
- < }
- < /*
- < * get new position of mouse pointer and save it in global variables ....
- < */
- < graphPtr->chx = sx;
- < graphPtr->chy = sy;
- < /*
- < * draw new cross hairs (complement)....
- < */
- < if (graphPtr->chx != -10) {
- < XDrawLine(Tk_Display(tkwin),draw,graphPtr->compgc,
- < graphPtr->chx,0,graphPtr->chx,graphPtr->height);
- < XDrawLine(Tk_Display(tkwin),draw,graphPtr->compgc,
- < 0,graphPtr->chy,graphPtr->width,graphPtr->chy);
- < }
- < return TCL_OK;
- < }
- <
- < /* PAUL -----------------------------------------------------------------
- < * draw ghost box
- < */
- < static int
- < DrawGhostBox(interp, graphPtr, screenX1, screenY1, screenX2, screenY2)
- < Tcl_Interp *interp; /* Interpreter to report results back to */
- < Graph *graphPtr; /* Graph widget record */
- < char *screenX1; /* String representing screen x coordinate */
- < char *screenY1; /* String representing Screen y coordinate */
- < char *screenX2; /* String representing screen x coordinate */
- < char *screenY2; /* String representing Screen y coordinate */
- < {
- < Tk_Window tkwin = graphPtr->tkwin;
- < Drawable draw;
- < int sx1, sy1, sx2, sy2; /* Convert integer screen coordinates */
- <
- < if ((tkwin == NULL) || !Tk_IsMapped(tkwin))
- < return;
- <
- < /* Reset width/height */
- < graphPtr->width = Tk_Width(graphPtr->tkwin);
- < graphPtr->height = Tk_Height(graphPtr->tkwin);
- < draw = (Drawable) Tk_WindowId(tkwin);
- <
- < if (Tcl_GetInt(interp, screenX1, &sx1) != TCL_OK ||
- < Tcl_GetInt(interp, screenY1, &sy1) != TCL_OK ||
- < Tcl_GetInt(interp, screenX2, &sx2) != TCL_OK ||
- < Tcl_GetInt(interp, screenY2, &sy2) != TCL_OK) {
- < return TCL_ERROR;
- < }
- <
- < /* don't draw outside window */
- < if (sx1 < 0) sx1 = 0;
- < else if (sx1 > graphPtr->width) sx1 = graphPtr->width;
- < if (sy1 < 0) sy1 = 0;
- < else if (sy1 > graphPtr->height) sy1 = graphPtr->height;
- < if (sx2 < 0) sx2 = 0;
- < else if (sx2 > graphPtr->width) sx2 = graphPtr->width;
- < if (sy2 < 0) sy2 = 0;
- < else if (sy2 > graphPtr->height) sy2 = graphPtr->height;
- <
- < /*
- < * draw box (complement)....
- < */
- < XDrawRectangle(Tk_Display(tkwin),draw,graphPtr->boxgc,
- < MIN(sx1, sx2), MIN(sy1, sy2),
- < (unsigned int) abs(sx2-sx1),(unsigned int) abs(sy2-sy1));
- <
- < return TCL_OK;
- < }
- <
- < /* ----------------------------------------------------------------------
- 1769,1781d1624
- < * PAUL-----------------------------------------------------------------
- < *
- < * FileVectorParseProc --
- < *
- < * This procedure is like VectorParseProc except that it
- < * interprets the list as a filename with type and data storage
- < * info. The minimum and maximum for both the X and Y vectors are
- < * determined if present.
- < *
- < * Results:
- < * The return value is a standard Tcl result. The vectors are passed
- < * back via the widget record (linePtr).
- < *
- 1783,2108d1625
- < */
- < static int
- < FileVectorParseProc(clientData, interp, tkwin, value, widgRec, offset)
- < ClientData clientData; /* not used */
- < Tcl_Interp *interp; /* Interpreter to send results back to */
- < Tk_Window tkwin; /* not used */
- < char *value; /* Tcl list of expressions */
- < char *widgRec; /* Line information record */
- < int offset; /* not used */
- < {
- < register int i;
- < register double *valuePtr;
- < register char *fvalPtr; /* used for accessing file buffer */
- < Line *linePtr = (Line *) widgRec;
- < int numExpr;
- < char **exprArr = NULL;
- < double *xValueArr = NULL, *yValueArr = NULL;
- < double min, max;
- < int firstMin, firstMax;
- < int arraySize;
- <
- < int d_fid = 0; /* file handle */
- < char d_type; /* type of data: hist, xdata, ydata, xydata */
- < long d_offset; /* byte offset from start of file to data */
- < long d_numpts; /* number of points to be read */
- < int d_bufsize; /* buffer size in bytes to read from file */
- < char d_ptsize; /* C-type for point: short,long,float,double */
- < char d_ptrstep = 1; /* number of bytes for stepping through buffer */
- < double d_xstart, d_xstep; /* for hist, how x values chosen */
- < int length; /* length of string */
- < char *fValueArr = NULL; /* pointer to start of file buffer */
- <
- < /* Split the bfile list and check the values */
- < if (Tcl_SplitList(interp, value, &numExpr, &exprArr) != TCL_OK) {
- < return TCL_ERROR;
- < }
- < /* need either 5 or 7 (for hist) arguments */
- < if (numExpr < 5) {
- < interp->result = "Bad bfile list. Need { filename type offset numpts \
- < ptsize ?xstart? ?xstep? }";
- < goto error;
- < } else if (numExpr > 7) {
- < interp->result = "Bad bfile list. Need { filename type offset numpts \
- < ptsize ?xstart? ?xstep? }";
- < goto error;
- < }
- <
- < /* get the byte offset and number of points */
- < if (Tcl_ExprLong(interp, exprArr[2], &d_offset) == TCL_ERROR ||
- < d_offset < 0 ) {
- < interp->result = "Bad byte offset in bfile list";
- < goto error;
- < }
- < if (Tcl_ExprLong(interp, exprArr[3], &d_numpts) == TCL_ERROR ||
- < d_numpts < 1) {
- < interp->result = "Bad point number in bfile list";
- < goto error;
- < }
- < d_bufsize = (int) d_numpts; /* file buffer size set to number points */
- <
- < /* get type of data */
- < length = strlen(exprArr[1]);
- < if ((strncmp(exprArr[1], "xdata", length) == 0) &&
- < (numExpr == 5)) d_type = XDATA;
- < else if ((strncmp(exprArr[1], "ydata", length) == 0) &&
- < (numExpr == 5)) d_type = YDATA;
- < else if ((strncmp(exprArr[1], "xydata", length) == 0) &&
- < (numExpr == 5)) {
- < d_type = XYDATA;
- < d_bufsize *= 2; /* need to read in double number of points */
- < d_ptrstep = 2; /* need to skip over x's to get y's, vice versa */
- < }
- < else if ((strncmp(exprArr[1], "hist", length) == 0) &&
- < (numExpr == 7)) d_type = HIST;
- < else {
- < interp->result = "Bad data type in bfile list or wrong number \
- < of arguments for specified type";
- < goto error;
- < }
- <
- < /* get x-value start and step if hist type */
- < if (d_type == HIST) {
- < if (Tcl_ExprDouble(interp, exprArr[5], &d_xstart) == TCL_ERROR) {
- < interp->result = "Bad xstart in bfile list";
- < goto error;
- < }
- < if (Tcl_ExprDouble(interp, exprArr[6], &d_xstep) == TCL_ERROR ||
- < d_xstep == 0.0) {
- < interp->result = "Bad xstep in bfile list";
- < goto error;
- < }
- < /* need to store each point twice for histogram stepping */
- < arraySize = (int) d_numpts * 2;
- < } else
- < arraySize = (int) d_numpts;
- <
- < /* get C-type of points to be read and set pointer stepping, buffer */
- < length = strlen(exprArr[4]);
- <
- < if (strncmp(exprArr[4], "short", length) == 0) {
- < d_ptsize = D_SHORT;
- < d_ptrstep *= sizeof(short);
- < d_bufsize *= sizeof(short);
- < }
- < else if (strncmp(exprArr[4], "long", length) == 0) {
- < d_ptsize = D_LONG;
- < d_ptrstep *= sizeof(long);
- < d_bufsize *= sizeof(long);
- < }
- < else if (strncmp(exprArr[4], "float", length) == 0) {
- < d_ptsize = D_FLOAT;
- < d_ptrstep *= sizeof(float);
- < d_bufsize *= sizeof(float);
- < }
- < else if (strncmp(exprArr[4], "double", length) == 0) {
- < d_ptsize = D_DOUBLE;
- < d_ptrstep *= sizeof(double);
- < d_bufsize *= sizeof(double);
- < }
- < else {
- < interp->result = "Bad data point size in bfile list";
- < goto error;
- < }
- <
- < /* Allocate an array of char to hold the values from file */
- < fValueArr = (char *)ckalloc(d_bufsize);
- < if (fValueArr == NULL) {
- < Tcl_AppendResult(interp, "Can't allocate bfile buffer for ",
- < linePtr->name, (char *)NULL);
- < Tcl_SetErrorCode(interp, "UNIX", "malloc", sys_errlist[errno], NULL);
- < goto error;
- < }
- <
- < /* Open file for reading */
- < if ((d_fid = open(exprArr[0], O_RDONLY)) == -1) {
- < perror(interp->result) ;
- < interp->result = "Error opening in -bfile";
- < goto error;
- < }
- < /* Read past header to data */
- < if((length = read(d_fid, fValueArr, (unsigned) d_offset)) == -1) {
- < perror(interp->result);
- < interp->result = "Error reading in -bfile";
- < goto error;
- < }
- < /* Check if at end of file */
- < if ( length < (int) d_offset) {
- < interp->result = "Offset past end of file in -bfile";
- < goto error;
- < }
- < /* Read data */
- < if((length = read(d_fid, fValueArr, (unsigned) d_bufsize)) == -1) {
- < perror(interp->result);
- < interp->result = "Error reading data of -bfile";
- < goto error;
- < }
- < /* Check if past end of file */
- < if ( length < d_bufsize) {
- < interp->result = "Read past end of file for data in -bfile";
- < goto error;
- < }
- < close(d_fid);
- <
- < /* get the x values from the file */
- < if (d_type != YDATA && d_type != HIST) {
- < /* Allocate an array of doubles to hold the values */
- < xValueArr = (double *)ckalloc(arraySize * sizeof(double));
- <
- < if (xValueArr == NULL) {
- < Tcl_AppendResult(interp, "Can't allocate X vector for ",
- < linePtr->name, (char *)NULL);
- < Tcl_SetErrorCode(interp, "UNIX", "malloc", sys_errlist[errno], NULL);
- < goto error;
- < }
- < if (d_type != HIST) {
- <
- < /* translate file values to doubles and store in graph record */
- < firstMin = firstMax = TRUE;
- < min = max = 0.0;
- < fvalPtr = fValueArr;
- < for (valuePtr = xValueArr, i = 0; i < d_numpts; i++, valuePtr++) {
- <
- < /* convert to double */
- < switch(d_ptsize) {
- < case D_SHORT:
- < *valuePtr = (double) ( *( (short *)fvalPtr ) );
- < break;
- < case D_LONG:
- < *valuePtr = (double) ( *( (long *)fvalPtr ) );
- < break;
- < case D_FLOAT:
- < *valuePtr = (double) ( *( (float *)fvalPtr ) );
- < break;
- < case D_DOUBLE:
- < /* don't real have to do this, but ... */
- < *valuePtr = *( (double *)fvalPtr );
- < break;
- < default:
- < interp->result = "SERIOUS error: ptsize lost in -bfile";
- < goto error;
- < }
- < fvalPtr += d_ptrstep; /* go to next x value */
- <
- < if (*valuePtr != NegativeInfinity && *valuePtr != PositiveInfinity) {
- < if (firstMin) {
- < min = *valuePtr;
- < firstMin = FALSE;
- < } else if (*valuePtr < min) {
- < min = *valuePtr;
- < }
- < if (firstMax) {
- < max = *valuePtr;
- < firstMax = FALSE;
- < } else if (*valuePtr > max) {
- < max = *valuePtr;
- < }
- < }
- < }
- < }
- < /* else if d_type == HIST */
- < else {
- < /* create x-values from xstart and xstep */
- < valuePtr = xValueArr;
- < for (i = 0; i < d_numpts; i++) {
- < *valuePtr = d_xstart + i * d_xstep;
- < valuePtr++;
- < *valuePtr = d_xstart + (i+1) * d_xstep;
- < valuePtr++;
- < }
- < min = d_xstart;
- < max = d_xstart + (i-1) * d_xstep;
- < }
- <
- < /* Save array and limits */
- < linePtr->x.minValue = min;
- < linePtr->x.maxValue = max;
- < linePtr->x.numValues = arraySize;
- < if (linePtr->x.valueArr != NULL)
- < free((char *)linePtr->x.valueArr);
- < linePtr->x.valueArr = xValueArr;
- < }
- <
- < /* get the y values from the file */
- < if (d_type != XDATA) {
- < yValueArr = (double *)ckalloc(arraySize * sizeof(double));
- <
- < if (yValueArr == NULL) {
- < Tcl_AppendResult(interp, "Can't allocate Y vector for ",
- < linePtr->name, (char *)NULL);
- < Tcl_SetErrorCode(interp, "UNIX", "malloc", sys_errlist[errno], NULL);
- < goto error;
- < }
- <
- < /* Now translate the Y values to doubles and store */
- < firstMin = firstMax = TRUE;
- < min = max = 0.0;
- < fvalPtr = fValueArr;
- < if (d_type == XYDATA) fvalPtr += (d_ptrstep/2); /* skip past first x value */
- < for (valuePtr = yValueArr, i = 0; i < d_numpts; i++, valuePtr++) {
- <
- <
- < if (d_ptsize == D_SHORT) {
- < *valuePtr = (double) ( *( (short *)fvalPtr ) );
- < } else if (d_ptsize == D_LONG) {
- < *valuePtr = (double) ( *( (long *)fvalPtr ) );
- < } else if (d_ptsize == D_FLOAT) {
- < *valuePtr = (double) ( *( (float *)fvalPtr ) );
- < } else if (d_ptsize == D_DOUBLE) {
- < *valuePtr = *( (double *)fvalPtr );
- < } else {
- < interp->result = "SERIOUS error: ptsize lost";
- < goto error;
- < }
- < fvalPtr += d_ptrstep;
- < if (d_type == HIST) { /* need to double points for histogram */
- < d_xstep = *valuePtr;
- < valuePtr++;
- < *valuePtr = d_xstep;
- < }
- <
- < if (*valuePtr != NegativeInfinity && *valuePtr != PositiveInfinity) {
- < if (firstMin) {
- < min = *valuePtr;
- < firstMin = FALSE;
- < } else if (*valuePtr < min) {
- < min = *valuePtr;
- < }
- < if (firstMax) {
- < max = *valuePtr;
- < firstMax = FALSE;
- < } else if (*valuePtr > max) {
- < max = *valuePtr;
- < }
- < }
- < }
- <
- < /* Save array and limits */
- < linePtr->y.minValue = min;
- < linePtr->y.maxValue = max;
- < linePtr->y.numValues = arraySize;
- < if (linePtr->y.valueArr != NULL)
- < free((char *)linePtr->y.valueArr);
- < linePtr->y.valueArr = yValueArr;
- < }
- <
- <
- < interp->result = "";
- < ckfree((char *)exprArr);
- < ckfree((char *)fValueArr);
- < return TCL_OK;
- < error:
- < /* Clean up, release allocated storage */
- < if (exprArr)
- < ckfree((char *)exprArr);
- < if (xValueArr)
- < ckfree((char *)xValueArr);
- < if (yValueArr)
- < ckfree((char *)yValueArr);
- < if (fValueArr)
- < ckfree((char *)fValueArr);
- < if (d_fid != 0) close(d_fid);
- < return TCL_ERROR;
- < }
- <
- < /*
- < *----------------------------------------------------------------------
- 2893,2894c2410
- < graphPtr->chx = -10; /* PAUL: signal that crosshair cursor */
- < } /* has been erased from screen */
- ---
- > }
- 4127,4132c3643
- <
- < /* need to keep track of last y position and will calculate slope */
- < double lastx, lasty, slope, sx, sy;
- < /* need to no if last point was out of bounds */
- < char outbounds;
- <
- ---
- > double lastx;
- 4158,4159d3668
- < lasty = 0.0;
- < outbounds = FALSE;
- 4168,4199c3677,3679
- < if (y < 0.0 || y > 1.0) {
- < /* Point is out-of-bounds, check if in line mode */
- < if (LINESTYLE(linePtr->symbol)) {
- < /* In line mode, check if already out of bounds */
- < if (!(n == 0 || outbounds)) {
- < /* not already out of bounds, draw to edge */
- < slope = (y - lasty) / (x - lastx) ;
- < if ( y < 0.0 ) sy = 0.0;
- < else sy = 1.0;
- < sx = (sy - lasty)/slope + lastx ;
- < ptArr[numPoints++] = Gr_Point(graphPtr, sx, sy);
- < XDrawLines(Tk_Display(tkwin), draw, linePtr->gc,
- < ptArr, numPoints, CoordModeOrigin);
- < numPoints = 0;
- < }
- < outbounds = TRUE;
- < lastx = x;
- < lasty = y;
- < continue;
- < } else
- < /* not in line mode so skip it */
- < continue;
- < } else if (outbounds && (LINESTYLE(linePtr->symbol)) ) {
- < /* Point isn't out of bounds, but last one was */
- < slope = (y - lasty) / (x - lastx) ;
- < if ( lasty < 0.0 ) lasty = 0.0;
- < else lasty = 1.0;
- < lastx = x - (y - lasty)/slope ;
- < ptArr[numPoints++] = Gr_Point(graphPtr, lastx, lasty);
- < outbounds = FALSE;
- < }
- <
- ---
- > if (y < 0.0 || y > 1.0)
- > continue;
- >
- 4209d3688
- < lasty = y;
- 5073,5076d4551
- < /* PAUL: needed for clipping fix*/
- < double slope, sx, sy;
- < char outbounds;
- <
- 5089c4564
- < double lastx, lasty; /* PAUL: need lasty also for clipping fix */
- ---
- > double lastx;
- 5095,5096d4569
- < lasty = 0.0; /* PAUL: */
- < outbounds = FALSE;
- 5113,5147c4586,4587
- < if (y < 0.0 || y > 1.0) {
- < /* PAUL: Point is out-of-bounds, check if in line mode */
- < if (LINESTYLE(linePtr->symbol)) {
- < /* In line mode, check if already out of bounds */
- < if (!(n == 0 || outbounds)) {
- < /* not already out of bounds, draw to edge */
- < slope = (y - lasty) / (x - lastx) ;
- < if ( y < 0.0 ) sy = 0.0;
- < else sy = 1.0;
- < sx = (sy - lasty)/slope + lastx ;
- < x1 = GX(graphPtr, sx), y1 = GY(graphPtr, sy);
- < fprintf(f, "%d %d lineto\n", x1, y1);
- < fprintf(f, "stroke\n%d %d moveto\n", x1, y1);
- < numPoints = 0;
- < }
- < outbounds = TRUE;
- < lastx = x;
- < lasty = y;
- < continue;
- < } else
- < /* not in line mode so skip it */
- < continue;
- < } else if (outbounds && (LINESTYLE(linePtr->symbol)) ) {
- < /* Point isn't out of bounds, but last one was */
- < slope = (y - lasty) / (x - lastx) ;
- < if ( lasty < 0.0 ) lasty = 0.0;
- < else lasty = 1.0;
- < lastx = x - (y - lasty)/slope ;
- < x1 = GX(graphPtr, lastx), y1 = GY(graphPtr, lasty);
- < fprintf(f, "%d %d moveto\n", x1, y1);
- < fprintf(f, "%d %d lineto\n", x1, y1);
- < numPoints++;
- < outbounds = FALSE;
- < }
- <
- ---
- > if (y < 0.0 || y > 1.0)
- > continue;
- 5161d4600
- < lasty = y;
- 5880d5318
- < unsigned char dotted[2];
- 5933,5959d5370
- < /* PAUL: Create graph crosshair GC */
- < gcValues.function = GXinvert;
- < gcValues.line_width = 1;
- < gcValues.line_style = LineSolid;
- < gcValues.cap_style = CapButt;
- < gcValues.join_style = JoinMiter;
- < valueMask = (GCFunction | GCLineWidth | GCLineStyle);
- < newGC = Tk_GetGC(graphPtr->tkwin, valueMask, &gcValues);
- < if (graphPtr->compgc != None)
- < Tk_FreeGC(graphPtr->compgc);
- < graphPtr->compgc = newGC;
- < graphPtr->chx = graphPtr->chy = -10;
- <
- < /* PAUL: Create zoom box GC */
- < dotted[0] = dotted[1] = 2;
- < gcValues.function = GXinvert;
- < gcValues.line_width = 1;
- < gcValues.line_style = LineOnOffDash;
- < gcValues.cap_style = CapButt;
- < gcValues.join_style = JoinMiter;
- < valueMask = (GCFunction | GCLineStyle | GCLineWidth);
- < newGC = Tk_GetGC(graphPtr->tkwin, valueMask, &gcValues);
- < XSetDashes(Tk_Display(graphPtr->tkwin), newGC, 0, dotted, 2);
- < if (graphPtr->boxgc != None)
- < Tk_FreeGC(graphPtr->boxgc);
- < graphPtr->boxgc = newGC;
- <
- 6199,6216d5609
- < } else if ((c == 'c') && (strncmp(argv[1], "crosshair", length) == 0)) {
- < if (argc == 3 && (strncmp(argv[2], "off", length) == 0)) {
- < result = MoveCrossHair(interp, graphPtr, "-10", "-10");
- < } else if (argc == 4) {
- < result = MoveCrossHair(interp, graphPtr, argv[2], argv[3]);
- < } else {
- < Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- < " crosshair x y\"", NULL);
- < goto error;
- < }
- < } else if ((c == 'g') && (strncmp(argv[1], "ghostbox", length) == 0)) {
- < if (argc != 6) {
- < Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- < " ghostbox x1 y1 x2 y2\"", NULL);
- < goto error;
- < }
- < result = DrawGhostBox(interp, graphPtr, argv[2], argv[3],
- < argv[4], argv[5]);
- 6220,6221c5613
- < insert, limits, locate, newtag, postscript, show, crosshair, ghostbox, \
- < tagconfigure, or untag ",
- ---
- > insert, limits, locate, newtag, postscript, show, tagconfigure, or untag ",
- 6326d5717
- <
-
- ############################## test.tk ################################
- #!./pish -f
- option add *XYGraph.Geometry 700x400
-
- ######################################################################
- # zoom utilities
- ######################################################################
- global zx; global zy
- global oldx; global oldy
- proc zoomstart { w sx sy } {
- global zx; global zy
- global oldx; global oldy
-
- $w crosshair off
- set oldx $sx
- set oldy $sy
- set zx $sx
- set zy $sy
- $w ghostbox $zx $zy $oldx $oldy
-
- }
- proc zoomchange { w sx sy } {
- global zx; global zy
- global oldx; global oldy
-
- $w ghostbox $zx $zy $oldx $oldy
- $w ghostbox $zx $zy $sx $sy
- set oldx $sx
- set oldy $sy
- }
- proc zoomstop { w sx sy} {
- global zx; global zy
- global oldx; global oldy
- $w ghostbox $zx $zy $oldx $oldy
- scan [$w locate $sx $sy ] "%s %s" oldx oldy
- scan [$w locate $zx $zy ] "%s %s" zx zy
- scan [$w limits ] "%s %s %s %s" xmin xmax ymin ymax
- if { $zx < $oldx } { swap zx oldx }
- if { $zy < $oldy } { swap zy oldy }
- if { $zx > $xmax } { set zx $xmax }
- if { $oldx < $xmin } { set oldx $xmin }
- if { $zy > $ymax } { set zy $ymax }
- if { $oldy < $ymin } { set oldy $ymin }
- $w configure -xmin $oldx -xmax $zx -ymin $oldy -ymax $zy
- }
- proc swap { var1 var2 } {
- global $var1 $var2
- set hold [set $var1]
- set $var1 [set $var2]
- set $var2 $hold
- }
-
- frame .top
- xygraph .top.graph -title "Another XY Graph" \
- -xlabel "X Axis Label" -ylabel "Y Axis Label" \
- -showlegend false
- .top.graph insert line1 -bfile {test.spe hist 36 2000 short 0 1} -color blue
-
- label .top.info -anchor w -width 10 -relief raised -background bisque3
- .top.info configure -text "BUTTON: (1) Zoom (2) See all (3) Quit"
-
- pack append .top .top.info {bottom fillx} .top.graph {top fill}
- pack append . .top {top fill}
- .top.graph configure -xmin 100 -xmax 500
- .top.graph configure -ymin 0 -ymax 1000
-
- bind .top.graph <Leave> { %W crosshair -10 -10 }
- bind .top.graph <Motion> { %W crosshair %x %y }
-
- bind .top.graph <ButtonPress-2> {
- %W config -xmin {} -ymin {} -xmax {} -ymax {}
- }
-
- bind .top.graph <ButtonPress-3> {exit}
-
- bind .top.graph <ButtonPress-1> {zoomstart %W %x %y}
- bind .top.graph <B1-Motion> {zoomchange %W %x %y}
- bind .top.graph <ButtonRelease-1> {zoomstop %W %x %y}
-
- ########################### test.spe.uu ###############################
- begin 644 test.spe
- M````&$=-050@,2XP,"``````````````````````````````````````````
- M``````````````````````````````````````````````````````$````%
- M``$``0````(`!0`,``D`!@`'``@`"P`*`!,`"P`%``\`&``0`!0`&@`5`!0`
- M#P`2`!<`"@`@`!(`%0`0`!,`#0`>``H`%0`2`"(`%P`0`!``)@`4`!L`$P`2
- M``T`'0`*`#,`+0`L`"L`&P`.`!0`&0`<`!4`(0`;`!X`+0`C`"L`,P`2`"(`
- M*P`0`"0`00!8`&D`+@`A`"0`(@`T`"$`*0`D`"$`)``R`"D`-P`S`#P`*0`J
- M`"\`-0`L`"D`)P`N`#@`00!J`(T`5@!"`!L`)P!#`#H`0@`U`"\`+@`O`"4`
- M10`]`#4`*P`^`#X`.P!$`#P`-``]`$<`,`!2`$L`J0'#`I(`W@!H`$(`-P!#
- M`#@`20!(`#P`-@!+`$H`.0!)`"P`.P!7`&D`9`!@`%(`0@!)`%\`2P`Z`#4`
- M0P!2`$8`.@`V`#X`20!\`(\`:0"C`)X`=@!(`$X`0@!.`#\`0`!&`$``80!>
- M`#D`0@`]`$@`40`^`$H`/@!(`%L`.`!*`%(`10!+`%H`70!,`#``5@!E`$(`
- M0P!H`&,`:0!M`&``90!R`&D`C@%:`T@#<`%L`((`=`"W`-<`S0&%`ND"\P%4
- M`&4`/P!-`$$`.0!$`"T`9P`\`&$`60!^`%H`:@`K`#\`4``]`$D`,@![`-T`
- M_P"L`&$`5`!#`$H`4``Y`$P`1@`X`$4`/P!``$@`50!4`%<`6P!6`&``80"0
- M`1<!U`)K`8,`A0!P`&X`:P!,`$L`2``W`$@`-P`S`%,`5``\`#P`6@`X`%,`
- MD`!Y`&\`7@!'`$0`.``U`%@`+P!"`$8`3`!7`.\"#0)>`6L`@@!!`%T`6@!7
- M`#P`,P!``$``=0!N`#T`.P!7`%L`.P`V`$0`<@!A`$4`4`!$`$<`-@`_`%$`
- M/0`Y`$<`4@!1`"P`,P`Y`#``)``P`#T`.P!;`&(`90!+`$@`2@`\`$$`1P!_
- M`(T`>0""`%8`3@"I`/4!1`#8`'``/@!!`#\`-P!#`$P`5`!1`'4`MP#9`.(`
- MA0!2`#D`+@!&`$(`7`#3`6`!;0#>`'``.0`[`#L`,@!!`$H`,P!7`%0`40!5
- M`'D`Z0%/`04`A@!(`#8`-@!+`$\`90!1`$(`5@!3`$``1P!5`&$`@`!:`#T`
- M20`X`$(`(``J`"X`.0`V`%,`3`!7`$$`+0!"`$X`1@!%`#4`2@!.`%(`0@`C
- M`%``6`!``#8`3@`_`#4`*@`N`"@`-@`E`"<`1``R`"D`(``Q`"L`,P!%`$``
- M/@`H`#T`*0`F`$$`-`!#`#X`9P!7`+$`I`"_`*<`Q0"<`&H`40!``#8`-``6
- M`#,`0``O`%0`-0!E`'@`B0!M`$T`-0`I`#L`/P`Z`"4`.``L`"L`,``J`#D`
- M+0!#`#P`0`!2`#\`,``K`"P`+P`O`"H`'@`;`!@`(@`P`#8`(P!$`%(`6`!R
- M`%@`4P!O`)H`DP""`%4`,P!!`#T`*P`L`$D`0@`S`#L`-0`_`!X`,`!2`#\`
- M0@`M`#H`00`Z`"$`,`!!`$``3P`\`$P`2@!/`%@`9`!9`$H`,``W`$@`+0!!
- M`#8`1P!V`,X`RP"(`%4`0``Y`"\`)P`K`"4`*``S`#,`10`[`#``,P`K`"@`
- M,P`B`"4`(0`^`"T`7`!%`$,`,@`P`#@`,P`8`!<`)P`?`"``,``F`"$`(``;
- M`"D`)0`G`!@`&``:`!T`.0`[`"$`.P!-`%$`40`P`#@`4`!7`"T`,0`F`"\`
- M+0`M`"P`+@`T`"L`*@`?`"@`$@`N`"X`+@`J`"D`(0`E`"(`)@`2`"L`%@`7
- M`"``(``B`"P`'``;`"@`)``@``T`&P`>`"D`)0`2`!8`+@`<`"4`+P`X`#,`
- M,P!&`$4`1``Z`"<`)@`@`"4`'P`>`"P`(P`?`"4`(``M`"0`,P`K`"@`+``K
- M`"P`-P`H`"T`*P!;`%``.``F`"0`+P`6`"0`&P`6`#T`-@!#`$@`+P`S`!$`
- M(@`B`"P`)P`Q`#<`&0`W`!X`(@`9`"``$0`M`!4`&P`;`!0`'``B`!,`$@`E
- M`",`&0`I`"@`8@#"`-4`MP"5`%4`30`N`!T`&0`?`"D`$P`L`!$`'P`7`!P`
- M*``>`"L`+@`C`"``)P`4`"$`(P`;`!P`(``7`!@`%@`?`"4`'``>`",`&``?
- M`",`-P`7`#``'@`H`!L`)``E`!H`+@`H`#4`*@`G`#(`,0`5`!``(0`1`"$`
- M(0`I`$P`;0#*`.4`R0"V`$X`/P`P`"<`%``5`"<`%@`-`!0`%``<`!(`%P`A
- M``T`"``6``(`"P`2`!@`'@`F`!<`#@`?`!@`"P`@`!$`%``=`!4`(``-`!T`
- M$0`<`!(`%@`3`!P`'@`M`",`-``Y`$@`+0`E`"0`(P`>`"T`&P`8`!<`$@`0
- M`!X`%``3`!<`$@`E`"(`$``@``L`&P`:`!4`"P`;`!4`+``Z`$<`:0![`(``
- M70`V`"L`(``8`!``$``6`!@`%``I`"P`.0!M`(L`E`!J`%(`.0`1`!X`&``<
- M``@`"@`/`!8`&0`.`"0`%0`A`!<`(``J`!4`'@`6`!0`$0`0`!(`'@`9`!0`
- M#P`5``P`&P`.`!8`$``2`!\`&``C`"``%``:``H`#@`8`"P`+``D`!L`&``>
- M`!<`%0`3``\`%``.``D``@`5`!0`%@`-`!``"@`'``X`$@`6`!H`%``'``\`
- M'P`<`!4`%P`4`!@`&@`B`!(`%0`7``X`"@`(`!(`#P`0`!<`&0`9``\`#``@
- M`!T`$``,`!T`(@`/`!X`'P`4``@`#@`9``D`%P`7`!T`%P`9`!T`'``A`"D`
- M+0`F`!L`$P`4`!\`$P`-``T`#``2``L`&P`2`!0`%@`3`!``#0`*``X`"@`+
- M``P`#@`4`!4`$0`8`!8`%P`5``T`$@`4`!0`#@`0``T`!``1``\`$P`(`!,`
- M%@`(``8`$P`!``H`!``&``0`"@`'``0`#P`1``@`%``2`!8`#P`%``T`%``1
- M`!,`%P`%`!$`!``!`!(`#0`.`!4`$P`6`!0`"0`0`!4`$0`,``X`$``#``T`
- M%@`0`!(`"P`5`!$`#P`:`"$`$P`3``\`#``4``L`#@`/`!$``@`*`!$`$``0
- M`!$`$P`)`!<`$``0`!,`&``,``D`%``/````#@`/`!(`%``*``@`#``(``H`
- M#P`+``@`!0`'``<`#0`*``8`#0`,`!<`$0`2``P`"0`&``T`"``'``\`"P`9
- M``\`&0`)``\`!@`=`!0`#``/``0`#P`1``0`#0`,`!$`$@`*``D`"``5``8`
- M"@`*``D``P`-``H`#P`8`!<`(0`+`!@`%0`+``L`!P`,``L`$@`(`!D`#P`4
- M``P`&0`:`!``#0`-``T`"P`&`!,``P`0``T`#P`*``P`"``.``T`%``-``(`
- M#@`*`!0`%``(`!0`#``4`!@`$@`!``T`#0`(`!,`"0`+`!$`"``2``P`"P`2
- M``T`$``)``@`%P`)`!``$@`)`!``"@`'``T`"0`)``H`#0`,``8`#0`.``\`
- M'0`/``@`#P`0`!,`$0`*``H`#P`'``@`#@`$`!``#@`!``D`!@`,``D`!@`/
- M`!0`#`````4`&``)`!$`$P`)``4`"0`+``<`"``%``P`"0`)``L`!@`$``<`
- M%0`$`!0`"``&``$``@`,``8`"P`:``T`&@`3``P`%``0``D`!P`*`!``"0`#
- M``D`"``/``<`!``.``X`%P`'``L`$``)``@`"``"``L`"@````D`%@`(``4`
- M!``+``P`!0`(`!```P`%``P`"0`,``D`"0`%``L`"P`-``@`"0`)``8`#``$
- M``H`!@`,``@`!``*``@`!@`*``,`!0`(``T`#0`(``P````)``D`#0`!`!$`
- M$0`&``D`#0`+``P``@`'``@`!0`(``(``0````<`!``'``H`!0````4````#
- M``\`"``"``H`#0`%``L`"``'``8`!@`#``0`!``)__T``@`&``8`#0`-``<`
- M"``.``8`"P`)``(````,``H`"0`(``,`#0`0``P`"0`4`!<`'P`,`!8`'P`*
- M``D``@`#``H`!P`#``0`!0`'``4`!0`&``4``P`,``<`!0`8`!$`%``C`",`
- M)0`D`"(`&P`.`!D``P`*``0`!@`+``4`$0`'``@`$0`,``4`!P`&``@`!@`'
- M``$`"0`)``,``0`#``4``@`,``L````)``D`"``"`````@`"``$`!``'``8`
- M`P`%``4``P````@`!@`'``@`"0`&``4``P`'``@`!0`)``(``P`%``D`"``'
- M``<``@`'``$``0`&````!@`&``4`!P`#``4``@`&``@`!``"``<`!@`"``H`
- M`0`(``8`!0`$``+__P`#``4`!``!``(`"@`+``,``0`$``$``0`$``D`"``#
- M``8`!P`#``0``P`"``$`!0`#````"`````(``@`(``0`!@`$``$`!0`&``$`
- M!``$``8`"0`$``$`!@`(``<``P````(`"@````+__P`(``(`!``!```````&
- M``,`!P`&``(`!``#__X`!@`'``8``0`#``0`!``#``(``___````!``$``@`
- M!P`"``0`!P````4``@`%``$`!``"``$``@`+``<`!`````,````%``0`!@`&
- M``0``0`&``4`!`````$````#``<`!0`#``(`!``"``(``P``````!P`$``0`
- M`0`$````!P`$````!P`!``(`!P`$``,``0````$`!P`#``0``0`%``,`"/__
- M``(`!P`!``8`!``$``0``@`"`````0`#``$````!``$``@`$``@`!P`#``$`
- M`P`#``8``@`"``,`!0`%``4`!P`(``8````#``4``O_^``,`!0`#``$````"
- M``(`!``!``,`!@`!``(``0`#``(`!``'`````0`"`````@`"``,`!``#``0`
- M`0`"``#__P`!``(````!``(``P`#``,````%``,`"``#``<``0`"``,``P`!
- M``+__@`"``(````#``,````"````!``'``,`!``$``(`"/_^``(``0`#``,`
- M`0```````0`"``(`!O__``0`!0`#```````!``$``@`!``(``P`!`````0`!
- M``,````!``(``0`$``,````'``0```````$``@`$``8``0`!``$``@`#``0`
- C```%````!``"``(``0`"``0`!`````,````$``$`````#\@!
- `
- end
-
- ____________________________________________________________________
- Paul Raines raines@bohr.physics.upenn.edu 215-898-8832
- Dept. of Physics
- University of Pennsylvania
-