/* @(#)pca.c 17.1.1.1 (ES0-DMD) 01/25/02 17:35:35 */ /*=========================================================================== 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 PCA .PURPOSE plot axes with tickmarks .AUTHOR R.M. van Hees IPG-ESO Garching .KEYWORDS High level plot interface .LANGUAGE C .COMMENTS holds PCFRAM and PCAXES, and redeclarations of low-level routines LOWCAS, GETTIC .ENVIRONment MIDAS and AGL #include Prototypes for AGL application programs #include Prototypes for MIDAS interfaces #include Symbols used by the PLT interfaces .VERSION 1.2 16-May-1994 removed initialization bug "tkfrm", RvH 1.1 23-Mar-1994 roundoff errors removed RvH 1.0 23-Sep-1993 created by R.M. van Hees -----------------------------------------------------------*/ /* * Define _POSIX_SOURCE to indicate * that this is a POSIX program */ #define _POSIX_SOURCE 1 /* * definition of the used functions */ #include #include #include #include #include #include /* * define some macros and constants */ #include /*++++++++++++++++++++++++++++ .IDENTifer Gettic .PURPOSE determine start and end values of the tickmarks input: float *axchar start, end value of the axis, and big and small tickmarks output: float *str_ax starting large tickmark float *end_ax last large tickmark .COMMENTS static function, also defined as low level routine GETTIC -----------------------------*/ #ifdef __STDC__ static void Gettic( float *axchar, float *str_ax, float *end_ax ) #else static void Gettic( axchar, str_ax, end_ax ) float *axchar, *str_ax, *end_ax; #endif { float clpl[4]; double amin, amax, abig, asmall, alen, atkstr, atkend, off, tick, value, xlen; amin = *axchar; amax = *(axchar + 1); abig = *(axchar + 2); asmall = *(axchar + 3); /* * Special case 1: lenght of the axis is zero */ if ( amin == amax ) { *str_ax = *axchar; *end_ax = *(axchar + 1); return; } /* * Special case 2: the big tickmark is larger than the lenght of the axis */ if ( asmall > 0 && abig >= fabs( amin - amax ) ) { *str_ax = *axchar; *end_ax = *(axchar + 1); return; } /* * Special case 3: log scaling and the axis is longer than 30 tickmarks */ if ( asmall < 0.0 && fabs( amin - amax ) > 30.0 ) { *str_ax = *axchar; *end_ax = *(axchar + 1); return; } if ( amax < amin ) abig *= -1.0; off = floor( amin / abig ); if ( amin / abig < 0.0 ) off -= 1.0; tick = abig * off; /* * get the length of the plot diagonal in pixel coordinates */ (void) AG_RGET( "CLPL", clpl ); alen = MYDIST( (clpl[1] - clpl[0]), (clpl[3] - clpl[2]) ); /* * find the smallest value on the axis */ do { if ( asmall < 0 ) { xlen = alen*( tick - amin )/( amax - amin ); value = pow( 10.0, tick ); } else { value = tick; if ( fabs( value ) < fabs( 1e-12 * abig ) ) value = 0.0; xlen = alen*( value - amin )/( amax - amin ); } if ( xlen < -0.00001 ) tick += abig; } while ( xlen < -0.00001 ); atkstr = value; /* * find the largest value on the axis */ atkend = atkstr; do { if ( asmall < 0 ) { xlen = alen*( tick - amin )/( amax - amin ); value = pow( 10.0, tick ); } else { value = tick; if ( fabs( value ) < fabs( 1e-12 * abig ) ) value = 0.0; xlen = alen * ( value - amin )/( amax - amin ); } if ( xlen <= alen * 1.00001 ) { atkend = value; tick += abig; } } while ( xlen <= alen * 1.00001 ); if ( asmall < 0.0 ) { *str_ax = (float) log10( atkstr ); *end_ax = (float) log10( atkend ); } else { *str_ax = (float) atkstr; *end_ax = (float) atkend; } return; } /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .IDENTifer PCFRAM .PURPOSE Draws a frame including tickmarks and labels input: float *xwcfrm axis definition for x: min, max & tick marks *ywcfrm axis definition for y: min, max & tick marks char *labelx label along X-axis *labely label along Y-axis .COMMENTS PCFRAM draws a standard MIDAS frame including tick marks and labels. Font, character size, line width and text thickness are defined by the MIDAS setting. PCFRAM uses the AGL routine AG_AXIS ------------------------------------------------------------*/ void PCFRAM( xwcfrm, ywcfrm, labelx, labely ) float *xwcfrm, *ywcfrm; char *labelx, *labely; { int actvals, xy, ltype, other, spec; float tkstr, tkend, *wcfram, adat[PLDIM2][11]; char *tkfrm, *format[2], *label[2], text[81]; /* * initialised variables, should be kept constant */ static char *scale[PLDIM2][2] = {{ "logx", "linx" }, { "logy", "liny" }}; static float lspace[PLDIM2] = { 2.0, 0.0 }; tkfrm = osmmget(10); for ( xy = 0; xy < PLDIM2; xy++ ) { format[xy] = osmmget(9); label[xy] = osmmget(81); *label[xy] = '\0'; } /* * set character and symbol sizes for the MIDAS layout */ PCTSET(); /* * Store the old line style, and set line style to solid */ (void) AG_IGET( "lstyl", <ype ); AG_SSET( "lstyl=0" ); if ( strncmp( labelx, "\"\"", 2 ) != 0 ) (void) strcpy( label[0], labelx ); if ( strncmp( labely, "\"\"", 2 ) != 0 ) (void) strcpy( label[1], labely ); /* * Set axis specification */ for ( xy = 0; xy < PLDIM2; xy++ ) { wcfram = ( xy == 0 ) ? xwcfrm : ywcfrm; Gettic( wcfram, &tkstr, &tkend ); adat[xy][0] = MYMIN( *wcfram, *(wcfram+1) ); adat[xy][1] = MYMAX( *wcfram, *(wcfram+1) ); adat[xy][2] = MYMIN( tkstr, tkend ); adat[xy][3] = MYMAX( tkstr, tkend ); adat[xy][4] = *(wcfram+2); adat[xy][5] = MYMIN( *(wcfram+2), *(wcfram+3) ); AG_SSET( scale[xy][1] ); if ( *(wcfram+3) <= -2.0 ) /*natural logarithmic scale*/ { adat[xy][0] = (float) exp( adat[xy][0] ); adat[xy][1] = (float) exp( adat[xy][1] ); adat[xy][2] = (float) exp( adat[xy][2] ); adat[xy][3] = (float) exp( adat[xy][3] ); adat[xy][4] = (float) exp( adat[xy][4] ); adat[xy][5] = adat[xy][4]; AG_SSET( scale[xy][0] ); } else if ( *(wcfram+3) < 0.0 ) /*logarithmic scale*/ { adat[xy][0] = (float) pow( 10.0, adat[xy][0] ); adat[xy][1] = (float) pow( 10.0, adat[xy][1] ); adat[xy][2] = (float) pow( 10.0, adat[xy][2] ); adat[xy][3] = (float) pow( 10.0, adat[xy][3] ); adat[xy][4] = (float) pow( 10.0, adat[xy][4] ); adat[xy][5] = MYMAX( 1.0, adat[xy][4] / 10.0 ); AG_SSET( scale[xy][0] ); } adat[xy][8] = 0; adat[xy][9] = 1; adat[xy][10] = 0; } /* * get format for the axes */ PCKRDC( "XFORM", 8, &actvals, format[0] ); PCKRDC( "YFORM", 8, &actvals, format[1] ); /* * draw X-axis and Y-axis, bottom and top */ for ( xy = 0; xy < PLDIM2; xy++ ) { CGN_LOWSTR( format[xy] ); *tkfrm = '\0'; if ( strncmp( format[xy], "none", 4 ) != 0 ) { (void) strcpy( tkfrm, "%" ); (void) strcat( tkfrm, format[xy] ); } other = (xy == 0) ? 1 : 0; /*define other as other axis*/ wcfram = ( other == 0 ) ? xwcfrm : ywcfrm; if ( *wcfram < *(wcfram+1) ) { adat[xy][6] = adat[other][0]; adat[xy][7] = adat[other][0]; } else { adat[xy][6] = adat[other][1]; adat[xy][7] = adat[other][1]; } spec = (xy == 0) ? 4 : 7; AG_AXIS( spec, adat[xy], lspace[xy], tkfrm, label[xy] ); if ( *wcfram < *(wcfram+1) ) { adat[xy][6] = adat[other][1]; adat[xy][7] = adat[other][1]; } else { adat[xy][6] = adat[other][0]; adat[xy][7] = adat[other][0]; } spec = (xy == 0) ? 6 : 5; AG_AXIS( spec, adat[xy], lspace[xy], " ", " " ); } /* * reset LTYPE */ if ( ltype > 0 ) { (void) sprintf( text, "lstyl=%1d", ltype ); AG_SSET( text ); } /* * free allocated memory */ (void) osmmfree( tkfrm ); for ( xy = 0; xy < PLDIM2; xy++ ) { (void) osmmfree( format[xy] ); (void) osmmfree( label[xy] ); } return; } /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .IDENTifer PCAXES .PURPOSE Computes tickmarks, and draws axes including tickmarks and labels input: float *xmnmx minimum and maximum value along the X-axis float *ymnmx minimum and maximum value along the Y-axis char *labelx label along X-axis char *labely label along Y-axis char *AGLopt AGL option string, see AG_AXES .COMMENTS PCAXES sets the clipping area so that it encloses the box defined by the axes (they are NOT taken from the MIDAS keywords!). In practice this means that you can call PCDATA and PCHIST to plot your data within the drawn frame. The character dimension is not affected by PCAXES. PC_AXES uses the AGL routine AG_AXES ------------------------------------------------------------*/ void PCAXES( xmnmx, ymnmx, labelx, labely, AGLopt ) float *xmnmx, *ymnmx; char *labelx, *labely, *AGLopt; { int actvals, ltype; float scale, ssize, tsize; char *buff, *options; char *fmt_sydi = "sydi=%-.3f;chdi=%-.3f,%-.3f"; buff = osmmget(41); options = osmmget(133); /* * make sure that strcat finds a null at the start of the string "options" */ *options = '\0'; /* * LTYPE is not saved by AG_AXES and also not consistently used * so we set line style to solid line */ (void) AG_IGET( "lstyl", <ype ); AG_SSET( "lstyl=0" ); /* * store character dimension */ (void) AG_RGET( "scale", &scale ); PCKRDR( "SSIZE", 1, &actvals, &ssize ); PCKRDR( "TSIZE", 1, &actvals, &tsize ); /* * fill a character array with options for AG_AXES */ if ( strlen( labelx ) != 0 ) { (void) strcat( options, "LABX=" ); (void) strcat( options, labelx ); (void) strcat( options, ";" ); } if ( strlen( labely ) != 0 ) { (void) strcat( options, "LABY=" ); (void) strcat( options, labely ); (void) strcat( options, ";" ); } (void) strcat( options, AGLopt ); /* * call AG_AXES */ AG_AXES( xmnmx[0], xmnmx[1], ymnmx[0], ymnmx[1], options ); /* * reset line type */ if ( ltype > 0 ) { (void) sprintf( buff, "lstyl= %1d", ltype ); AG_SSET( buff ); } /* * reset character dimension */ (void) sprintf( buff, fmt_sydi, scale * ssize, scale * tsize, scale * tsize ); AG_SSET( buff ); /* * free allocated memory */ (void) osmmfree( options ); (void) osmmfree( buff ); return; }