/* COPYRIGHT (c) 1995 Kapteyn Astronomical Institute University of Groningen, The Netherlands All Rights Reserved. #> plotsym.dc1 Program: PLOTSYM Purpose: Plot PGPLOT's marker- and Hershey symbols Category: PLOTTING, UTILITY File: plotsym.c Author: M.G.R. Vogelaar Keywords: GRDEVICE= Plot device: [LIST OF DEVICES] Destination of plot, Screen or Hardcopy. OPTION= 1=Plot markers, 2=Plot Hershey symbols: [1] 1: Plot one page with rows x columns graph markers starting with marker index -1. 2: Plot Hershey symbols in pages with rows x columns symbols. Boxes with undefined Hershey symbols are not displayed, so the symbol numbers are not consecutive. Page numbers are set with PAGENR=. ROWCOL= Give number of rows, columns to display: [CALCULATED] One page has rows x columns boxes with symbols. CHARHEI= Give char.height in mm for symbols,numbers: [CALCULATED] In the default situation, both symbol- and number heights are the same. ** PGWIDTH= Give line width 1..21: [1] Width for characters, symbols and lines. ** PGFONT= Give font 1..4: [2] 1: (default) a simple single-stroke font ("normal" font) 2: roman font 3: italic font 4: script font PAGENR= Give page number <= %d (0=exit): [NEXT PAGE] This keyword is used to browse through the plot pages for OPTION=2 (Hershey symbols). Description: A Graph Marker is a symbol, such as a cross, dot, or circle, drawn on a graph to mark a specific point. Usually the symbol used will be chosen to be symmetrical with a well-defined center. In most GIPSY applications a marker is identified by a number given with a keyword like SYMBOL=. The symbol number can be: -1, to draw a dot of the smallest possible size (one pixel); 0--31, to draw any one of the symbols in Figure obtained with OPTION=1 or 33--127, to draw the corresponding ASCII character (the character is taken from the currently selected text font); or >127, to draw one of the Hershey symbols in the plot obtained with OPTION=2. Text in plots can contain special symbols. The total number of different symbols available is about 1000. Each symbol is composed of a set of vectors, based on digitized type fonts devised by A. V. Hershey of the US Naval Postgraduate School, and each symbol is assigned a number in the range 0--4000. Any character can be inserted in a text string using an escape sequence of the form \(nnnn), where nnnn is the Hershey number. Notes: The Hershey symbols 0--127 are not the same symbols as the graph markers with corresponding numbers. For higher numbers all Hershey symbols can be used as graph markers. Example: Updates: Dec 22, 1994: VOG, Document created. #< */ /* plotsym.c: include files */ #include "stdio.h" /* Defines ANSI C input and output utilities */ #include "stdlib.h" /* Defines the ANSI C functions for number */ /* conversion, storage allocation, and similar tasks.*/ #include "string.h" /* Declares the ANSI C string functions*/ /* like:strcpy, strcat etc.*/ #include "math.h" /* Declares the mathematical functions and macros.*/ #include "cmain.h" /* Defines the main body of a C program with */ /* MAIN_PROGRAM_ENTRY and IDENTIFICATION */ #include "gipsyc.h" /* Defines the ANSI-F77 types for Fortran to C intface */ /* including def. of char2str,str2char,tofchar,zadd */ /* and macros tobool and toflog */ #include "float.h" /* Definition of FLT_MAX etc.*/ #include "ctype.h" /* Declares ANSI C functions for testing characters */ /* like: isalpha, isdigit etc. also tolower, toupper.*/ /* Common includes */ #include "init.h" /* Declare task running to HERMES and initialize.*/ #include "finis.h" /* Informs HERMES that servant quits and cleans up the mess.*/ #include "anyout.h" /* General character output routine for GIPSY programs.*/ #include "setfblank.h" /* Subroutine to set a data value to the universal BLANK.*/ #include "error.h" /* User error handling routine. */ #include "myname.h" /* Obtain the name under which a GIPSY task is being run.*/ #include "nelc.h" /* Characters in F-string discarding trailing blanks.*/ /* User input routines */ #include "userint.h" /* User input interface routines.*/ #include "userlog.h" #include "userreal.h" #include "userdble.h" #include "usertext.h" #include "usercharu.h" #include "reject.h" /* Reject user input.*/ #include "cancel.h" /* Remove user input from table maintained by HERMES.*/ /* Input of sets */ #include "gdsinp.h" /* Input of set, subsets, return # subsets.*/ #include "gdspos.h" /* Define a position in a subset.*/ #include "gdsbox.h" /* Define a box inside/around a subset.*/ #include "gdsc_range.h" /* Return lower left and upper right corner of a subset.*/ #include "gdsc_ndims.h" /* Return the dimensionality of a coordinate word.*/ #include "gdsc_grid.h" /* Extract grid value.*/ #include "gdsc_fill.h" /* return coordinate word filled with a grid */ /* value for each axis.*/ #include "gdsi_read.h" /* Reads data from (part of) a set.*/ /* PGPLOT includes */ #include "pgbeg.h" /* Begin PGPLOT, open output device. */ #include "pgend.h" /* Terminate PGPLOT. */ #include "pgask.h" /* Control new page prompting. */ #include "pgslw.h" /* Set line width.*/ #include "pgsvp.h" /* Set viewport (normalized device coordinates). */ #include "pgsci.h" /* Set color index. */ #include "pgsch.h" /* Set character height. */ #include "pgpage.h" /* Advance to new page. */ #include "pgswin.h" /* Set window. */ #include "pgscf.h" /* Set character font.*/ #include "pgdraw.h" /* Draw a line from the current pen position to a point.*/ #include "pgmove.h" /* Move pen (change current pen position).*/ #include "pgpt.h" /* Plot one or more points.*/ #include "pgexist.h" /* Does number correspond to a Hershey symbol? */ /* DEFINITIONS: */ /* Initialize Fortran compatible string with macro 'fmake' */ #define fmake(fchr,size) { \ static char buff[size+1]; \ int i; \ for (i = 0; i < size; buff[i++] = ' '); \ buff[i] = 0; \ fchr.a = buff; \ fchr.l = size; \ } /* Malloc version of 'fmake' */ #define finit( fc , len ) { fc.a = malloc( ( len + 1 ) * sizeof( char ) ) ; \ fc.a[ len ] = '\0' ; \ fc.l = len ; } #define MYMAX(a,b) ( (a) > (b) ? (a) : (b) ) #define MYMIN(a,b) ( (a) > (b) ? (b) : (a) ) #define NINT(a) ( (a) < 0 ? (int)((a)-.5) : (int)((a)+.5) ) #define ABS(a) ( (a) < 0 ? (-(a)) : (a) ) #define PI 3.141592653589793 #define RAD(a) ( a * 0.017453292519943295769237 ) #define DEG(a) ( a * 57.295779513082320876798155 ) #define RELEASE "1.0" /* Version number */ #define STRLEN 80 /* Max length of strings */ #define KEYLEN 20 /* Max length of keywords */ #define MAXHERSEY 3000 #define NONE 0 /* Default levels in userxxx routines */ #define REQUEST 1 #define HIDDEN 2 #define EXACT 4 #define YES 1 /* C versions of .TRUE. and .FALSE. */ #define NO 0 /* PGPLOT variables */ const fint background = 0; /* Color definitions for PGPLOT. */ const fint foreground = 1; /* Black if background is white. */ const fint red = 2; const fint green = 3; const fint blue = 4; const fint cyan = 5; const fint magenta = 6; const fint yellow = 7; const fint orange = 8; const fint greenyellow = 9; const fint greencyan = 10; const fint bluecyan = 11; const fint bluemagenta = 12; const fint redmagenta = 13; const fint darkgray = 14; const fint lightgray = 15; /* Miscellaneous */ static char message[120]; /* All purpose character buffer. */ void anyoutC( int dev, char *anyCstr ) /*------------------------------------------------------------------*/ /* The C version of 'anyout_c' needs two parameters: */ /* an integer and a C-type string. The integer determines */ /* the destination of the output which is: */ /* 0 use default [set by HERMES to 3 but can be changed by user]*/ /* 1 terminal */ /* 2 LOG file */ /* 8 terminal, suppressed in "experienced mode" */ /* 16 terminal, only when in "test mode" */ /*------------------------------------------------------------------*/ { fint ldev = (fint) dev; anyout_c( &ldev, tofchar( anyCstr ) ); } static int hardcopydevice( void ) /*------------------------------------------------------------------*/ /* Is current plot device a hard copy device? */ /*------------------------------------------------------------------*/ { fint len; fchar Inquiry; fmake( Inquiry, 4 ); /* Return value can be YES or NO only */ /* The number of characters returned */ /* in 'Inquiry' is 'len' */ pgqinf_c( tofchar( "HARDCOPY" ), Inquiry, &len ); if (len == 3) /* If 'YES' is returned */ { anyoutC( 16, "Device is a hard copy device" ); return( YES ); } else { anyoutC( 16, "Device is a screen device" ); return( NO ); } } void initplot( void ) /*------------------------------------------------------------------*/ /* Initialize plot software. */ /*------------------------------------------------------------------*/ { fint unit; /* Ignored by pgbeg, use unit=0. */ fchar Devspec; /* Device specification. */ fint nxysub[2]; /* Number of subdivisions on 1 page. */ fint nitems, dfault; fint r1; fint errlev = 4; /* Set error level to fatal. */ bool pageoff; /* Disable PGPLOT's NEXTPAGE keyword. */ float xl, xr, yb, yt; /* Edges of the viewport. */ /* Begin PGPLOT, open output device. A return value of 1 indicates */ /* successful completion. There are 4 arguments for PGBEG: */ /* UNIT, this argument is ignored by PGBEG (use zero). */ /* FILE, If this argument is a question mark PGBEG will prompt the */ /* user to supply a string. */ /* NXSUB,the number of subdivisions of the view surface in X. */ /* NYSUB,the number of subdivisions of the view surface in Y. */ nxysub[1] = nxysub[0] = 1; /* Default no subdivisions in plot.*/ unit = 0; Devspec = tofchar("?"); r1 = pgbeg_c( &unit, Devspec, &nxysub[0], &nxysub[1] ); if (r1 != 1) error_c( &errlev, tofchar("Cannot open output device") ); /* No PGPLOT's NEXTPAGE= keyword */ pageoff = toflog( NO ); pgask_c( &pageoff ); { /* Set the line width */ fint lwidth; if (hardcopydevice()) lwidth = 2; else lwidth = 1; nitems = 1; dfault = HIDDEN; (void) sprintf( message, "Give line width 1..21: [%d]", lwidth ); r1 = userint_c( &lwidth, &nitems, &dfault, tofchar("PGWIDTH="), tofchar( message ) ); if (lwidth > 21) lwidth = 21; if (lwidth < 1 ) lwidth = 1; pgslw_c( &lwidth ); } { /* Set the character font */ fint font; font = 2; nitems = 1; dfault = HIDDEN; r1 = userint_c( &font, &nitems, &dfault, tofchar("PGFONT="), tofchar("Give font 1..4: [2]") ); if (font > 4) font = 4; if (font < 1) font = 1; pgscf_c( &font ); /* Set font. */ } } static void plmove( float x, float y ) /*------------------------------------------------------------*/ /*------------------------------------------------------------*/ { pgmove_c( &x, &y ); } static void pldraw( float x, float y ) /*------------------------------------------------------------*/ /*------------------------------------------------------------*/ { pgdraw_c( &x, &y ); } static void plmark( float x, float y, fint symbol ) /*------------------------------------------------------------*/ /* Plot a marker at position x,y. */ /*------------------------------------------------------------*/ { fint one = 1; pgpt_c( &one, &x, &y, &symbol ); } static void plhtxt( float x, float y, char *txt ) /*------------------------------------------------------------*/ /* Plot a horizontal centered text at position x,y. */ /*------------------------------------------------------------*/ { float just = 0.5; float angle = 0.0; pgptxt_c( &x, &y, &angle, &just, tofchar(txt) ); } static void drawframe( float x1, float x2, float y2, float xoff, float yoff, float xstep, float ystep, int rows, int columns , char *title, fint color ) /*------------------------------------------------------------*/ /* Plot a frame and write title. */ /*------------------------------------------------------------*/ { int i, j; fint oldcolor; pgqci_c( &oldcolor ); pgsci_c( &color ); plmove( xoff, yoff ); /* Draw frame */ pldraw( xoff, y2 - yoff ); pldraw( x2 - xoff, y2 - yoff ); pldraw( x2 - xoff, yoff ); pldraw( xoff, yoff ); /* Lines of constant y */ for (i = 0; i < rows; i++) { float y; y = y2 - yoff - ((float)i)*ystep; plmove( xoff, y ); pldraw( x2 - xoff, y ); } /* Lines of constant x */ for (j = 0; j < columns; j++) { float x; x = x = x1 + xoff + ((float)j)*xstep; plmove( x, yoff ); pldraw( x, y2 - yoff ); } plhtxt( x2/2.0, y2 - yoff + 2.0, title ); /* Title */ pgsci_c( &oldcolor ); /* Reset colour */ } static void plotmarkers( int rows, int columns, float *charhei ) /*------------------------------------------------------------*/ /* Plot markers with numbers -1 to 'rows*columns-2' in 'rows' */ /* rows and 'columns' columns. Put number of symbol below */ /* the plotted symbol. */ /*------------------------------------------------------------*/ { fint mm = 2; float nx1 = 0.0, nx2 = 1.0, ny1 = 0.0, ny2 = 1.0; float x1, x2, y1, y2; float xoff, yoff; float xstep, ystep; float h; int i, j; int symnr; /* Get the size of the device in mm */ pgsvp_c( &nx1, &nx2, &ny1, &ny2 ); pgqvp_c( &mm, &x1, &x2, &y1, &y2 ); pgswin_c( &x1, &x2, &y1, &y2 ); /* From this moment on, all plotting is done in mm. */ /* There are 'rows*columns' symbols. Arrange in x rows /* of y columns. */ xoff = 10.0; /* In mm */ yoff = 15.0; xstep = (x2-x1-2.0*xoff) / (float)columns; ystep = (y2-y1-2.0*yoff) / (float)rows; symnr = -1; h = MYMIN(x2, y2) / 40.0; /* The height in mm of one character */ /* Convert character height from mm to scales. */ for (i = 0; i < 2; i++) { if (charhei[i] == 0.0) charhei[i] = ystep / 5.0; charhei[i] = ABS(charhei[i]) / h; } pgbbuf_c(); /* Start buffering */ drawframe( x1, x2, y2, xoff, yoff, xstep, ystep, rows, columns, "PGPLOT (marker) symbols:", green ); /* Plot the symbols */ for (i = 0; i < rows; i++) { float x, y; y = y2 - yoff - ((float)i+0.5)*ystep; for (j = 0; j < columns; j++) { x = x1 + xoff + ((float)j+0.5)*xstep; (void) sprintf( message, "%d", symnr ); pgsch_c( &charhei[0] ); /* Set character height */ plmark( x, y, symnr++ ); pgsch_c( &charhei[1] ); plhtxt( x, y-0.5*ystep+2.0, message ); } } pgebuf_c(); } static void plothershey( int rows, int columns, float *charhei ) /*------------------------------------------------------------*/ /* Plot Hershey symbols per page in 'rows' rows and 'columns' */ /* columns. Put number of Hershey symbol below the plotted */ /* character. */ /*------------------------------------------------------------*/ { fint mm = 2; fint nitems, dfault; float nx1 = 0.0, nx2 = 1.0, ny1 = 0.0, ny2 = 1.0; float x1, x2, y1, y2; float xoff, yoff; float xstep, ystep; float h; int i, j, symnr; fint pagenr, basenr; fint *symbolnr = NULL; int maxsymbols; int maxpages; int quit; int hardcopy; fint snr; symbolnr = (fint *) calloc( MAXHERSEY + 1, sizeof(fint) ); if (symbolnr == NULL) { anyoutC( 1, "Cannot allocate space for index array" ); return; } for (i = 1, snr = 1; snr <= MAXHERSEY; snr++) if (pgexist_c(&snr)) symbolnr[i++] = snr; maxsymbols = i - 1; /* Get the size of the device in mm and set window in mm */ pgsvp_c( &nx1, &nx2, &ny1, &ny2 ); pgqvp_c( &mm, &x1, &x2, &y1, &y2 ); pgswin_c( &x1, &x2, &y1, &y2 ); /* From this moment on, all plotting is done in mm. */ xoff = 10.0; /* In mm */ yoff = 15.0; xstep = (x2-x1-2.0*xoff) / (float)columns; ystep = (y2-y1-2.0*yoff) / (float)rows; symnr = -1; h = MYMIN(x2, y2) / 40.0; /* The height in mm of one character */ /* Convert character height from mm to scales. */ for (i = 0; i < 2; i++) { if (charhei[i] == 0.0) charhei[i] = ystep / 4.0; charhei[i] = ABS(charhei[i]) / h; } hardcopy = hardcopydevice(); pagenr = 1; maxpages = (maxsymbols - 1) / (rows * columns) + 1; do /* Loop over pages */ { nitems = 1; dfault = REQUEST; if (pagenr > maxpages) pagenr = 0; if (!hardcopy) { if (pagenr) (void) sprintf( message, "Give page number <= %d (0=exit): [%d]", maxpages, pagenr ); else (void) sprintf( message, "Give page number <= %d (0=exit): [EXIT]", maxpages, pagenr ); (void) userint_c( &pagenr, &nitems, &dfault, tofchar("PAGENR="), tofchar(message) ); cancel_c( tofchar("PAGENR=") ); } quit = (pagenr == 0); pagenr = MYMIN( pagenr, maxpages ); basenr = rows * columns * (pagenr-1) + 1; if (!quit) { pgpage_c(); pgbbuf_c(); (void) sprintf( message, "PGPLOT Hershey symbols %d", pagenr ); drawframe( x1, x2, y2, xoff, yoff, xstep, ystep, rows, columns, message, green ); for (i = 0; i < rows; i++) { float x, y; y = y2 - yoff - ((float)i+0.5)*ystep; for (j = 0; j < columns; j++) { if (basenr <= maxsymbols) { x = x1 + xoff + ((float)j+0.5)*xstep; (void) sprintf( message, "\\(%04d)", symbolnr[basenr] ); pgsch_c( &charhei[0] ); /* Set character height */ plhtxt( x, y, message ); (void) sprintf( message, "%04d", symbolnr[basenr] ); pgsch_c( &charhei[1] ); plhtxt( x, y-0.5*ystep+2.0, message ); } basenr++; } } pgebuf_c(); } pagenr++; } while (!quit); } MAIN_PROGRAM_ENTRY /*-------------------------------------------------------------------------*/ /* The macro MAIN_PROGRAM_ENTRY replaces the C-call main() to start the */ /* main body of your GIPSY application. Variables defined as 'fchar' start */ /* with a capital. */ /*-------------------------------------------------------------------------*/ { fint rowcol[2]; float charhei[2]; fint nitems, dfault; fint r1; fint option; init_c(); /* contact Hermes */ /* Task identification */ { static fchar Task; /* Name of current task */ fmake( Task, 20 ); /* Macro 'fmake' must be available */ myname_c( Task ); /* Get task name */ Task.a[nelc_c(Task)] = '\0'; /* Terminate task name with null char*/ IDENTIFICATION( Task.a, RELEASE ); /* Show task and version */ } initplot(); /* Make a selection. Plot the marker symbols on one page (auto scaling) */ /* or plot the Hershey symbols per page. */ nitems = 1; dfault = REQUEST; option = 1; (void) sprintf( message, "1=Plot markers, 2=Plot Hershey symbols: [%d]", option ); (void) userint_c( &option, &nitems, &dfault, tofchar("OPTION="), tofchar(message) ); if (option != 2) option = 1; nitems = 2; dfault = REQUEST; if (option == 1) rowcol[0] = rowcol[1] = 6; else { rowcol[0] = 12; rowcol[1] = 8; } (void) sprintf( message, "Give number of rows, columns to display: [%d %d]", rowcol[0], rowcol[1] ); (void) userint_c( rowcol, &nitems, &dfault, tofchar("ROWCOL="), tofchar(message) ); nitems = 2; dfault = REQUEST; charhei[0] = 0.0; charhei[1] = 0.0; r1 = userreal_c( charhei, &nitems, &dfault, tofchar("CHARHEI="), tofchar("Give char.height (in mm) for symbols, numbers: [calculated]") ); if (option == 1) { /* Plot the markers */ plotmarkers( rowcol[0], rowcol[1], charhei ); } else { /* Plot the Hershey symbols */ plothershey( rowcol[0], rowcol[1], charhei ); } /*-------------------------------------------------------*/ /* To end the program, make sure files opened with fopen */ /* are closed, allocated memory is released, PGPLOT is */ /* closed and HERMES is instructed to stop. */ /*-------------------------------------------------------*/ pgend_c(); finis_c(); return(EXIT_SUCCESS); /* Dummy return */ }