/* @(#)trace1d.c 17.1.1.2 (ESO-DMD) 02/25/02 17:45:37 */ /*=========================================================================== 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 Massachusetts Ave, Cambridge, MA 02139, USA. Correspondence 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: Copyright (c) 1994 European Southern Observatory, all rights reserved .IDENTIFIER TRACE1D .LANGUAGE C .AUTHOR K. Banse, R.M. van Hees IPG-ESO Garching .KEYWORDS Image Display, graphic trace .PURPOSE display (in graphics or overlay) a interactively extracted 1-D trace and copy it to a file .ALGORITHM use one cursor to define the line we are working on .INPUT/OUTPUT call as TRACE1D( action, maxsize, imf, stepln, outfra ); input: char *action : '1' for 1-dim trace '3' for 1-dim row trace '4' for 1-dim column trace int maxsize : maximum size of the trace int imf : id of the input image double stepln : step size along the trace char *outfra : name of the trace .RETURNS nothing .ENVIRONment MIDAS #include Prototypes for MIDAS interfaces #include Global variables for DISPLAY interfaces .VERSIONS 1.00 940630 converted to C from TRACE.FOR, R.M.van Hees 020201 last modif ------------------------------------------------------------*/ /* Define _POSIX_SOURCE to indicate that this is a POSIX program */ #define _POSIX_SOURCE 1 #include #include /* needed for agl.h */ #include #include #include #include #include #ifndef TRUE #define TRUE 1 #define FALSE 0 #endif #ifndef PI #define PI 3.14159265358979325e0 #endif #define DEG2RAD (PI / 180.0) #define SMALLVAL 1.e-12 #define RowTRACE 0 /* tracefl: a horizontal trace */ #define ColTRACE 1 /* a vertical trace */ #define RupTRACE 2 /* <= 45 deg. trace */ #define CupTRACE 3 /* > 45 deg. trace */ /* for Ccursin */ #define CFORM 8 /* cursor shape (= x-hair) */ #define COLOR 2 /* cursor color */ #define POLL_POS 2 /* continuous cursor position */ #define ENTR_POS 1 /* cursor position after ENTER */ #define MYMIN(a,b) ((a) > (b) ? (b) : (a)) #define MYMAX(a,b) ((a) < (b) ? (b) : (a)) /* Global variables, they are set in TRACE1D and not to be changed in one of the static functions! */ static char ident[33], cunit[49]; static int npix[2]; static int planoff = 0, ffelem = 1; /* */ /*++++++++++++++++++++++++++++++ .IDENTIFIER GET_ANGLE .PURPOSE return angle in degrees .INPUT/OUTPUT input: float *area : x_min, x_max, y_min, y_max of trace (in world coordinates) .RETURNS nothing ------------------------------*/ #ifdef __STDC__ static double GET_ANGLE( float *area ) #else static double GET_ANGLE( area ) float *area; #endif { double dx, dy; dx = area[1] - area[0]; dy = area[3] - area[2]; if (fabs(dy) < SMALLVAL) return 90.0; else return atan2( dy, dx ) / DEG2RAD; } /* */ /*++++++++++++++++++++++++++++++ .IDENTIFIER EXTEND_TR(ace) .PURPOSE extend trace across whole image, but not outside display window .INPUT/OUTPUT input: int tr_flag : type of trace int tr_rm : slope of the trace in/output: int *disp : x_min, x_max, y_min, y_max of trace (in channel coordinates) .RETURNS nothing ------------------------------*/ #ifdef __STDC__ static void EXTEND_TR( int tr_flag, double tr_rm, int *disp ) #else static void EXTEND_TR( tr_flag, tr_rm, disp ) int tr_flag, *disp; double tr_rm; #endif { int idum, fsx, fsy, flx, fly; fsx = fsy = 0; /* fsx,fsy,flx,fly = corners of display */ Sc2ch(1,&fsx,&fsy); fsx = MYMAX(fsx,SSPX); /* SSPX, SSPY already in image channel */ fsy = MYMAX(fsy,SSPY); flx = QDSZX - 1; fly = QDSZY - 1; Sc2ch(1,&flx,&fly); flx = MYMIN(flx,(SSPX + NSX - 1)); fly = MYMIN(fly,(SSPY + NSY - 1)); if ( tr_flag == RowTRACE ) { disp[0] = fsx; disp[1] = flx; } else if ( tr_flag == ColTRACE ) { disp[2] = fsy; disp[3] = fly; } else { /* find 'entering' intersection */ idum = CGN_NINT( tr_rm * (fsx - disp[0])) + disp[2]; if ( fsy > idum ) { disp[0] = CGN_NINT( (fsy - disp[2])/tr_rm ) + disp[0]; disp[2] = fsy; } else if ( fly < idum ) { disp[0] = CGN_NINT( (fly - disp[2])/tr_rm ) + disp[0]; disp[2] = fly; } else { disp[0] = fsx; disp[2] = idum; } /* find 'leaving' intersection */ idum = CGN_NINT( tr_rm * (flx - disp[0]) ) + disp[2]; if ( fsy > idum ) { disp[1] = CGN_NINT( (fsy - disp[2])/tr_rm ) + disp[0]; disp[3] = fsy; } else if ( fly < idum ) { disp[1] = CGN_NINT( (fly - disp[2])/tr_rm ) + disp[0]; disp[3] = fly; } else { disp[1] = flx; disp[3] = idum; } } } /* */ /*++++++++++++++++++++++++++++++ .IDENTIFIER CONV_TR .PURPOSE convert display coordinates to image and world coordinates .INPUT/OUTPUT input: int tr_flag : type of trace int tr_rm : slope of the trace char *cutfl : extend the trace or not int *disp : x_min, x_max, y_min, y_max of trace (in channel coordinates) output: float *image : size in PIXEL coordinates float *area : size in WORLD coordinates .RETURNS error status: -1 Could not do the pixel conversion ------------------------------*/ #ifdef __STDC__ static int CONV_TR(int tr_flag,double tr_rm,char *cutfl, int *disp,float *image,float *area) #else static int CONV_TR(tr_flag,tr_rm,cutfl,disp,image,area) int tr_flag, *disp; char *cutfl; float *image, *area; double tr_rm; #endif { float pixel[6]; double dd1[4], dd2[4], dd3[4]; /* synchronize with fp2wc */ Sc2ch(1,disp,disp+2); *disp = MYMAX(*disp,SSPX); *disp = MYMIN(*disp,(SSPX+NSX-1)); *(disp+2) = MYMAX(*(disp+2),SSPY); *(disp+2) = MYMIN(*(disp+2),(SSPY+NSY-1)); Sc2ch(1,disp+1,disp+3); *(disp+1) = MYMAX(*(disp+1),SSPX); *(disp+1) = MYMIN(*(disp+1),(SSPX+NSX-1)); *(disp+3) = MYMAX(*(disp+3),SSPY); *(disp+3) = MYMIN(*(disp+3),(SSPY+NSY-1)); if ( *cutfl == 'N' ) EXTEND_TR(tr_flag,tr_rm,disp); /* convert intersection points from image memory pixels to real pixels & w.c. */ dd1[0] = (double)disp[0]; dd1[1] = (double)disp[2]; dd1[2] = ZPLANE; if ( Pixconv("IRW",0,dd1,dd2,dd3) != 0 ) return (-1); image[0] = (float)dd2[0]; image[2] = (float)dd2[1]; area[0] = (float)dd3[0]; area[2] = (float)dd3[1]; dd1[0] = (double)disp[1]; dd1[1] = (double)disp[3]; if ( Pixconv("IRW",0,dd1,dd2,dd3) != 0 ) return (-1); image[1] = (float)dd2[0]; image[3] = (float)dd2[1]; area[1] = (float)dd3[0]; area[3] = (float)dd3[1]; return (0); } /* */ /*++++++++++++++++++++++++++++++ .IDENTIFIER EXTR_DATA .PURPOSE extract data of trace from image .INPUT/OUTPUT input: int mxsize : maximum size of a chunk int imf : file id of data frame float *image : xstart,xend,ystart,yend, in pixel space double pxstep : step size output: int *npnts : actual no. of pixels in trace float **p_trace : pointer to the data of the trace float *cuts : min & max found in the trace .RETURNS nothing ------------------------------*/ #ifdef __STDC__ static void EXTR_DATA( int mxsize, int imf, float *image, double pxstep, int *npnts, float **p_trace, float *cuts ) #else static void EXTR_DATA( mxsize, imf, image, pxstep, npnts, p_trace, cuts ) int mxsize, *npnts, imf; float *image, **p_trace, *cuts; double pxstep; #endif { register int ii; int actvals, unit, knul; static int img_size, map_all, max_pnt = 10000, init = TRUE; float *pntrX, *pntrY, *p_img, xa, ya, xb, yb; static float *pntrL; char output[82]; static char *err_mem = "EXTR_DATA: line longer than %-d points..."; if ( init ) { init = FALSE; img_size = *npix * npix[1]; if ( img_size <= mxsize ) map_all = TRUE; else map_all = FALSE; } else (void) free( (char *) pntrL ); xa = image[0]; ya = image[2]; xb = image[1]; yb = image[3]; /* get no. of pixels and the indices (in pixel space) */ get_nopix: pntrX = (float *) malloc((unsigned int)(max_pnt * sizeof(float))); pntrY = (float *) malloc((unsigned int)(max_pnt * sizeof(float))); if ((*npnts = Cpixlin(xa,ya,xb,yb,pxstep,max_pnt,pntrX,pntrY)) == max_pnt) { (void) free((char *) pntrX); (void) free((char *) pntrY); max_pnt += 10000; /* increase size */ if (max_pnt > 1000000) { (void) sprintf(output,err_mem,max_pnt); SCETER(1,output); } else goto get_nopix; } pntrL = (float *) malloc((unsigned int)((*npnts) * sizeof(float))); *p_trace = pntrL; /* Now we want to extract enough data from the image to collect the data of the line. There are 3 possibilities: - the image is small (<= MAXSIZE) --> we read it and keep it in memory - the image is large (> MAXSIZE), but the number of points needed for the line is small (<= MAXSIZE) --> we read what we need and release it - the image is large (> MAXSIZE) and the number of points needed for the line is large (> MAXSIZE) --> we read chunks, collect from each chunk the data for the line and release memory after use */ if ( map_all ) { p_img = (float *) malloc((unsigned int)(img_size * sizeof(float))); SCFGET(imf,ffelem,img_size,&actvals,(char *) p_img); Czima(p_img,npix,pntrX,pntrY,*npnts,pntrL,cuts+2, cuts+3); } else { int offX, offY, rpix[2]; rpix[0] = CGN_NINT(fabs(xa - xb)) + 1; rpix[1] = CGN_NINT(fabs(ya - yb)) + 1; p_img = (float *) malloc((unsigned int)(mxsize * sizeof(float))); if ((img_size = *npix * rpix[1]) > mxsize) /* take full lines */ { int first, npoint, offL, img_max; float cutvls[2], frame[4], ln_last = MYMAX(ya,yb); img_max = mxsize/(*npix); /* max. possible rows */ cuts[2] = (float) 1.0e+38; cuts[3] = (float) -1.0e+38; frame[0] = MYMIN(xa,xb); frame[1] = MYMAX(xa,xb); frame[2] = MYMIN(ya,yb); offX = CGN_NINT( frame[0] ) - 1; for (ii=0; ii<*npnts; ii++) pntrX[ii] -= offX; while (frame[2] <= ln_last) { frame[3] = MYMIN( frame[2] + img_max - 1, ln_last ); rpix[1] = CGN_NINT( frame[3] - frame[2] ) + 1; GetData(imf,mxsize,npix,frame,ffelem,0,p_img); /* Determine number of points in subimage which are falling within "frame" and offset in array pntrL of these points in array "pntrL" */ first = TRUE; npoint = 0; offY = CGN_NINT(frame[2]) - 1; for (ii=0; ii<*npnts; ii++) { if ( pntrY[ii] >= frame[2] && pntrY[ii] < frame[3] ) { if ( first ) { first = FALSE; offL = ii; } npoint++; pntrY[ii] -= offY; } } Czima(p_img,rpix,pntrX+offL,pntrY+offL,npoint,pntrL+offL,cutvls, cutvls+1); /* Determine minima & maxima */ if ( cuts[2] > cutvls[0] ) cuts[2] = cutvls[0]; if ( cuts[3] < cutvls[1] ) cuts[3] = cutvls[1]; frame[2] = frame[3] + 1; } } else { GetData(imf,mxsize,npix,image,ffelem,0,p_img); offX = CGN_NINT( MYMIN(xa,xb)) - 1; offY = CGN_NINT( MYMIN(ya,yb)) - 1; for ( ii = 0; ii < *npnts; ii++ ) { pntrX[ii] -= offX; pntrY[ii] -= offY; } Czima( p_img, rpix, pntrX, pntrY, *npnts, pntrL, cuts+2, cuts+3 ); } } (void) free((char *) pntrX); (void) free((char *) pntrY); (void) free((char *) p_img); } /* */ /*++++++++++++++++++++++++++++++ .IDENTIFIER ERASE_TR(ace) .PURPOSE Erase old trace in image display .INPUT/OUTPUT input: float *cuts : min & max of trace int npnt : dimension of trace float *pntrT : pointer to data of trace .RETURNS nothing ------------------------------*/ #ifdef __STDC__ static void ERASE_TR( int *disp, float *cuts, int npnt, float *pntrT ) #else static void ERASE_TR( disp, cuts, npnt, pntrT ) int *disp, npnt; float *cuts, *pntrT; #endif { int icen[2]; static int initD = TRUE, scale[2] = { 1, 1 }, iaux[4]; static float angle; if ( initD ) /* initialise for DISPLAY */ { initD = FALSE; iaux[0] = 1; /* used by DRIMG: y_start */ iaux[1] = NSX; /* y_end */ iaux[2] = 0; /* y_offset */ iaux[3] = 0; /* maximum intensity */ } if ( IDINUM == 11 ) { (void) IIMCMY_C( QDSPNO, &QOVCH, 1, 0 ); (void) IIGPLY_C( QDSPNO, QOVCH, disp, disp+2, 2, 99, 1 ); } else { icen[0] = 1 + npnt / 2; /* graph in center of display windo */ icen[1] = QDSZX / 2; DRIMG_C(QDSPNO,QOVCH,TRUE,iaux,pntrT,npnt,icen,cuts+2,scale,angle); } } /* */ /*++++++++++++++++++++++++++++++ .IDENTIFIER DRAW_TR(ace) .PURPOSE Draw the trace on image or graphics display .INPUT/OUTPUT input: int cno : 1,2 for no. of cursors int tr_flag : type of trace char *plotfl : to plot or not to plot struct Point cpos[2]: cursor positions in screen coords float *image : start & end of trace (in pixel coord.) float *area : start & end of trace (in world coord.) float *cuts : min & max of trace int npnt : dimension of trace float *pntrT : pointer to data of trace .RETURNS nothing ------------------------------*/ #ifdef __STDC__ static void DRAW_TR(int cno, int tr_flag, char *plotfl, struct Point cpos[2], float *image, float *area, float *cuts, int npnt, float *pntrT ) #else static void DRAW_TR(cno,tr_flag,plotfl,cpos,image,area,cuts,npnt,pntrT) char *plotfl; int cno, tr_flag, npnt; float *image, *area, *cuts, *pntrT; struct Point cpos[2]; #endif { register int ii; int actvals, icen[2]; float rdum[4], rdumm[4], stepx, *xdata, wcfram[8]; char bin[3], cbuff[81]; /* Initialized and saved variables */ static char *metafl = "trace1d.plt", *label[4]; static int initD = TRUE, scale[2] = { 1, 1 }, initP = TRUE, /* initialisation flag */ access = 0, /* parameter PCOPEN */ plmode = -1, /* parameter PCOPEN */ stype, ltype, binmod, iaux[4]; static float angle = 0.0, /* no angle in DRIMG_C */ offset = 0.0; /* no y-offs in PCDATA */ if (*plotfl == 'D') { if (initD) /* initialize for DISPLAY */ { initD = FALSE; iaux[0] = 1; /* used by DRIMG: y_start */ iaux[1] = NSX; /* y_end */ iaux[2] = 0; /* y_offset */ iaux[3] = 255; /* maximum intensity */ } /* graph in center of display window */ icen[0] = 1 + (npnt/2); icen[1] = QDSZX / 2; DRIMG_C(QDSPNO,QOVCH,TRUE,iaux,pntrT,npnt,icen,cuts+2,scale,angle); } else if (*plotfl == 'P') { if (initP) /* get symbol type, line type, binmode & write labels */ { initP = FALSE; PCKRDI( "STYPE", 1, &actvals, &stype ); PCKRDI( "LTYPE", 1, &actvals, <ype ); PCKRDC( "BINMO", 4, &actvals, bin ); binmod = (strncmp( bin, "ON", 2 ) == 0) ? 1 : 0; for ( ii = 0; ii < 4; ii++ ) label[ii] = malloc((unsigned int)84); (void) strcpy(label[0],"Position("); (void) strcpy(label[1],"Position("); (void) strcpy(label[2],"Pixel value("); (void) strcpy(label[3],"Frame: "); if ( (int)strlen(cunit) > 32 ) (void) strncat( label[1], cunit+32, 16 ); if ( (int)strlen(cunit) > 16 ) (void) strncat( label[0], cunit+16, 16 ); if ( (int)strlen(cunit) > 0 ) (void) strncat( label[2], cunit, 16 ); for ( ii = 0; ii < 3; ii++ ) { (void) strcat(label[ii],")"); LABSTR( label[ii] ); } (void) strcat(label[3],dzmemc); } PCKWRR( "SCALE", 0, rdum ); /* scaling to default */ PCKWRR( "OFFSET", 0, rdum ); /* offset to default */ /* collect data */ xdata = (float *) malloc((unsigned int)(npnt * sizeof(float))); if ( tr_flag == ColTRACE || tr_flag == CupTRACE ) { wcfram[0] = area[2]; wcfram[1] = area[3]; } else { wcfram[0] = area[0]; wcfram[1] = area[1]; } *xdata = *wcfram; stepx = (wcfram[1] - wcfram[0]) / (npnt - 1); for ( ii = 1; ii < npnt; ii++ ) xdata[ii] = *xdata + ii * stepx; wcfram[4] = cuts[2]; wcfram[5] = cuts[3]; wcfram[2] = wcfram[3] = wcfram[6] = wcfram[7] = 0.0; /* Calculate small and big tickmarks, set world and pixel coordinate box, and set up the graphics device according to MIDAS settings */ GETFRM( "AUTO", wcfram ); PCKWRR( "XWNDL", 4, wcfram ); GETFRM( "AUTO", wcfram+4 ); PCKWRR( "YWNDL", 4, wcfram+4 ); PCKWRR( "PIXEL", 4, image ); PCOPEN( " ", metafl, access, &plmode ); /* plot the data and draw a frame (if requested) */ PCDATA( stype, ltype, binmod, xdata, pntrT, offset, npnt ); if (cno > 0) { double dd1[4], dd2[4], dd3[4]; dd1[0] = (double) cpos[0].px; /* screen coords of cursor 0 */ dd1[1] = (double) cpos[0].py; (void) Pixconv("SRW",0,dd1,dd2,dd3); if ( tr_flag == CupTRACE || tr_flag == ColTRACE ) ii = 1; else ii = 0; rdum[0] = (float) dd3[ii]; rdum[1] = rdum[0]; rdum[2] = (float) dd2[0]; /* save frame pixels */ rdum[3] = (float) dd2[1]; if (cno == 2) { dd1[0] = (double) cpos[1].px; /* screen coords of cursor 0 */ dd1[1] = (double) cpos[1].py; (void) Pixconv("SRW",0,dd1,dd2,dd3); if ( tr_flag == CupTRACE || tr_flag == ColTRACE ) ii = 1; else ii = 0; rdumm[0] = (float) dd3[ii]; rdumm[1] = rdumm[0]; } } if ( plmode > 0 ) { if ( tr_flag == RowTRACE || tr_flag == RupTRACE ) PCFRAM(wcfram,wcfram+4,label[0],label[2]); else PCFRAM(wcfram,wcfram+4,label[1],label[2]); if (cno > 0) { PCKRDR("YWNDL",2,&actvals,&rdum[2]); /* get y-min, max of plot */ PCDATA(0,5,0,rdum,&rdum[2],0.,2); if (cno == 2) PCDATA(0,5,0,rdumm,&rdum[2],0.,2); /* no typing error: rdum[2] */ } PLBDFI(plmode,dzmemc,ident,image); if ( plmode == 1 ) { if ( tr_flag == RowTRACE ) (void) sprintf( cbuff, "Row: # %-.0f", image[2] ); else if ( tr_flag == ColTRACE ) (void) sprintf( cbuff, "Column: # %-.0f", image[0] ); else (void) sprintf( cbuff, "Trace from: (%-.0f,%-.0f), angle: %-.2f", image[0], image[2], GET_ANGLE( area )); PLIDEN( plmode, label[3], cbuff ); } } /* close the meta file (opened in PCOPEN) */ AG_MCLS(); (void) free( (char *) xdata ); } } /* */ /*++++++++++++++++++++++++++++++ .IDENTIFIER WR_FRAME .PURPOSE write data of trace into output file .INPUT/OUTPUT input: int tr_flag : type of trace char *outfra : name of the output file float *image : start & end of trace (in pixel coord.) float *area : start & end of trace (in world coord.) double stepT : stepsize of trace float *cuts : min & max of trace int npnt : dimension of trace float *pntrT : pointer to data of trace .RETURNS nothing ------------------------------*/ #ifdef __STDC__ static void WR_FRAME( int tr_flag, char *outfra, float *image, float *area, double stepT, float *cuts, int npnt, float *pntrT ) #else static void WR_FRAME(tr_flag,outfra,image,area,stepT,cuts,npnt,pntrT) char *outfra; int tr_flag, npnt; float *image, *area, *cuts, *pntrT; double stepT; #endif { int imno, unit, pixo[4]; char output[84]; static char *rowhis= "row trace of: %s, from frame pixels %-.0f,%-.0f to %-.0f,%-.0f", *colhis= "Column trace of: %s, from frame pixels %-.0f,%-.0f to %-.0f,%-.0f", *trchis= "trace of: %s, from frame pixels %-.0f,%-.0f to %-.0f,%-.0f"; if ( *outfra != '+' ) { char *cpntr; double startT, endT; if ( tr_flag == ColTRACE || tr_flag == CupTRACE ) { startT = area[2]; endT = area[3]; } else { startT = area[0]; endT = area[1]; } if (endT < startT) { if (stepT > 0.) stepT = -stepT; } else { if (stepT < 0.) stepT = -stepT; } (void) SCIPUT(outfra,D_R4_FORMAT,F_O_MODE,F_IMA_TYPE,1,&npnt, &startT,&stepT,ident,cunit,&cpntr,&imno); Ccopyf(pntrT,(float *) cpntr,npnt); (void) strcpy(output,"min, max, low_cut, high_cut for display/plot"); (void) SCDHWR(imno,"LHCUTS",cuts,1,4,&unit,output); (void) sprintf(output,"frame %s created",outfra); SCTPUT(output); pixo[0] = image[0]; pixo[1] = image[2]; pixo[2] = image[1]; pixo[3] = image[3]; (void) strcpy(output,"start, end pixels of trace in original frame"); (void) SCDHWI(imno,"START_END_TRACEPIX",pixo,1,4,&unit,output); if (tr_flag == RowTRACE) (void) sprintf(output,rowhis,dzmemc,image[0],image[2],image[1],image[3]); else if (tr_flag == ColTRACE) (void) sprintf(output,colhis,dzmemc,image[0],image[2],image[1],image[3]); else (void) sprintf(output,trchis,dzmemc,image[0],image[2],image[1],image[3]); (void) SCDWRC(imno,"HISTORY",1,output,1,80,&unit); SCTPUT(output); (void) SCFCLO(imno); } } /* */ void TRACE1D( action, maxsize, imf, stepln, outfra ) char *action, *outfra; int maxsize, imf; double stepln; { register int nn; int actvals, enter, iter, knul, ncurs, npnts, tr_flag, unit, disp[4]; int cursex, idx, idy, cno, nopix, zoomwn, kkbuf[2], odisp[4]; int dazhold[2]; float result[4], cutvls[2], fixpts[4]; float *p_trace, cuts[4], image[4], area[4]; double step[2], dd1[4], dd2[4], dd3[4]; double rm, pxstep, stepT; char cutfl[2], plotfl[2], cbuff[81], output[81]; struct Point cpos[2]; int first = 1, got_frame = 0; static int draw, erase_flag, old_disp[4]; static double abs_rm = 1.0; static char *err_conv = "TRACE1D - FATAL: can not convert given screen coordinates", *err_step = "TRACE1D - FATAL: invalid stepsize: %-.6g for trace entered", *war_plfl = "TRACE1D - WARNING: Invalid plot flag, reset to D(isplay)"; static char *rowmes = "Min, Max = %-.6g, %-.6g at y-pixel #%-.0f", *colmes = "Min, Max = %-.6g, %-.6g at x-pixel #%-.0f", *trcmes = "Min, Max = %-.6g, %-.6g no_of_pixels = %-d "; if ( IDINUM == 11 ) /* flags for IDI interfaces */ { erase_flag = 99; draw = 99; } else { erase_flag = 0; draw = 200; } for (nn=0; nn<4; nn++) old_disp[nn] = -1; /* Read the input image descriptors, except cuts these are global! */ (void) SCDRDI(imf,"NPIX",1,2,&actvals,npix,&unit,&knul); (void) SCDRDD(imf,"STEP",1,2,&actvals,step,&unit,&knul); (void) SCDGETC(imf,"IDENT",1,32,&actvals,ident); (void) SCDGETC(imf,"CUNIT",1,48,&actvals,cunit); (void) SCDRDR(imf,"LHCUTS",1,4,&actvals,cuts,&unit,&knul); if (ZPLANE != 0) /* 3-dim frame was loaded */ { planoff = (ZPLANE-1)*npix[0]*npix[1]; dd1[2] = ZPLANE; } else planoff = 0; ffelem = planoff + 1; if (Pixconv("INIT",imf,dd1,dd2,dd3) > 0) /* init wc conversion */ SCETER(69,"initialization of world coord. conversion failed ..."); /* Set flags */ (void) SCKGETC( "DEFAULT", 1, 2, &actvals, cbuff ); CGN_UPSTR( cbuff ); /* assure we have upper-case ... */ (void) strncpy( plotfl, cbuff, 1 ); if ( *plotfl != 'N' && *plotfl != 'D' && *plotfl != 'P' ) { SCTPUT(war_plfl); (void) strcpy(plotfl,"D"); } if ( *action == '1' ) { ncurs = 3; (void) strncpy(cutfl,cbuff+1,1); tr_flag = RupTRACE; /* default can also be Cup */ } else { ncurs = 0; (void) strcpy(cutfl,"N"); if ( *action == '3' ) tr_flag = RowTRACE; else if ( *action == '4' ) tr_flag = ColTRACE; else SCETER(1,"TRACE1D: unknown action flag..."); } /* Read keyword DAZIN, it contains zoom factor if we use zoom window */ (void) SCKRDI("DAZIN",1,1,&actvals,&zoomwn,&unit,&knul); /* check, if we use fixed "cursor positions" for repeatable extractions */ (void) SCKRDR("INPUTR",1,4,&actvals,fixpts,&unit,&knul); if (fixpts[0] > 0.) { cpos[0].px = fixpts[0]; cpos[0].py = fixpts[1]; cpos[1].px = fixpts[2]; cpos[1].py = fixpts[3]; enter = TRUE; cursex = 1; /* force to stop */ goto swap_points; } CURS_SETUP(ncurs,CFORM,COLOR); /* setup the cursors */ iter = 1; /* get cursor interrupts + update graph accordingly */ get_cursor: cursex = GET_CPOS(zoomwn,action,POLL_POS,ncurs,&iter,&enter,cpos); if (cursex == 0) { if ( tr_flag == RowTRACE ) { cpos[1].px = ( cpos->px <= QDSZX-2 ) ? cpos->px+1 : cpos->px-1; cpos[1].py = cpos->py; } else if ( tr_flag == ColTRACE ) { cpos[1].px = cpos->px; cpos[1].py = ( cpos->py <= QDSZY-2 ) ? cpos->py+1 : cpos->py-1; } swap_points: if ( cpos->px > cpos[1].px ) SWAP_PNT( 0, 1, cpos ); else if ( cpos->py > cpos[1].py ) SWAP_PNT( 0, 1, cpos ); odisp[0] = cpos[0].px; /* save original 2 points */ odisp[1] = cpos[1].px; odisp[2] = cpos[0].py; odisp[3] = cpos[1].py; if ( *cutfl != 'N' ) /* check, if short or extended line */ { cno = 0; /* cursors always at end */ for (nn=0; nn<4; nn++) disp[nn] = odisp[nn]; } else cno = 1; idx = cpos[1].px - cpos->px; /* set angles */ idy = cpos[1].py - cpos->py; if ( idx == 0 ) { if ( idy != 0 || abs_rm >= 1.0 ) { disp[0] = disp[1] = cpos->px; if ( *cutfl == 'N' ) { disp[2] = 0; disp[3] = QDSZY - 1; } rm = abs_rm = 99999.0; } else /* y-coords also equal, get last slope */ { if ( *cutfl == 'N' ) { disp[0] = 0; disp[1] = QDSZX - 1; } disp[2] = disp[3] = cpos->py; rm = abs_rm = 0.0; } } else if ( idy == 0 ) { if ( *cutfl == 'N' ) { disp[0] = 0; disp[1] = QDSZX - 1; } disp[2] = disp[3] = cpos->py; rm = abs_rm = 0.0; } else /* calculate new endpoints of line in screen pixels */ { rm = (double) idy / (double) idx; abs_rm = fabs( rm ); if (*cutfl == 'N') { END_PNT(rm,cpos,disp); cno = 2; } } /* erase old vector + draw new vector */ nn = 0; while ( nn < 4 && disp[nn] == old_disp[nn] ) nn++; if ( nn != 4 ) { if (first == 1) /* erase old vector + draw new one */ first = 0; else (void) IIGPLY_C(QDSPNO,QOVCH,old_disp,old_disp+2,2,erase_flag,1); (void) IIGPLY_C( QDSPNO, QOVCH, disp, disp+2, 2, draw, 1 ); /* store new vector into old one */ for (nn=0; nn<4; nn++) old_disp[nn] = disp[nn]; } /* if the ENTER key is pressed we extract the trace and draw it (optionally) */ if ( enter ) { iter = 0; if ( CONV_TR(tr_flag,rm,cutfl,odisp,image,area) != 0 ) SCETER(2,err_conv); /* Set the step size along the trace */ if ( tr_flag != ColTRACE && tr_flag != RowTRACE ) tr_flag = ( abs_rm > 1.0001 ) ? CupTRACE : RupTRACE; if ( tr_flag == CupTRACE || tr_flag == ColTRACE ) /* in y-dir */ { if (fabs(stepln) < SMALLVAL) { stepT = step[1]; pxstep = 1.0; /* stepsize in pixel space */ } else { if ((pxstep = stepln / step[1]) < SMALLVAL) { (void) sprintf( output, err_step, stepln ); SCETER( 3, output ); } stepT = stepln; } } else /* in x-dir */ { if (fabs(stepln) < SMALLVAL) { stepT = *step; pxstep = 1.0; /* stepsize in pixel space */ } else { if ((pxstep = stepln / *step) < SMALLVAL) { (void) sprintf( output, err_step, stepln ); SCETER( 3, output ); } stepT = stepln; } } /* Erase old trace */ if (got_frame == 0) got_frame = 1; /* nothing to erase */ else { if (*plotfl == 'D') ERASE_TR(disp,cuts,npnts,p_trace); } /* Extract the data of the trace and draw the trace*/ EXTR_DATA(maxsize,imf,image,pxstep,&npnts,&p_trace,cuts); DRAW_TR(cno,tr_flag,plotfl,cpos,image,area,cuts,npnts,p_trace); (void) CGN_FILL(output,' ',80); if ( tr_flag == RowTRACE ) (void) sprintf(output,rowmes,cuts[2],cuts[3],image[2]); else if ( tr_flag == ColTRACE ) (void) sprintf(output,colmes,cuts[2],cuts[3],*image); else (void) sprintf(output,trcmes,cuts[2],cuts[3],npnts ); (void) SCTDIS( output,99); } if (cursex == 0) goto get_cursor; /* look for more */ } /* Write data */ if (got_frame == 1) { (void) SCTDIS(output,0); /* repeat last output */ WR_FRAME(tr_flag,outfra,image,area,stepT,cuts,npnts,p_trace); (void) SCKWRI("OUTPUTI",disp,1,2,&unit); } }