/* @(#)plgra.c 17.1.1.1 (ES0-DMD) 01/25/02 17:44:48 */ /*=========================================================================== Copyright (C) 1995 European Southern Observatory (ESO) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Massachusetss Ave, Cambridge, MA 02139, USA. Corresponding concerning ESO-MIDAS should be addressed as follows: Internet e-mail: midas@eso.org Postal address: European Southern Observatory Data Management Division Karl-Schwarzschild-Strasse 2 D 85748 Garching bei Muenchen GERMANY ===========================================================================*/ /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .COPYRIGHT (c) 1993 European Southern Observatory .IDENTifer module PLGRA .AUTHOR R.M. van Hees IPG-ESO Garching .KEYWORDS plot software, graphics, bulk data fame, gray scale plotting .LANGUAGE C .PURPOSE Grayscale plotting routine for two dimensional data .COMMENTS holds PLGRA, WEDGE and PLGRAI .ENVIRONment MIDAS and AGL #include Prototypes for AGL application programs #include Prototypes for MIDAS interfaces #include Symbols used by the PLT interfaces .VERSION 1.1 23-Sep-1993 FORTRAN --> ANSI-C RvH ------------------------------------------------------------*/ /* * Define _POSIX_SOURCE to indicate * that this is a POSIX program */ #define _POSIX_SOURCE 1 /* * definition of the used functions in this module */ #include #include #include #include #include #include /* * define some macros and constants */ #include #ifndef RAND_MAX #define RAND_MAX 32768.0 #endif /* * The array "options" holds TRUE and FALSE values for the following options */ #define LINS ( (*options == FALSE) ? TRUE : FALSE ) /*lineair scaling*/ #define LOGS ( (*options == TRUE) ? TRUE : FALSE ) /*log. scaling*/ #define CONT ( (*(options+1) == FALSE) ? TRUE : FALSE ) /*cont. gray scale*/ #define STEP ( (*(options+1) == TRUE) ? TRUE : FALSE ) /*stepwise gray*/ #define FLIP ( (*(options+2) == TRUE) ? TRUE : FALSE ) /*change sign*/ #define ABSV ( (*(options+3) == TRUE) ? TRUE : FALSE ) /*take abs values*/ #define CUTP ( (*(options+4) == TRUE) ? TRUE : FALSE ) /*only gray between cut values*/ /*++++++++++++++++++++++++++++++ .IDENTifer DWLOG .PURPOSE return the "traditional" Dwingeloo/Westerbork log scaling input double value .RETURNS Dwi/Wbrk log .COMMENTS static function --------------------------------*/ #ifdef __STDC__ static double DWLOG( double value ) #else static double DWLOG( value ) double value; #endif { value *= 0.549999 + 0.45 * value; return log10( 30 * value + 1 )/ log10( 30.42 ) - 0.007; } /*++++++++++++++++++++++++++++++ .IDENTifer HALFT .PURPOSE Produce halftone plot of a 2-D image input: double vnom normalized intensity: 0 <= vnom <= 1.0 int ipx number of pixels in the X direction int ipy number of pixels in the Y direction double pixx pixel size in world coordinates in X double pixy pixel size in world coordinates in Y double xstr position of stip in plotter coordinates double ystr position of stip in plotter coordinates float greynes grayness parameter: 0 <= greyness <= 1.0 .COMMENTS static function --------------------------------*/ #ifdef __STDC__ static void HALFT( double vnom, int ipx, int ipy, double pixx, double pixy, double xstr, double ystr, float greynes ) #else static void HALFT( vnom, ipx, ipy, pixx, pixy, xstr, ystr, greynes ) int ipx, ipy; float greynes; double vnom, pixx, pixy, xstr, ystr; #endif { float xpos, ypos; double rrand; register int ix, iy; if ( (ipx+1) * pixx < 1.0 ) ipx +=1; vnom *= greynes * RAND_MAX; for ( ix = 0; ix < ipx; ix++ ) { for ( iy = 0; iy < ipy; iy++ ) { rrand = fmod( (double) rand(), RAND_MAX ); if ( rrand < vnom ) { xpos = (float) (xstr + ix * pixx); ypos = (float) (ystr + iy * pixy); AG_GPLM( &xpos, &ypos, 1, 0 ); } } } } /*++++++++++++++++++++++++++++++++++++++++++++++++++ .IDENTifer PLGRA .PURPOSE Gray scale plotting routine for two dimensional data input: float *p_img pointer to the data of the frame float *image image size in pixel coordinates float *area image size in world coordinates double *step distance between pixels in world units float *glevl level of the countours int nlevl number of countours int *options holds the following options: LIN - LOG gray scaling STEP - CONTineously increasing gray scale POS - NEG increasing or decreasing gray scale ABS take the absolute values CUTS only gray scaling between the cuts float greynes grayness parameter between 0.0 and 1.0, 1.0 gives the maximum blackness 0.0 means white .COMMENTS if image[0] > image[1] or image[2] > image[3] then the values are put in the right order --------------------------------*/ #ifdef __STDC__ void PLGRA(float *p_img, float *image, float *area, double *step, float *glevl, int nlevl, int *options, float greynes) #else void PLGRA( p_img, image, area, step, glevl, nlevl, options, greynes ) int nlevl, *options; float *p_img, *image, *area, *glevl, greynes; double *step; #endif { int ipx, ipy, ipy1, ix, iy, nl, nx, ny, pixnx, pixny; float rres[2], clpl[4], wndl[4]; double delwx, delwy, delcx, delcy, diff, eps, pixx, pixy, val, vnom, xnom, xstr, ystr, ynom; /* * this functions only works if the number of levels is greater than zero */ if ( nlevl == 0 ) return; /* * get viewport characteristics */ (void) AG_RGET( "clpl", clpl ); (void) AG_RGET( "wndl", wndl ); (void) AG_RGET( "reso", rres ); AG_SSET( "sydi=0.10" ); /* * get the start world coordinates and window characteristics */ nx = (int) fabs( image[1] - image[0] ) + 1; ny = (int) fabs( image[3] - image[2] ) + 1; if ( *step < 0 ) xnom = MYMAX( area[0], area[1] ); else xnom = MYMIN( area[0], area[1] ); delwx = wndl[1] - wndl[0]; /* window size in X */ delwy = wndl[3] - wndl[2]; /* window size in Y */ delcx = fabs( clpl[1] - clpl[0] ); /* clipping size in X */ delcy = fabs( clpl[3] - clpl[2] ); /* clipping size in Y */ pixnx = NINT( delcx / rres[0] ); /* number of X pixels */ pixny = NINT( delcy / rres[1] ); /* number of Y pixels */ pixx = delwx / pixnx; /* size of a X pixel in w.c. */ pixy = delwy / pixny; /* size of a Y pixel in w.c. */ eps = fabs( *glevl * 0.0001 ); /* * start the code */ ipx = (int) ceil( *step/pixx ); ipy = (int) ceil( *(step+1)/pixy ); /* * reverse order of contours and reverse sign */ if ( FLIP ) { for ( nl = 0; nl < NINT( nlevl/2.0 ); nl++ ) { register int nn = nlevl - nl - 1; register float dummy = *(glevl+nl); *(glevl+nl) = - *(glevl+nn); *(glevl+nn) = - dummy; } } /* * Begin value in Y of gray - tone * ynom = nominal plot position; ystr = actual starting plot position */ if ( *(step+1) < 0 ) ynom = MYMAX( area[2], area[3] ) - 1.5 * *(step+1); else ynom = MYMIN( area[2], area[3] ) - 1.5 * *(step+1); ystr = ynom; for ( iy = 0; iy < ny - 1; iy++ ) { ystr += ipy * pixy; ynom += *(step+1); diff = ystr - ynom; if ( diff < 0 ) ystr += pixy; /* Does it start too low? */ if ( diff > pixy ) ystr -= pixy; /* Does it start too high? */ /* * how many lines within grid-interval */ ipy1 = (int) ceil( (ynom - ystr + *(step+1))/pixy ); for ( ix = 0; ix < nx; ix++ ) { xstr = xnom + (ix - 0.5) * *step; /* start position in X */ val = *(p_img+ix); if ( fabs( val ) < eps ) val = 0.0; if ( ABSV ) val = fabs( val ); if ( FLIP ) val = -val; if ( val > (double) *glevl ) { if ( val >= (double) *(glevl+nlevl - 1) ) { val = *(glevl+nlevl-1); if ( CUTP ) val += eps; } } vnom = 0.0; if ( STEP ) { if ( nlevl > 1 ) { for ( nl = 0; nl < nlevl-1; nl++ ) { if ( val >= (double) *(glevl+nl) && val < (double) *(glevl+nl+1)) { vnom = (double) (nl+1) / nlevl; if ( LOGS ) /* "log" scale Dwi/Wbrk.*/ vnom = DWLOG( vnom ); } } } if ( val == (double) *(glevl+nlevl-1) ) { vnom = 1.0; if ( LOGS ) /* "log" scale Dwi/Wbrk.*/ vnom = DWLOG( vnom ); } } else { if ( val >= (double) *glevl && val <= (double) *(glevl+1) ) { vnom = (val - *glevl)/fabs( *(glevl+1) - *glevl ); if ( LOGS ) /* "log" scale Dwi/Wbrk.*/ vnom = DWLOG( vnom ); } } if ( val >= (double) *glevl && val <= (double) *(glevl+nlevl-1) ) HALFT( vnom, ipx, ipy1, pixx, pixy, xstr, ystr, greynes); } /* * set the pointer to the begin of the new line to be drawn */ p_img += nx; } /* * reverse order of contours and reverse sign to get the original values */ if ( FLIP ) { for ( nl = 0; nl < NINT( nlevl/2.0 ); nl++ ) { register int nn = nlevl - nl - 1; register float dummy = *(glevl+nl); *(glevl+nl) = - *(glevl+nn); *(glevl+nn) = - dummy; } } return; } /*++++++++++++++++++++++++++++++++++++++++++++++++++ .IDENTifer WEDGE .PURPOSE plots a gray scale wedge input: float *glevl level of the countours int nlevl number of countours int *option holds the following options: LIN - LOG gray scaling STEP - CONTineously increasing gray scale POS - NEG increasing or decreasing gray scale ABS take the absolute values CUTS only gray scaling between the cuts float greynes grayness parameter between 0.0 and 1.0, 1.0 gives the maximum blackness 0.0 means white .COMMENTS ----------------------------------------------------*/ #ifdef __STDC__ void WEDGE(double *step, float *glevl, int nlevl, int *options, float greynes) #else void WEDGE( step, glevl, nlevl, options, greynes ) int nlevl, *options; float *glevl, greynes; double *step; #endif { int il, ix, iy, ngray, nx, ny; float eps, clpl[4], frame[4], image[4], xl[2], yl[2], *wdata; (void) AG_RGET( "clpl", clpl ); /* * define the area fro the wedge */ clpl[2] = clpl[3] - (clpl[3] - clpl[2]) / 20; AG_VN2U( clpl[0], clpl[2], frame , frame+2 ); AG_VN2U( clpl[1], clpl[3], frame+1, frame+3 ); /* * draw a line between the wedge and the gray scale plot */ xl[0] = frame[0]; xl[1] = frame[1]; yl[0] = frame[2]; yl[1] = frame[2]; AG_GPLL( xl, yl, 2 ); nx = (int) fabs( (frame[1] - frame[0]) / *step ) + 2; ny = (int) fabs( (frame[3] - frame[2]) / *(step+1) ) + 2; wdata = (float *) osmmget( nx * ny * sizeof( float )); if ( STEP ) { ngray = NINT( (float) nx / nlevl ); /* # gr. pnts. with same gray tone */ for ( iy = 0; iy < ny; iy++ ) { for ( il = 0; il < nlevl-1; il++ ) { eps = 0.00001 * (double) glevl[il]; for ( ix = 0; ix < ngray; ix++ ) *(wdata + (il-1) * ngray + ix) = *(glevl+il) + eps; } for ( ix = (nlevl-1) * ngray; ix < nx; ix++ ) *(wdata + ix) = *(glevl+il) + eps; wdata += nx; } wdata -= nx * ny; } else /* continuous gray scale */ { for ( iy = 0; iy < ny; iy++ ) { for ( ix = 0; ix < nx; ix++ ) { *(wdata + ix) = *glevl + ix * ( *(glevl+1) - *glevl) / nx; } wdata += nx; } wdata -= nx * ny; } /* * size of the wedge in pixel coordinates */ image[0] = image[2] = 0; image[1] = nx; image[2] = ny; /* * size of the wedge in world coordinates */ frame[0] += 1.5 * *step; frame[1] += 1.5 * *step; frame[2] += 0.5 * *(step+1); frame[3] += 0.5 * *(step+1); PLGRA( wdata, image, frame, step, glevl, nlevl, options, greynes ); return; } /*++++++++++++++++++++++++++++++++++++++++++++++++++ .IDENTifer PLGRAI .PURPOSE produce plot information for a two-dimensional grayscaler plot input: int plmode plot mode, see PMODE in PLISTAT char *name data frame name char *ident ascii identifier of image int nlevl number of contour levels float *glevl values of the contours .COMMENTS none ----------------------------------------------------*/ void PLGRAI( plmode, name, ident, nlevl, glevl, options ) int plmode, nlevl, *options; char *name, *ident; float *glevl; { int actvals, ii; float one, ssize, tsize, x1, x2, y1, y2, xt, yt, yh, xstr; float mnmx[2], scale[2], xl[3], yl[3], clpl[4], image[4], wndl[4]; char buff[81]; /* * only plot mode is 2 */ if ( plmode != 2 ) return; /* * get the symbol and character dimensions, from the MIDAS keywords */ PCKRDR( "SSIZE", 1, &actvals, &ssize ); PCKRDR( "TSIZE", 1, &actvals, &tsize ); /* * if the symbol size or the text size is not equal to 1, set it to 1 * and call PCTSET to get the proper sizes for the MIDAS layout */ if ( ssize != 1.0 || tsize != 1.0 ) { one = 1.0; PCKWRR( "SSIZE", 1, &one ); PCKWRR( "TSIZE", 1, &one ); } PCTSET(); AG_SSET( "norm"); AG_SSET( "linx"); AG_SSET( "liny"); (void) AG_RGET( "clpl", clpl ); (void) AG_RGET( "wndl", wndl ); x1 = clpl[1] + 0.01; x2 = 1.0; y1 = 0.0; y2 = clpl[3]; AG_CDEF( x1, x2, y1, y2); AG_WDEF( 0.0, 1.0, 0.0, 1.0 ); /* * plot MIDAS logo */ PLLOGI( &xt, &yt ); /* * set character height */ AG_SSET( "sydi=0.75;chdi=0.75,0.75" ); AG_TGET( "M", xl, yl ); yh = 2.0 * yl[1]; /* * plot user name */ PLUSER( buff ); AG_GTXT( xt, yt, buff, 1 ); /* * name of frame */ yt -= 2*yh; if ( strlen( name ) > (size_t) 12 ) { AG_GTXT( xt, yt, "Frame:", 1 ); yt -= yh; AG_GTXT( xt, yt, name, 1 ); } else { (void) sprintf( buff, "Frame: %s", name ); AG_GTXT( xt, yt, buff, 1 ); } /* * identification */ if ( strlen( ident ) > (size_t) 0 ) { yt -= 2*yh; AG_GTXT( xt, yt, "Identification:", 1 ); yt -= yh; AG_GTXT( xt, yt, ident, 1 ); } /* * area */ PCKRDR( "PIXEL", 4, &actvals, image ); yt -= 2*yh; AG_GTXT( xt, yt, "Area:", 1 ); yt -= yh; (void) sprintf( buff, "X: %.0f to %.0f", image[0], image[1] ); AG_GTXT( xt, yt, buff, 1 ); yt -= yh; (void) sprintf( buff, "Y: %.0f to %.0f", image[2], image[3] ); AG_GTXT( xt, yt, buff, 1 ); /* * scales */ PCKRDR( "SCALES", 2, &actvals, scale ); yt -= 2*yh; AG_GTXT( xt, yt, "Scales:", 1 ); yt -= yh; (void) sprintf( buff, "X: %-.6g", scale[0] ); AG_GTXT( xt, yt, buff, 1 ); yt -= yh; (void) sprintf( buff, "Y: %-.6g", scale[1] ); AG_GTXT( xt, yt, buff, 1 ); /* * minimum and maximum */ PCKRDR( "ZWNDL", 2, &actvals, mnmx ); yt -= 2*yh; (void) sprintf( buff, "Min: %-.3g ", mnmx[0] ); AG_GTXT( xt, yt, buff, 1 ); yt -= yh; (void) sprintf( buff, "Max: %-.3g ", mnmx[1] ); AG_GTXT( xt, yt, buff, 1 ); /* * contour levels */ yt -= 2*yh; if ( STEP ) AG_GTXT( xt, yt, "Gray scale levels:", 1 ); else { nlevl = 2; AG_GTXT( xt, yt, "Gray scale range:", 1 ); } for ( ii = 0; ii < nlevl; ii++ ) { xstr = xt + 11 * xl[1]; if ( ii % 2 == 0 ) { xstr = xt; yt -= yh; } (void) sprintf( buff, "%8.5g", glevl[ii] ); AG_GTXT( xstr, yt, buff, 1 ); } yt -= 2.*yh; PLDATI( &xt, &yt ); /* * back to standard sizes */ AG_CDEF( clpl[0], clpl[1], clpl[2], clpl[3] ); AG_WDEF( wndl[0], wndl[1], wndl[2], wndl[3] ); /* * reset if necessary the symbol and text size */ if ( ssize != 1.0 || tsize != 1.0 ) { PCKWRR( "SSIZE", 1, &ssize ); PCKWRR( "TSIZE", 1, &tsize ); PCTSET(); } return; }