void gb2_gdtlamb( float *navblk, int *igdtmpl, int *iret ) /************************************************************************ * gb2_gdtlamb * * * * This routine converts a LCC Gempak grid navigation block to a * * GRIB2 Grid Definition Template 3.30. * * * * gb2_gdtlamb ( navblk, igdtmpl, iret ) * * * * Input parameters: * * *navblk float Decoded GRIB2 structure * * * * Output parameters: * * *igdtmpl int GDT 3.30 values * * *iret int Return code * * -36 = Projection not LCC * ** * * Log: * * S. Gilbert/NCEP 08/05 Calculations taken from GDS_LCC * * S. Gilbert/NCEP 03/06 Chngs to remove compiler warnings * ***********************************************************************/ { int ier; double rlon, rlov, phi1, phi2, trult1, trult2; double sign, rnx, rny, psi1, psi2; double rlat1, rlon1, rlat2, rlon2, clon; double re, cc, tan1, tan2, dlon1, dlon2; double x1, y1, x2, y2, alfa, dx, dy; /*---------------------------------------------------------------------*/ *iret = 0; /* * ensure grid navigation block is LCC */ if ( strncmp( (char *)(navblk+1), "LCC", 3) != 0 ) { *iret=-36; ER_WMSG("GB", iret, (char *)(navblk+1), &ier, 2, 4 ); } /* * Compute the grid increments. */ rnx=navblk[4]; rny=navblk[5]; rlat1 = navblk[6]; rlon1 = navblk[7]; rlat2 = navblk[8]; rlon2 = navblk[9]; phi1 = navblk[10]; rlov = navblk[11]; phi2 = navblk[12]; if ( fabs(phi1) > fabs(phi2) ) { trult1 = phi1; trult2 = phi2; if ( phi1 > 0.0 ) sign = -1.0; else sign = 1.0; } if ( fabs(phi2) > fabs(phi1) ) { trult1 = phi2; trult2 = phi1; if ( phi2 > 0.0 ) sign = -1.0; else sign = 1.0; } else { trult1 = phi1; trult2 = phi2; if ( phi1 > 0.0 ) sign = -1.0; else sign = 1.0; } rlat1 = rlat1 * DTR / 2.; rlat2 = rlat2 * DTR / 2.; rlon1 = rlon1 * DTR; rlon2 = rlon2 * DTR; clon = rlov * DTR; /* * Compute the cone constant */ psi1 = HALFPI + sign * phi1 * DTR; psi2 = HALFPI + sign * phi2 * DTR; if ( G_DIFF (phi1, phi2) ) cc = cos ( psi1 ); else { cc = log ( sin ( psi2 ) / sin ( psi1 ) ); cc = cc / log ( tan ( psi2 / 2. ) / tan ( psi1 / 2. ) ); } re = RADIUS / cc; tan1 = pow ( tan ( PI4TH + sign * rlat1 ) , cc); tan2 = pow ( tan ( PI4TH + sign * rlat2 ) , cc); dlon1 = ( rlon1 - clon ) * cc; dlon2 = ( rlon2 - clon ) * cc; x1 = re * tan1 * sin ( dlon1 ); y1 = sign * re * tan1 * cos ( dlon1 ); x2 = re * tan2 * sin ( dlon2 ); y2 = sign * re * tan2 * cos ( dlon2 ); alfa = sin ( psi1 ) / pow( tan ( psi1 / 2. ) , cc ); dx = ( x2 - x1 ) * alfa / ( rnx - 1. ); dy = ( y2 - y1 ) * alfa / ( rny - 1. ); /* * Set Grid Definition Template */ igdtmpl[0] = 1; /* Earth Assumed Spherical */ igdtmpl[1] = 0; /* Radius scale factor */ igdtmpl[2] = G_NINT( RADIUS ); /* Radius of Earth */ igdtmpl[3] = 0; /* Oblate info n/a */ igdtmpl[4] = 0; /* Oblate info n/a */ igdtmpl[5] = 0; /* Oblate info n/a */ igdtmpl[6] = 0; /* Oblate info n/a */ igdtmpl[7] = G_NINT( navblk[4] ); /* Kx */ igdtmpl[8] = G_NINT( navblk[5] ); /* Kx */ igdtmpl[9] = G_NINT(navblk[6]*1000000.0); /* Lat of 1st grid point */ rlon = navblk[7]; if ( rlon < 0.0 ) rlon += 360.0; igdtmpl[10] = G_NINT(rlon*1000000.0); /* Lon of 1st grid point */ igdtmpl[11] = 8; /* Res and Comp flags */ igdtmpl[12] = G_NINT(trult1*1000000.0); /* LaD */ rlov = navblk[11]; if ( rlov < 0.0 ) rlov += 360.0; igdtmpl[13] = G_NINT(rlov*1000000.0); /* LoV */ igdtmpl[14] = G_NINT( dx*1000.0 ); /* Dx */ igdtmpl[15] = G_NINT( dy*1000.0 ); /* Dy */ if ( sign < 0.0 ) igdtmpl[16] = 0; else igdtmpl[16] = 128; /* Projection center flag */ igdtmpl[17] = 64; /* Scanning mode */ igdtmpl[18] = G_NINT( trult1*1000000.0); /* Lat intrsect 1 */ igdtmpl[19] = G_NINT( trult2*1000000.0); /* Lat intrsect 2 */ igdtmpl[20] = -90000000; /* Lat of South Pole */ igdtmpl[21] = 0; /* Lon of South Pole */ }
void gb2_gdtpstr( float *navblk, int *igdtmpl, int *iret ) /************************************************************************ * gb2_gdtpstr * * * * This routine converts a STR Gempak grid navigation block to a * * GRIB2 Grid Definition Template 3.20. * * * * gb2_gdtpstr ( navblk, igdtmpl, iret ) * * * * Input parameters: * * *navblk float Decoded GRIB2 structure * * * * Output parameters: * * *igdtmpl int GDT 3.20 values * * *iret int Return code * * -36 = Projection not STR * ** * * Log: * * S. Gilbert/NCEP 08/05 Calculations taken from GDS_STR * * S. Gilbert/NCEP 03/06 Chngs to remove compiler warnings * ***********************************************************************/ { double rlat1, rlon1, rlat2, rlon2, dx, dy, polat, rlov; double rnx, rny, sign, clon, re, x1, y1, x2, y2; double tlat1, tlon1; double tan1, tan2, dlon1, dlon2; int ier; int nx, ny; /*---------------------------------------------------------------------*/ *iret = 0; /* * ensure grid navigation block is STR */ if ( strncmp( (char *)(navblk+1), "STR", 3) != 0 ) { *iret=-36; er_wmsg("GB", iret, (char *)(navblk+1), &ier, 2, 4 ); } nx = G_NINT(navblk[4]); ny = G_NINT(navblk[5]); rlat1 = navblk[6]; rlon1 = navblk[7]; rlat2 = navblk[8]; rlon2 = navblk[9]; polat = navblk[10]; rlov = navblk[11]; /* * compute the grid increments */ if ( polat > 0.0 ) sign = -1.0; else sign = 1.0; rnx = navblk[4]; rny = navblk[5]; tlat1 = rlat1 * DTR / 2.; rlat2 = rlat2 * DTR / 2.; tlon1 = rlon1 * DTR; rlon2 = rlon2 * DTR; clon = rlov * DTR; re = RADIUS; tan1 = tan ( PI4TH + sign * tlat1 ); tan2 = tan ( PI4TH + sign * rlat2 ); dlon1 = tlon1 - clon; dlon2 = rlon2 - clon; x1 = re * tan1 * sin ( dlon1 ); y1 = sign * re * tan1 * cos ( dlon1 ); x2 = re * tan2 * sin ( dlon2 ); y2 = sign * re * tan2 * cos ( dlon2 ); dx = ( x2 - x1 ) * 1.8660254 / ( rnx - 1. ); dy = ( y2 - y1 ) * 1.8660254 / ( rny - 1. ); /* * Set Grid Definition Template */ igdtmpl[0] = 1; /* Earth Assumed Spherical */ igdtmpl[1] = 0; /* Radius scale factor */ igdtmpl[2] = G_NINT(RADIUS); /* Radius of Earth */ igdtmpl[3] = 0; /* Oblate info n/a */ igdtmpl[4] = 0; /* Oblate info n/a */ igdtmpl[5] = 0; /* Oblate info n/a */ igdtmpl[6] = 0; /* Oblate info n/a */ igdtmpl[7] = nx; /* Kx */ igdtmpl[8] = ny; /* Kx */ igdtmpl[9] = G_NINT(rlat1*1000000.0); /* Lat of 1st grid point */ if ( rlon1 < 0.0 ) rlon1 += 360.0; igdtmpl[10] = G_NINT(rlon1*1000000.0); /* Lon of 1st grid point */ igdtmpl[11] = 56; /* Res and Comp flags */ igdtmpl[12] = 60000000; /* Lat where Dx,Dy true */ if ( rlov < 0.0 ) rlov += 360.0; igdtmpl[13] = G_NINT(rlov*1000000.0); /* Lon of Orientation */ igdtmpl[14] = G_NINT(dx*1000.0); /* Dx */ igdtmpl[15] = G_NINT(dy*1000.0); /* Dy */ igdtmpl[16] = 0; if ( polat < 0.0 ) igdtmpl[16] = 128; /* Projection center flag */ igdtmpl[17] = 64; /* Scanning mode */ }
void df_nmax ( int *iret ) /************************************************************************ * df_nmax * * * * This subroutine computes NMAX (S,ROI), the neigborhood maximum * * value of a scalar field (S) within some radius of influence * * (ROI; meters). Masking could be used [e.g., SGT(S1,S2)] to subset * * and filter the grid beforehand to allow for faster processing. * * * * df_nmax ( iret ) * * * * Output parameters: * * *iret int Return code * * As for DG_GETS * ** * * Log: * * C. Melick/SPC 06/12 * ************************************************************************/ { int num1, num2, num3, num, kxd, kyd, ksub1, ksub2, zero, indx, ier; int ixmscl, iymscl, jgymin, jgymax, jgxmin, jgxmax, idglat, idglon; int row, col, ibeg, iend, jbeg, jend, ibox, jbox, boxindx, nval; float gddx, gddy, gdspdx, gdspdy, radius; float *gnum1, *gnumn, *gkxms, *gkyms, *gnumroi, *glat, *glon, *dist; /*----------------------------------------------------------------------*/ *iret = 0; zero = 0; dg_ssub ( iret ); /* * Compute map scale factors. */ dg_mscl ( iret ); if ( *iret != 0 ) return; /* * Query DGCMN.CMN idglat/idglon. */ nval = 1; dg_iget ( "IDGLAT", &nval, &idglat, iret ); if ( *iret != 0 ) return; dg_iget ( "IDGLON", &nval, &idglon, iret ); if ( *iret != 0 ) return; /* * Get the grids from the stack. */ dg_gets ( &num1, iret ); if ( *iret != 0 ) return; dg_gets ( &num2, iret ); if ( *iret != 0 ) return; /* * Get a new grid number. */ dg_nxts ( &num3, iret ); if ( *iret != 0 ) return; dg_nxts ( &num, iret ); if ( *iret != 0 ) return; dg_qmsl ( &ixmscl, &iymscl, &gddx, &gddy, &ier ); dg_qbnd ( &jgxmin, &jgxmax, &jgymin, &jgymax, &ier ); dg_getg ( &num1, &gnum1, &kxd, &kyd, &ksub1, &ksub2, &ier ); dg_getg ( &num, &gnumn, &kxd, &kyd, &ksub1, &ksub2, &ier ); dg_getg ( &ixmscl, &gkxms, &kxd, &kyd, &ksub1, &ksub2, &ier ); dg_getg ( &iymscl, &gkyms, &kxd, &kyd, &ksub1, &ksub2, &ier ); dg_getg ( &num2, &gnumroi, &kxd, &kyd, &ksub1, &ksub2, &ier ); dg_getg ( &idglat, &glat, &kxd, &kyd, &ksub1, &ksub2, &ier ); dg_getg ( &idglon, &glon, &kxd, &kyd, &ksub1, &ksub2, &ier ); dg_getg ( &num3, &dist, &kxd, &kyd, &ksub1, &ksub2, &ier ); radius = gnumroi[0]; /* QC check on lower and upper bounds of radius of influence. */ if ( radius < 0 ) { radius = 0.0; printf ("\n WARNING : RADIUS value less than zero. " "Resetting to zero.\n"); } if ( radius > 0.5*gddx*(float)(kxd)) { radius = 0.5*gddx*(float)(kxd); printf ("\n WARNING : RADIUS value too high. " "Resetting to half the distance in X (%f meters).\n",radius); } /* * Loop over all grid points to initialize output grid. */ for ( row = jgymin; row <= jgymax; row++ ) { for ( col = jgxmin; col <= jgxmax; col++ ) { indx=(row-1)*kxd+(col-1); if ( ERMISS ( gnum1[indx] ) ) { gnumn[indx] = RMISSD; } else { gnumn[indx] = gnum1[indx]; } } } /* * Loop over all grid points to determine neighborhood maximum for each grid point. */ for ( row = jgymin; row <= jgymax; row++ ) { for ( col = jgxmin; col <= jgxmax; col++ ) { indx=(row-1)*kxd+(col-1); if ( ! ERMISS ( gnum1[indx] ) ) { gdspdx= gddx / gkxms[indx]; gdspdy= gddy / gkyms[indx]; /* Constructing box for each grid point */ ibeg = col- G_NINT(radius / gdspdx); iend = col+ G_NINT(radius / gdspdx); jbeg = row- G_NINT(radius / gdspdy); jend = row+ G_NINT(radius / gdspdy); if (ibeg < jgxmin) { ibeg = jgxmin; } if (iend > jgxmax) { iend = jgxmax; } if (jbeg < jgymin) { jbeg = jgymin; } if (jend > jgymax) { jend = jgymax; } for ( ibox = ibeg; ibox <= iend; ibox++ ) { for ( jbox = jbeg; jbox <= jend; jbox++ ) { boxindx=(jbox-1)*kxd+(ibox-1); if ((glat[indx] == glat[boxindx]) && (glon[indx] == glon[boxindx])) { dist[boxindx]=0.0; } else { /* Great Circle Distance calculation */ dist[boxindx] = acos(sin(glat[boxindx])*sin(glat[indx]) + cos(glat[boxindx])*cos(glat[indx])*cos((glon[boxindx])-(glon[indx]))); dist[boxindx] = RADIUS * dist[boxindx]; } /* Check maximum value if neighboring point is defined and within radius of influence. */ if ( (dist[boxindx] <= radius) && (! ERMISS ( gnum1[boxindx] ) ) ) { if ( gnum1[boxindx] > gnumn[indx] ) { gnumn[indx] = gnum1[boxindx]; } } } } for ( ibox = ibeg; ibox <= iend; ibox++ ) { for ( jbox = jbeg; jbox <= jend; jbox++ ) { boxindx=(jbox-1)*kxd+(ibox-1); /* Spreading the response around to surrounding undefined values */ if ( ERMISS ( gnum1[boxindx] ) ) { if (dist[boxindx] <= radius) { if ( ERMISS ( gnumn[boxindx] ) ) { gnumn[boxindx] = gnumn[indx]; } else if ( gnum1[indx] > gnumn[boxindx] ) { gnumn[boxindx] = gnum1[indx]; } } } } } } } } /* * Make a name of the form 'NMAX'//S and update header; * update stack. */ dg_updh ( "NMAX", &num, &num1, &num2, iret ); dg_puts ( &num, iret ); dg_esub ( &num, &zero, &zero, &zero, &ier ); if ( ier != 0 ) *iret = ier; return; }
void clo_ddenc ( char *type, int format, float lat, float lon, char *str, int *iret ) /************************************************************************ * clo_ddenc * * * * This function returns gets the string for the seek and location * * structure indicating which entry matches the input CLO name for the * * given latitude and longitude. The format code is in a 4-5 digit * * format (Eg. 5212 or 10212). The columns are formatted as follows : * * * * * * ROUNDING UNITS DIRECTION DISPLAY * * * * 5 - nearest 5 0 - omit 0 - omit 0 - degrees * * 10 - nearest 10 1 - NM 1 - 16 point 1 - decimal/minutes * * 2 - SM 2 - degrees 2 - 1st column * * 3 - KM 4 - 3rd column * * * * For DISPLAY, the 1st column is usually the station id and the 3rd * * column is the name of the station, city or county. * * * * clo_ddenc ( type, format, lat, lon, str, iret) * * * * Input parameters: * * *type char Name of CLO parameter * * format int Indicator of format to use * * lat float Latitude point * * lon float Longitude point * * * * Output parameters: * * *str char Character string location * * *iret int Return value * * = < 0 - String not created * * * ** * * Log: * * A. Hardy/GSC 01/00 Create * * A. Hardy/GSC 01/00 Added new format display option * * A. Hardy/GSC 01/00 Added length chk of str;changed rounding* * A. Hardy/GSC 02/00 modified for all variations of formats * * A. Hardy/GSC 02/00 reworked string display; city locations * * D.W.Plummer/NCEP 8/00 changes for clo_ redesign * * A. Hardy/GSC 8/00 renamed from clo_format * * T. Piper/GSC 3/01 Fixed IRIX6 compiler warnings * * D.W.Plummer/NCEP 8/01 Repl clo_bqinfo w/ cst_gtag * * D.W.Plummer/NCEP 6/05 Tens digit sets # decimals for lat,lon * ***********************************************************************/ { int idist, icmp, nh, ier; int ilat, ilon, imnt, imnn, isit, isin; char stn[80], idx[80], *pidx, sdir[4]; float dist, dir; int ione, itens, ihund, irnd, which, inlen; int isln, iwidth, ilftovr; char sdirc[5], sdist[5]; char info[128], fmt[20]; /*---------------------------------------------------------------------*/ *iret = 0; strcpy ( str, "NULL" ); iwidth = 16; /* * Parse out format into it's components. */ ione = format % 10; itens = (int) (format/10) % 10; ihund = (int) (format/100) % 10; irnd = format / 1000; /* * Check one's place for lat-lon or deg-min. */ if ( ione == 0 ) { /* show lat/lon */ /* * Tens digit controls the number of decimal digits for the * lat,lon display. The default is 2 digits. */ if ( itens == 0 ) itens = 2; sprintf(fmt,"%%.%df, %%.%df", itens, itens ); sprintf(str, fmt, lat, lon); } else if ( ione == 1 ) { /* show lat/lon as deg-min */ isit = ( lat < 0.0F ) ? '-' : ' '; ilat = (int) G_ABS ( lat ); imnt = G_NINT ( ( G_ABS(lat) - (float)ilat ) * 60.0F ); if ( imnt >= 60 ) { imnt = imnt % 60; ilat += 1; } isin = ( lon < 0.0F ) ? '-' : ' '; ilon = (int) G_ABS ( lon ); imnn = G_NINT ( ( G_ABS(lon) - (float)ilon ) * 60.0F ); if ( imnn >= 60 ) { imnn = imnn % 60; ilon += 1; } sprintf ( str, "%c%3d:%02d, %c%3d:%02d", isit, ilat, imnt, isin, ilon, imnn ); } else { /* show city/county/stn */ which = clo_which ( type ); if ( clo.loc[which].format == 1 ) { /* show bound */ clo_tqbnd ( type, lat, lon, idx, &ier); pidx = idx; /* * Find and save the county FIPS id. */ if ( ione == 2) { if (strcmp ( pidx,"-") != 0 ) { clo_bginfo ( type, 0, info, &ier ); cst_gtag ( "FIPS", info, "?", str, &ier ); } else { cst_split (pidx, ' ', 14, str, &ier); } } if ( ione == 4) { /* Save the bound name */ cst_split (pidx, ' ', 14, str, &ier); } } else { if ( clo.loc[which].format == 0 ) { /* show station */ /* * get station ID, distance and direction. */ clo_tdirect ( type, lat, lon, stn, &dist, &dir, &ier ); if ( ione == 4 ) { /* * Replace station ID w/ station name. */ clo_tgnm ( type, 1, sizeof(stn), &nh, stn, &ier ); } } if ( ihund == 0 ) { strcpy ( sdirc, "" ); } else { if ( ihund == 1 ) { /* get nautical miles */ dist *= M2NM; } else if ( ihund == 2 ) { /* get statute miles */ dist *= M2SM; } else if ( ihund == 3 ) { /* get kilometers */ dist /= 1000.0F; } if ( irnd > 0 ) { idist = G_NINT ( dist / (float)irnd ) * irnd; sprintf ( sdirc, "%i ", idist); } else if ( irnd < 0 ) { irnd = 1; idist = G_NINT ( dist / (float)irnd ) * irnd; sprintf ( sdirc, "%i ", idist); } else if ( irnd == 0 ) { strcpy ( sdirc, "" ); } } if ( itens == 0 ) { /* omit the direction */ strcpy ( sdist, "" ); } else { if ( itens == 1 ) { /* use 16 point dir. */ clo_compass ( &dir, sdir, &icmp, &ier ); sprintf ( sdist, "%s", sdir ); } else if ( itens == 2 ) { /* use degrees */ sprintf ( sdist, "%.0f", dir ); } } sprintf(str, "%s %s",sdirc, sdist); /* * If the stn name is longer than 4 chars, print */ inlen = (int)strlen(stn); isln = (int)strlen(str); ilftovr = iwidth - isln; if (inlen > 4 ) { sprintf ( str, "%*s %.*s", isln, str, ilftovr, stn ); } else { sprintf ( str, "%s %3s", str, stn ); } if ( (ihund == 0 ) && ( itens == 0 ) ) { sprintf ( str, "%.*s", ilftovr, stn ); } } } if ( strcmp ( str, "NULL") != 0 ) *iret = -1; }
void gb2_vcrd ( char *wmolvltbl, char *lcllvltbl, Gribmsg *cmsg, int *levels, int *vcord, int *iret ) /************************************************************************ * gb2_vcrd * * * * This routine computes the vertical coordinate level/layer values * * from the GRIB2 PDS. Also, the GEMPAK vertical coordinate type is * * obtained from the appropriate GRIB2 vertical coordinate table. * * * * If either wmolvltbl or lcllvltbl are NULL, the default tables are * * read. * * * * gb2_vcrd ( wmolvltbl, lcllvltbl, cmsg, levels, vcord, iret ) * * * * Input parameters: * * *wmolvltbl char WMO vertical coordinate table * * *lcllvltbl char Local vertical coordinate table * * *cmsg struct Gribmsg GRIB2 message structure * * * * Output parameters: * * levels[2] int lower/upper level/layer values * * *vcord int GEMPAK vertical goordinate type * * *iret int return code * * -27 = Unrecognized PDT number * ** * * Log: * * S. Gilbert/NCEP 11/04 * * S. Gilbert/NCEP 10/05 Use new routines to read tables * * S. Gilbert/NCEP 03/06 Chngs to remove compiler warnings * ***********************************************************************/ { int ret, ier, lvl1, lvl2, iver, lclver; G2level g2lev; G2lvls *g2lvltbl; char vparm[12], ctemp[20]; float rlevel[2]; double sfact; /*---------------------------------------------------------------------*/ *iret = 0; /* * Get Level into from vertical coordinate table(s). */ iver=cmsg->gfld->idsect[2]; lclver=cmsg->gfld->idsect[3]; lvl1=cmsg->gfld->ipdtmpl[9]; lvl2=cmsg->gfld->ipdtmpl[12]; if ( ( lvl1 < 192 || lvl1 == 255 ) && ( lvl2 < 192 || lvl2 == 255 ) ) { /* * Get WMO vertical coordinate table. */ gb2_gtwmolvltbl( wmolvltbl, iver, &g2lvltbl, &ier); if ( ier == 0 ) { /* * Get Level into from WMO vertical coordinate table. */ gb2_sklvl( lvl1, lvl2, g2lvltbl, &g2lev, &ier); } } else { /* * Get Local vertical coordinate table. */ gb2_gtlcllvltbl( lcllvltbl, cmsg->origcntr, lclver, &g2lvltbl, &ier); if ( ier == 0 ) { /* * Get Level into from Local vertical coordinate table. */ gb2_sklvl( lvl1, lvl2, g2lvltbl, &g2lev, &ier); } } if ( ier != 0 ) { *iret=ier; if ( ier == -30 ) { sprintf(ctemp,"%d|%d", lvl1, lvl2); er_wmsg("GB",&ier,ctemp,&ret,2,strlen(ctemp)); } return; } /* * Calculate GEMPAK vertical coordinate type */ lv_cord ( g2lev.abbrev, vparm, vcord, &ier, 4, 12); if ( ier != 0 ) { *iret=-7; return; } /* * Extract vertical coordinate levels from GRIB2 PDS */ gb2_vlev ( cmsg->gfld, rlevel, &ier ); if ( ier != 0 ) { *iret=ier; return; } /* * Scale level values by scale factor found in vertical * coordinate table. */ sfact=pow((double)10.0,g2lev.scale); levels[0] = G_NINT( rlevel[0] * sfact ); if ( G_DIFF ( -1.0, rlevel[1] ) ) { levels[1] = -1; } else { levels[1] = G_NINT( rlevel[1] * sfact ); } if ( lvl1 == 1 ) { /* Surface */ levels[0] = 0; levels[1] = -1; } }
void dg_g2gc ( const int *inttyp, const int *glbwi, const int *kxi, const int *kyi, const float *grdi, const int *kxo, const int *kyo, float *gixo, float *giyo, float *grdo, int *iret ) /************************************************************************ * dg_g2gc * * * * This subroutine remaps cosines of data from one grid to another grid.* * * * A globe-wrapping grid must be configured so that the last column * * and first column are identical. * * * * If INTTYP=0, the code determines automatically whether to use a * * simple bi-linear interpolation or an area average preserving re- * * mapping of data. The method is determined locally and may vary * * across the grid. The transition to area average preserving remap- * * ping occurs when one output grid box contains approximately four (4) * * or more input grid boxes. Since bilinear interpolation preserves * * the area average when grid resolutions are comparable or when the * * input grid is coarse compared to the output grid, this method always * * preserves area averages. * * * * If INTTYP=1, the code performs nearest neighbor assignment. * * If INTTYP=2, the code performs only bi-linear interpolation. * * * * dg_g2gc ( inttyp, glbwi, kxi, kyi, grdi, kxo, kyo, gixo, giyo, grdo, * * iret ) * * * * Input parameters: * * *inttyp const int Remapping type * * = 0 area average preserving * * = 1 nearest point assignment * * = 2 bi-linear interpolation * * *glbwi const int Flg for globe-wrapping input grd* * *kxi const int Number of x pts on input grid * * *kyi const int Number of y pts on input grid * * *grdi const float Input grid * * *kxo const int Number of x pts on output grid * * *kyo const int Number of y pts on output grid * * *gixo flaot Input grd rltv x on output grid * * *giyo float Input grd rltv y on output grid * * * * Output parameters: * * *grdo float Output grid of results * * *iret int Return code * * 0 = normal return * * -68 = INTTYP is not valid * * -69 = grid rel position error * ** * * Log: * * K. Brill/HPC 3/04 Created from DG_G2GI * * K. Brill/HPC 4/04 IF (k==0) k=1; add .005 to rad * * R. Tian/SAIC 2/06 Recoded from Fortran * ************************************************************************/ { float rkio2, rdtst, xchk, rad2m, dx, dy, d2, x, y, xi, omx, omy, rad, rad2, radx2, sum, sumw, ri, r2, dr2, dr22, wt, tmp; int ir[4], jr[4], kio2, ityp, cidx, cidx1, i, j, k, io, jo, in, jn, idx1, idx2, idx3, idx4, ip, ib, jb, ie, je, ii, jj, jdif, npts; int rflct; /*----------------------------------------------------------------------*/ *iret = 0; if ( (*inttyp) < 0 || (*inttyp) > 2 ) { *iret = -68; return; } kio2 = (*kxi) / 2; rkio2 = (float)kio2; rdtst = 4. / PI; if ( (*inttyp) == 0 && (*glbwi) == G_TRUE && ( (*kxi) % 2 ) == 1 ) { /* * Check to relect points across the pole of a global grid. * All points along bottom and top rows must be identical. */ rflct = G_TRUE; for ( j = 1; j <= (*kyi); j += (*kyi) - 1 ) { cidx = (j - 1 ) * (*kxi); xchk = cos ( grdi[cidx] ); i = 2; while ( i <= (*kxi) && rflct == G_TRUE ) { cidx = ( j - 1 ) * (*kxi) + i - 1; rflct = ( ! ERMISS ( grdi[cidx] ) ) ? G_TRUE : G_FALSE; if ( rflct == G_TRUE ) { if ( G_ABS ( xchk - cos ( grdi[cidx] ) ) < RDIFFD ) { rflct = G_FALSE; } } i++; } } } else { rflct = G_FALSE; } /* * Loop over all output grid points. */ rad2m = -9999.; for ( jo = 1; jo <= (*kyo); jo++ ) { for ( io = 1; io <= (*kxo); io++ ) { cidx = ( jo - 1 ) * (*kxo) + io - 1; grdo[cidx] = RMISSD; if ( ERMISS ( gixo[cidx] ) || ERMISS ( giyo[cidx] ) ) { ityp = 2; } else if ( (*inttyp) == 1 ) { /* * Assign value at nearest point. */ ityp = 2; in = G_NINT ( gixo[cidx] ); if ( (*glbwi) == G_TRUE ) { if ( in > (*kxi) ) in = in - (*kxi) + 1; if ( in < 1 ) in = in + (*kxi) - 1; } jn = G_NINT ( giyo[cidx] ); if ( in >= 1 && in <= (*kxi) && jn >= 1 && jn <= (*kyi) ) { /* * Nearest point value assignment. */ cidx1 = ( jn - 1 ) * (*kxi) + in - 1; grdo[cidx] = cos ( grdi[cidx1] ); } } else if ( (*inttyp) == 2 ) { ityp = 1; } else { ityp = 0; /* * Get radius in input grid units of the circle * circumscribing the the diamond formed by the * four points closest to the current point on * the output grid. */ rad2 = -1.1E31; ir[0] = io - 1; jr[0] = jo; ir[1] = io; jr[1] = jo - 1; ir[2] = io + 1; jr[2] = jo; ir[3] = io; jr[3] = jo + 1; for ( ip = 0; ip < 4; ip++ ) { cidx1 = ( jr[ip] - 1 ) * (*kxo) + ir[ip] - 1; if ( ir[ip] >= 1 && ir[ip] <= (*kxo) && jr[ip] >= 1 && jr[ip] <= (*kyo) && ! ERMISS ( gixo[cidx1] ) && ! ERMISS ( giyo[cidx1] ) ) { dx = gixo[cidx1] - gixo[cidx]; if ( (*glbwi) == G_TRUE && G_ABS (dx) > rkio2 ) { /* * Skip this point. */ } else if ( G_ABS (dx) > rkio2 ) { *iret = -69; return; } else { dy = giyo[cidx1] - giyo[cidx]; d2 = dx * dx + dy * dy; rad2 = G_MAX ( d2, rad2 ); } } } /* * Since RAD2 is the square of the radius of the * circle circumscribing the output grid diamond * in input grid units, multiply by .5 to get the * the square of the radius of the inscribed circle. * This circle circumscribes the output grid box. */ if ( rad2 > -1.0E30 ) { rad2 *= .5; /* * If the radius is much larger than that at the * adjacent point, then reduce it. */ if ( rad2m > 0.0 && rad2 > 1.5 * rad2m ) { rad2 = 1.5 * rad2m; } rad2m = rad2; } else { rad2m = -9999.; } /* * If the squared radius of the inscribed circle is * small enough (4/PI), then there are less than four * input grid boxes per output grid box and linear * interpolation will suffice. */ if ( rad2 < rdtst ) { ityp = 1; } } if ( ityp == 1 ) { /* * Do bi-linear interpolation. */ i = (int)gixo[cidx]; if ( (*glbwi) == G_TRUE ) { if ( i >= (*kxi) ) { i = i - (*kxi) + 1; xi = gixo[cidx] - (float)(*kxi) + 1; } else if ( i < 1 ) { i = i + (*kxi) - 1; xi = gixo[cidx] + (float)(*kxi) - 1; if ( gixo[cidx] < 0.0 ) i--; } else { xi = gixo[cidx]; } } else { xi = gixo[cidx]; } j = (int)giyo[cidx]; if ( i >= 1 && i <= (*kxi) && j >= 1 && j <= (*kyi) ) { if ( i == (*kxi) ) i--; if ( j == (*kyi) ) j--; idx1 = ( j - 1 ) * (*kxi) + i - 1; idx2 = ( j - 1 ) * (*kxi) + i; idx3 = j * (*kxi) + i - 1; idx4 = j * (*kxi) + i; if ( ! ERMISS ( grdi[idx1] ) && ! ERMISS ( grdi[idx2] ) && ! ERMISS ( grdi[idx3] ) && ! ERMISS ( grdi[idx4] ) ) { x = xi - (float)i; y = giyo[cidx] - (float)j; omx = 1. - x; omy = 1. - y; grdo[cidx] = ( cos ( grdi[idx1] ) * omx + cos ( grdi[idx2] ) * x ) * omy + ( cos ( grdi[idx3] ) * omx + cos ( grdi[idx4] ) * x ) * y; } } } else if ( ityp == 0 ) { /* * Do area average preserving interpolation. * * This integer truncation acts to pull the * output grid box circumscribing circle in * just a bit. */ tmp = sqrt ( rad2 ); k = (int)tmp; if ( k == 0 ) k = 1; /* * Reset rad2 accordingly. */ rad = (float)k + .005; rad2 = rad * rad; radx2 = 1. / ( 2. * rad ); ib = G_NINT ( gixo[cidx] ) - k; jb = G_NINT ( giyo[cidx] ) - k; ie = G_NINT ( gixo[cidx] ) + k; je = G_NINT ( giyo[cidx] ) + k; sum = 0.0; sumw = 0.0; npts = 0; for ( j = jb; j <= je; j++ ) { for ( i = ib; i <= ie; i++ ) { jj = j; ii = i; ri = (float)i; if ( (*glbwi) == G_TRUE ) { if ( i > (*kxi) ) ii = i - (*kxi) + 1; if ( i < 1 ) ii = i + (*kxi) - 1; } dx = ri - gixo[cidx]; dy = (float)j - giyo[cidx]; r2 = dx * dx + dy * dy; if ( rflct == G_TRUE ) { if ( j > (*kyi) ) { jdif = j - (*kyi); jj = (*kyi) - jdif; if ( ii <= kio2 ) { ii += kio2; } else { ii -= kio2; } } else if ( j < 1 ) { jdif = 1 - j; jj = 1 + jdif; if ( ii <= kio2 ) { ii += kio2; } else { ii -= kio2; } } } if ( r2 <= rad2 ) { if ( ii >= 1 && ii <= (*kxi) && jj >= 1 && jj <= (*kyi) ) { cidx1 = ( jj - 1 ) * (*kxi) + ii - 1; if ( ! ERMISS (grdi[cidx1] ) ) { /* * Compute a weighting factor based * on an estimate of how much of * the area of the input grid box * is contributing to the area * covered by the output grid box. * The criterion is (rad-r) < .5. * Using the approximation that * rad ~ r, then (rad2-r2) is nearly * equal to 2*rad(rad-r). Substi- * tute into above inequality and * rearrange to get this criterion: * (rad2-r2)**2<rad2. The weight is * either 1 or [.5+(rad2-r2)/rad*2]. * The .5 is added on because a * point on the circle has about * half of its area inside. */ dr2 = rad2 - r2; dr22 = dr2 * dr2; if ( dr22 < rad2 ) { wt = .5 + dr2 * radx2; } else { wt = 1.0; } sum += wt * cos ( grdi[cidx1] ); sumw += wt; npts++; } } } } } if ( sumw >= 2.0 && npts >= 4 ) { /* * The value 2.0 is used as the criterion here * because at least 4 points must contribute * at least a half. */ grdo[cidx] = sum / sumw; } else { /* * Perform linear interpolation, which itself * preserves area averages when grid resolutions * are comparable. */ i = (int)gixo[cidx]; if ( (*glbwi) == G_TRUE ) { if ( i >= (*kxi) ) { i = i - (*kxi) + 1; xi = gixo[cidx] - (float)(*kxi) + 1; } else if ( i < 1 ) { i = i + (*kxi) - 1; xi = gixo[cidx] + (float)(*kxi) - 1; if ( gixo[cidx] < 0.0 ) i--; } else { xi = gixo[cidx]; } } else { xi = gixo[cidx]; } j = (int)giyo[cidx]; if ( i >= 1 && i <= (*kxi) && j >= 1 && j <= (*kyi) ) { if ( i == (*kxi) ) i--; if ( j == (*kyi) ) j--; idx1 = ( j - 1 ) * (*kxi) + i - 1; idx2 = ( j - 1 ) * (*kxi) + i; idx3 = j * (*kxi) + i - 1; idx4 = j * (*kxi) + i; if ( ! ERMISS ( grdi[idx1] ) && ! ERMISS ( grdi[idx2] ) && ! ERMISS ( grdi[idx3] ) && ! ERMISS ( grdi[idx4] ) ) { x = xi - (float)i; y = giyo[cidx] - (float)j; omx = 1. - x; omy = 1. - y; grdo[cidx] = ( cos ( grdi[idx1] ) * omx + cos ( grdi[idx2] ) * x ) * omy + ( cos ( grdi[idx3] ) * omx + cos ( grdi[idx4] ) * x ) * y; } } } } } } return; }
void wsatim ( char *imgnam, int *xispace0, int *yispace0, int *xispace1, int *yispace1, int *ist, int *inum, int *iret ) /************************************************************************ * wsatim * * * * This subroutine displays satellite images for the GIF driver. * * It is capable of displaying raw satellite images and remapped images.* * * * wsatim ( imgnam, xispace0, yispace0, xispace1, yispace1, * * ist, inum, iret ) * * * * Input parameters: * * *imgnam char Name of image file * * *xispace0 int Left of image in plot coord * * *yispace0 int Top of image in plot coord * * *xispace1 int Right of image in plot coord * * *yispace1 int Bottom of image in plot coord * * *ist int Starting point of color table * * *inum int Number of colors * * * * Output parameters: * * *iret int Return code * * G_NORMAL = normal return * * G_NIMGFL = cannot open image file * * G_NFILENM = file name is too long (xslutf) * * G_NIMGCOL = not enough image colors * * G_NMEMRY = Memory allocation failure * * G_NIMCORD = invalid image coordinates * ** * * Log: * * G. Krueger/EAI 12/93 Modify xrest -> xsatim * * G. Krueger/EAI 02/93 Added simplified color alloc scheme * * S. Jacobs/NMC 3/94 Added std image max/min values * * S. Jacobs/NMC 7/94 General clean up * * C. Lin/EAI 7/94 Multi-window, multi-pixmap * * C. Lin/EAI 8/94 Take clrsalloc into xwcmn.h * * J. Cowie/COMET 8/94 Added byte swapping for image headers * * D. Himes/COMET 8/94 Return error code if xcaloc fails * * S. Jacobs/NMC 8/94 Updated calls to MV_SWP4 to send arrays * * S. Jacobs/NMC 9/94 Added more optional debug prints * * J. Cowie/COMET 11/94 Handle radar, use default LUT file * * S. Jacobs/NMC 1/95 Changed to use a radar colors array * * J. Cowie/COMET 1/95 Fixed index color mapping rounding bug * * J. Cowie/COMET 1/95 Added image subsetting * * C. Lin/EAI 3/95 Added clearing pixmap * * Used calloc() to clear image_data * * Error code; error handling * * Use ColorBanks structure * * Bug fix: all malloc() calls * * C. Lin/EAI 3/95 Take out normal coordinates input. * * Rewrite the program. * * C. Lin/EAI 9/95 Add G_ZEROCB check * * J. Cowie/COMET 10/95 Changed to use icbank value * * J. Nielsen-Gammon/TAMU2/96 Disabled pixmap clearing * * J. Nielsen-Gammon/TAMU12/96 Modified for GIF driver * * J. Nielsen-Gammon/TAMU9/98 Gempak 5.4 version * * T. Lee/GSC 7/00 Renamed x*.c to w*.c * * R. Curtis/EAI 8/00 Updated for NetCDF files * * S. Chiswell/Unidata 11/00 Updated for ZLIB compressed NIDS files * * R. Tian/SAIC 05/02 Modified to display fax image * * D.W.Plummer/NCEP 3/03 Changes for 10-bit GVAR imagery * * S. Danz/AWC 11/03 Changed to not clear background data * * A. Hardy/NCEP 4/04 Modified to display 10-bit VIS imagery * * T. Piper/SAIC 10/05 Dynamically allocate coltrans & rowtrans* * T. Piper/SAIC 1/06 Change *lenfil from long int to int * * T. Piper/SAIC 08/06 Moved byte swapping to crarea * * T. Piper/SAIC 11/06 Restore coltrans[0] back to original * * T. Piper/SAIC 03/07 Fixed flaw in row processing * * X. Guo/CWS 04/10 Added codes to support 94 product * * X. Guo/CWS 05/10 Added IFHINIDS to process 8 bit product * ***********************************************************************/ { int *coltrans, drange, element_size, ier, ii; int imghght, imgwdth, indx, isGVARRAW, iwdth; int linestart, ncolors, *rowtrans, ximage0; int ximage1, xloc, yimage0, yimage1, yloc; char dev[] = "GIF"; float *fpix, *tmpk; size_t imgsize; double dbltmp, doffset, imgratio, plotratio, ratio, sf_hght, sf_wdth; unsigned char datamap[256], *ddptr, *dptr; unsigned int col, linesize, newdim, *pix; unsigned int plothght, plotwdth, remainder, row, xhght, xwdth; /*---------------------------------------------------------------------*/ /* * Check the input for valid bounds. Then set the image dimensions. */ if (( imbot <= imtop ) || ( imrght <= imleft ) || ( *xispace1 <= *xispace0) || ( *yispace0 <= *yispace1 )) { *iret = G_NIMCORD; return; } imgwdth = (imrght - imleft) + 1; imghght = (imbot - imtop) + 1; /* * Initialize the image data arrays. */ csinit ( &ier ); /* * Read image data file if this is a new file. */ if ( strcmp ( lastimg.filename, imgnam ) != 0 ) { /* * Allocate image data space. */ imgsize = (size_t)(imnpix * imnlin * imdpth); if ( ( imgData != (unsigned char *)NULL ) && ( imgsize <= lastimg.imgsize ) ) { memset ( (unsigned char *)imgData, 0, imgsize ); } else { if ( imgData != (unsigned char *)NULL ) { free ( imgData ); } imgData = (unsigned char *) calloc ( imgsize, sizeof ( unsigned char ) ); if ( imgData == (unsigned char *)NULL ) { *iret = G_NMEMRY; return; } } /* * Get the image data for the type of image file format. */ switch ( imftyp ) { case IFAREA: /* Area file */ crarea ( imgnam, &ier ); break; case IFGINI: /* AWIPS GINI files */ crgini ( imgnam, &ier ); break; case IFNIDS: /* NIDS radar files */ case IFHINIDS: /*Higher Resolution NIDS radar files*/ crnids (imgnam, &ier ); break; case IFNOWR: /* WSI NOWRAD radar files */ crnowr ( imgnam, &ier ); break; case IFNCDF: /* NetCDF files */ crncdf ( imgnam, &ier ); break; case IFNEXZ: /* ZLIB NEXRAD files */ crnexz ( imgnam, &ier ); break; case IFNFAX: /* 6-bit FAX product files */ crnfax ( dev, imgnam, &ier ); break; case IFNEX2: /* NEXRAD Level2 files */ crnex2 ( imgnam, &ier ); break; default: /* Error in format */ ier = G_NIMGFMT; break; } /* * Check for error. Set this file as the 'last' one if OK. */ if ( ier != G_NORMAL ) { *iret = ier; return; } strcpy ( lastimg.filename, imgnam ); lastimg.imgsize = imgsize; } /* * Check image data range. */ if ( immxpx == immnpx ) { *iret = G_BADPXV; return; } /* * Request image area. Set image scaling. */ imgratio = (double)imghght / (double)imgwdth; if ( ( !G_DIFF(rmxysc, 1.0F) ) && ( rmxysc > MNSCAL ) ) { imgratio /= (double)rmxysc; } /* * Compute the plot area. */ plotwdth = (*xispace1 - *xispace0) + 1; plothght = (*yispace0 - *yispace1) + 1; plotratio = (double)plothght / (double)plotwdth; /* * Calculate final image size. * ( ximage0, ximage1, yimage0, yimage1 ) */ if ( plotratio > imgratio ) { /* * If the height to width of the space available for the image * is greater than the height to width of the image, width is * the limiting factor, and scale the height to keep the * appropriate aspect ratio. */ ximage0 = *xispace0; ximage1 = *xispace1; /* * Center the image in the plot area. */ newdim = (unsigned int)((double)plotwdth * imgratio); remainder = plothght - newdim; yimage0 = G_NINT ( (double)*yispace0 - (double)remainder / 2.0 ); yimage1 = G_NINT ( (double)*yispace1 + (double)remainder / 2.0 ); } else { /* * Otherwise, if the height to width of the space available for * the image is less than the height to width of the image, * height is the limiting factor, and scale the width to keep * the appropriate aspect ratio. */ yimage0 = *yispace0; yimage1 = *yispace1; /* * Center the image in the plot area. */ newdim = (unsigned int)((double)plothght / imgratio); remainder = plotwdth - newdim; ximage0 = G_NINT ( (double)*xispace0 + (double)remainder / 2.0 ); ximage1 = G_NINT ( (double)*xispace1 - (double)remainder / 2.0 ); } /* * Final image size. */ xwdth = (unsigned int)((ximage1 - ximage0) + 1); xhght = (unsigned int)((yimage0 - yimage1) + 1); /* * Construct the mapping from the image data to the final color * pixel index -- datamap[]. */ isGVARRAW = G_FALSE; if ( strcmp ( cmstyp, "GVAR" ) == 0 && strcmp ( cmcalb, "RAW" ) == 0 ) isGVARRAW = G_TRUE; /* * Compute image data range. */ if ( isGVARRAW != G_TRUE ) { dbltmp = pow (2.0, (double)(imdpth * 8) ); } else { /* * Treat GVAR RAW data as 0-255. * (10-bit GVAR count scaled to 8-bit brightness temperature) */ dbltmp = pow(2.0, 8.0); } drange = (int)dbltmp; ncolors = *inum; ratio = (double)(ncolors - 1) / (double)(immxpx - immnpx); /* * Compute offset for data mapping. */ doffset = (double)immnpx * ratio - 0.5; if ( imdpth < 2 || isGVARRAW == G_TRUE ) { /* * One byte data. */ for ( ii = 0; ii < drange; ii++ ) { if ( ii < immnpx ) datamap[ii] = 0; else if ( ii > immxpx ) datamap[ii] = *ist + ncolors - 1; else { if ( ! isGVARRAW == G_TRUE) indx = (int)((double)ii * ratio - doffset); else indx = (int)((double)(ii*(ncolors-1)) / (double)drange - doffset); datamap[ii] = *ist + indx; } } } /* * Fill the column translation array with incremental indices * into the original image columns with respect to the previous * column. Off-image values are set to -1. */ G_MALLOC(coltrans, int, xwdth, "coltrans"); sf_wdth = (double)(imgwdth - 1) / (double)(xwdth - 1); for ( col = 0; col < xwdth; col++ ) { coltrans[col] = (imleft - 1) + (int)(sf_wdth * (double)col + 0.5); if ( coltrans[col] < 0 || coltrans[col] >= imnpix ) { coltrans[col] = -1; } else if ( col != 0 && coltrans[col-1] != -1 ) { coltrans[col] -= (imleft - 1) + (int)(sf_wdth*(double)(col-1) + 0.5); } } /* * Fill the row translation array with indices into the * original image rows. Set off-image values to -1. */ G_MALLOC(rowtrans, int, xhght, "rowtrans"); sf_hght = (double)(imghght - 1) / (double)(xhght -1); for ( row = 0; row < xhght; row++ ) { rowtrans[row] = (imtop - 1) + (int)(sf_hght * (double)row + 0.5); if ( rowtrans[row] < 0 || rowtrans[row] >= imnlin ) { rowtrans[row] = -1; } } /* * Construct the final image for display. */ *iret = G_NORMAL; element_size = imdpth; linesize = (unsigned int)(imnpix * element_size); /* * Allocate memory for one row/line of pixel data. */ G_MALLOC(pix, unsigned int, xwdth, "pix"); if ( imdpth == 2 && isGVARRAW == G_TRUE ) { G_MALLOC(tmpk, float, xwdth, "tmpk"); G_MALLOC(fpix, float, xwdth, "fpix"); }
void vfwsaw ( int *iret ) /************************************************************************ * vfwsaw * * * * This program opens, creates and closes the Weather Watch SAW text * * product file. * * * * vfwsaw ( iret ) * * * * Input parameters: * * * * Output parameters: * * *iret int Return Code * * * ** * * Log: * * A. Hardy/GSC 8/99 Created * * M. Li/GSC 10/99 Modified output format * * A. Hardy/GSC 11/99 Added replacement watch information * * A. Hardy/GSC 2/00 Extracted from SPCTXT * * A. Hardy/GSC 3/00 Add check for listing replacement states* * A. Hardy/GSC 5/00 Changed cfl_aopn to cfl_wopn; Use * * AWIPS/WMO header ids.; removed 'NNNN' * * A. Hardy/GSC 10/00 Added ck for '0' dist. anchor/vor points* * A. Hardy/GSC 12/00 Removed '&' from iret * * A. Hardy/SAIC 10/01 Added check for old/new WMO header flag * * R. Tian/SAIC 06/02 Modified to meet the SPC requirement * * R. Tian/SAIC 04/03 Corrected if(iret == 0) syntax error * * A. Hardy/NCEP 6/03 Change hail size to string for decimals * * A. Hardy/NCEP 10/03 Modified to use utl/wbc libraries and * * added 'TEST' if a test watch * * A. Hardy/NCEP 3/04 Added wbc_mzrm * * G. Grosshans/SPC 10/04 Added ADD_WATCH_APPROX check * * G. Grosshans/SPC 11/05 Added LATLON_SAW_FORMAT tag to turn * * off lat-lon info at bottom of product. * * S. Jacobs/NCEP 11/05 Fixed array indices for ilat and ilon * * T. Piper/SAIC 12/05 Updated for cst_wrap CSC * * J. Wu/SAIC 04/06 Added parameter in cst_wrap * ***********************************************************************/ { FILE *ifpsaw; char blank[2]={' '}, ifname[256], wtch_type[20]; char cname1[32], cname2[32], sep[5], cpstates[256], states[256]; char newname[132], tmpsaw[500], hwmstr[500]; char prefs_tag[] = "LATLON_SAW_FORMAT"; float xx, yy; int ii, jj, ier, len, ilat[4], ilon[4]; Boolean useln; /*-------------------------------------------------------------------*/ ier = 0; /* * Create output file for appending. */ utl_gname ( spcinfo.ancrpt.stn1, spcinfo.ancrpt.stnnam1, spcinfo.ancrpt.stateid1, &ier ); utl_gname ( spcinfo.ancrpt.stn2, spcinfo.ancrpt.stnnam2, spcinfo.ancrpt.stateid2, &ier ); sprintf ( ifname, "WW%04d.SAW", spcinfo.wnum ); ifpsaw = cfl_wopn ( ifname, &ier ); /* * Set up header information. */ if ( strcmp(spcinfo.wtype,"SEVERE THUNDERSTORM" ) == 0 ) strcpy ( wtch_type, "SEVERE TSTM"); if ( strcmp(spcinfo.wtype,"TORNADO" ) == 0 ) strcpy ( wtch_type, "TORNADO"); spcinfo.sssnum = spcinfo.wnum % 10; fprintf ( ifpsaw, "WWUS30 KWNS %02d%s\n", spcinfo.itime.day,spcinfo.itime.hour); fprintf ( ifpsaw, "SAW%d \n", spcinfo.sssnum); fprintf ( ifpsaw, "%cSPC AWW %02d%s\n", CHRS, spcinfo.itime.day,spcinfo.itime.hour); /* * Replace underscores in the county names with a space. */ cst_rnan ( spcinfo.ancrpt.stnnam1, cname1, &ier ); cst_rnan ( spcinfo.ancrpt.stnnam2, cname2, &ier ); /* * Check if watch has been issued as a 'TEST'. */ if ( strcmp (spcinfo.status, "TEST") == 0 ) { fprintf ( ifpsaw, "WW %d TEST ", spcinfo.wnum); } else { fprintf ( ifpsaw, "WW %d ", spcinfo.wnum); } /* * Check for the marine zones which aren't the Great Lakes or * coastal water (CW). Remove them, if found. */ strcpy (cpstates, spcinfo.states); wbc_mzrm ( cpstates, states, &len, &ier ); /* * Set up rest of section. */ fprintf ( ifpsaw, "%s %s %02d%sZ - %02d%sZ\n", wtch_type, states, spcinfo.vtime.day, spcinfo.vtime.hour, spcinfo.etime.day, spcinfo.etime.hour ); fprintf ( ifpsaw, "AXIS..%d STATUTE MILES %s OF LINE..\n", spcinfo.ancatt.dist, spcinfo.ancatt.dirc ); /* * Check for zero distance for anchor points. */ if ( (spcinfo.ancrpt.dist1 != 0 ) && ( spcinfo.ancrpt.dist2 != 0 ) ) { fprintf ( ifpsaw, "%d%s %s/%s %s/ - %d%s %s/%s %s/\n", spcinfo.ancrpt.dist1, spcinfo.ancrpt.dirct1, spcinfo.ancrpt.stn1, cname1, spcinfo.ancrpt.stateid1, spcinfo.ancrpt.dist2, spcinfo.ancrpt.dirct2, spcinfo.ancrpt.stn2, cname2, spcinfo.ancrpt.stateid2); } else if ( ( spcinfo.ancrpt.dist1 == 0 ) && ( spcinfo.ancrpt.dist2 != 0 ) ) { fprintf ( ifpsaw, "%s/%s %s/ - %d%s %s/%s %s/\n", spcinfo.ancrpt.stn1, cname1, spcinfo.ancrpt.stateid1, spcinfo.ancrpt.dist2, spcinfo.ancrpt.dirct2, spcinfo.ancrpt.stn2, cname2, spcinfo.ancrpt.stateid2); } else if ( ( spcinfo.ancrpt.dist1 != 0 ) && ( spcinfo.ancrpt.dist2 == 0 ) ) { fprintf ( ifpsaw, "%d%s %s/%s %s/ - %s/%s %s/\n", spcinfo.ancrpt.dist1, spcinfo.ancrpt.dirct1, spcinfo.ancrpt.stn1, cname1, spcinfo.ancrpt.stateid1, spcinfo.ancrpt.stn2, cname2, spcinfo.ancrpt.stateid2); } else if ( ( spcinfo.ancrpt.dist1 == 0 ) && ( spcinfo.ancrpt.dist2 == 0 ) ) { fprintf ( ifpsaw, "%s/%s %s/ - %s/%s %s/\n", spcinfo.ancrpt.stn1, cname1, spcinfo.ancrpt.stateid1, spcinfo.ancrpt.stn2, cname2, spcinfo.ancrpt.stateid2); } /* * Check for zero distance for the vor points. */ if ( (spcinfo.vorrpt.dist1 != 0 ) && ( spcinfo.vorrpt.dist2 != 0 ) ) { fprintf ( ifpsaw, "..AVIATION COORDS.. %dNM %s /%d%s %s - %d%s %s/\n", spcinfo.voratt.dist, spcinfo.voratt.dirc, spcinfo.vorrpt.dist1, spcinfo.vorrpt.dirct1, spcinfo.vorrpt.stn1, spcinfo.vorrpt.dist2, spcinfo.vorrpt.dirct2, spcinfo.vorrpt.stn2); } else if ( (spcinfo.vorrpt.dist1 == 0 ) && ( spcinfo.vorrpt.dist2 != 0 ) ) { fprintf ( ifpsaw, "..AVIATION COORDS.. %dNM %s /%s - %d%s %s/\n", spcinfo.voratt.dist, spcinfo.voratt.dirc, spcinfo.vorrpt.stn1, spcinfo.vorrpt.dist2, spcinfo.vorrpt.dirct2, spcinfo.vorrpt.stn2); } else if ( (spcinfo.vorrpt.dist1 != 0 ) && ( spcinfo.vorrpt.dist2 == 0 ) ) { fprintf ( ifpsaw, "..AVIATION COORDS.. %dNM %s /%d%s %s - %s/\n", spcinfo.voratt.dist, spcinfo.voratt.dirc, spcinfo.vorrpt.dist1, spcinfo.vorrpt.dirct1, spcinfo.vorrpt.stn1, spcinfo.vorrpt.stn2); } else if ( (spcinfo.vorrpt.dist1 == 0 ) && ( spcinfo.vorrpt.dist2 == 0 ) ) { fprintf ( ifpsaw, "..AVIATION COORDS.. %dNM %s /%s - %s/\n", spcinfo.voratt.dist, spcinfo.voratt.dirc, spcinfo.vorrpt.stn1, spcinfo.vorrpt.stn2); } /* * Set up hail, wind gusts and lightning section. */ tmpsaw[0] = '\0'; cst_ncpy ( sep, "TO", 2, &ier ); len = sizeof(hwmstr); wbc_dhwm ( sep, &(spcinfo.hailsz), &(spcinfo.maxgust), &(spcinfo.maxtops), &(spcinfo.motion.deg), &(spcinfo.motion.speed), len, hwmstr, &ier ); tmpsaw[0] = '\0'; strcat ( tmpsaw, hwmstr); strcat ( tmpsaw, EOL ); cst_wrap ( tmpsaw, blank, &len, EOL, (char *)NULL, tmpsaw, &ier ); fprintf ( ifpsaw, tmpsaw); /* * If there are replacement watches listed, retrieve the lists of states * for each replacement watch. */ if ( strcmp ( spcinfo.replcnm[0], "NONE") != 0 ) { strcpy ( newname, "ww"); strcat ( newname, spcinfo.replcnm[0] ); strcat ( newname, ".txt" ); strcpy ( newinfo.file_info.filnam,newname); vfrptxt (newname, iret); if ( *iret == 0 ){ wbc_mzrm ( newinfo.states, states, &len, &ier ); fprintf ( ifpsaw, "\nREPLACES WW %d..%s \n", atoi(spcinfo.replcnm[0]), states); } else { fprintf ( ifpsaw, " WW %d.. \n", atoi (spcinfo.replcnm[0]) ); } /* * If there are more that 1 replacement watches listed, * proceed with the loop. */ for(jj = 1; jj <= spcinfo.wwrepnm; jj++) { strcpy ( newname, "ww"); strcat ( newname, spcinfo.replcnm[jj] ); strcat ( newname, ".txt" ); strcpy ( newinfo.file_info.filnam,newname); vfrptxt (newname, iret); if ( *iret == 0 ){ wbc_mzrm ( newinfo.states, states, &len, &ier ); fprintf ( ifpsaw, "REPLACES WW %d..%s \n", atoi (spcinfo.replcnm[jj]), states); } else { fprintf ( ifpsaw, " WW %d.. \n", atoi (spcinfo.replcnm[jj]) ); } } fprintf ( ifpsaw, "\n"); } else { fprintf ( ifpsaw, "\n"); } /* * Check if the LATLON_SAW_FORMAT flag is TRUE and then * add enhanced lat-lon data to the SAW text. * Make sure lats and lons are rounded to * 100ths of deg. */ tmpsaw[0] = '\0'; ctb_pfbool (prefs_tag, &useln, &ier ); if ( useln == TRUE ) { for ( ii = 0 ; ii < 4 ; ii++ ) { switch ( ii ) { case 0: xx = ((int)(spcinfo.wcpnt1.lat*100.0F)) / 100.0F; yy = ((int)(spcinfo.wcpnt1.lon*-100.0F)) / 100.0F; break; case 1: xx = ((int)(spcinfo.wcpnt2.lat*100.0F)) / 100.0F; yy = ((int)(spcinfo.wcpnt2.lon*-100.0F)) / 100.0F; break; case 2: xx = ((int)(spcinfo.wcpnt3.lat*100.0F)) / 100.0F; yy = ((int)(spcinfo.wcpnt3.lon*-100.0F)) / 100.0F; break; case 3: xx = ((int)(spcinfo.wcpnt4.lat*100.0F)) / 100.0F; yy = ((int)(spcinfo.wcpnt4.lon*-100.0F)) / 100.0F; break; default: break; } if ( yy >= 100.0F ) yy = yy - 100.0F; ilat[ii] = G_NINT(xx*100.0F); ilon[ii] = G_NINT(yy*100.0F); } fprintf ( ifpsaw, "LAT...LON %4d%04d %4d%04d %4d%04d %4d%04d\n\n", ilat[0], ilon[0], ilat[1], ilon[1], ilat[2], ilon[2], ilat[3], ilon[3]); } /* * Check if the approximation verbage needs to be included * in the SAW text. */ tmpsaw[0] = '\0'; strcpy (prefs_tag, "ADD_WATCH_APPROX"); ctb_pfbool (prefs_tag, &useln, &ier ); if ( useln == TRUE ) { tmpsaw[0] = '\0'; fprintf(ifpsaw, "THIS IS AN APPROXIMATION TO THE WATCH AREA. FOR A\n"); fprintf(ifpsaw, "COMPLETE DEPICTION OF THE WATCH SEE WOUS64 KWNS\n"); fprintf(ifpsaw, "FOR WOU%d.\n", spcinfo.sssnum); fprintf(ifpsaw, "\n"); } /* * Close output file. */ cfl_clos ( ifpsaw, &ier ); }
int main ( int argc, char **argv ) /************************************************************************ * mdp * * * * This program generates the mesoscale discussion latlon pairings. * * Pairings will be written to a file whose filename is based on the * * input filename (filename extension, if exists, is replaced w/ "mdp").* * * * Example: * * mdp input_vgf_file.vgf * * Produces latlon pairings in the ASCII file * * output_vgf_file.mdp * * * * main(argc, argv) * * * * Input parameters: * * argc int number of parameters of command line * * argv char** parameter array of command line * * * * Output parameters: * * Return parameters: * * NONE * * * ** * * Log: * * D.W.Plummer/NCEP 6/02 * * D.W.Plummer/NCEP 8/02 Bug fix for lons > 99.995 and < 100.0 * * m.gamazaychikov/SAIC 3/03 Made mdp work only on scallop lines * * added WFOs and STATES to output text * * m.gamazaychikov/SAIC 3/03 Made mdp work on lines grouped or not * * grouped with WFOs and/or STATES * * Made MDP exit upon encountering first * * scallop line in VGF file * * Made changes to format of output text * * T. Piper/SAIC 12/05 Updated cst_wrap for CSC * * J. Wu/SAIC 04/06 Added parameter in cst_wrap * ***********************************************************************/ { int ii, ix, iy, pagflg, ier; int ilen, npts; char vg_class, vg_type; char blank[2]={' '}, errgrp[8], infile[128], ifname[128], outfile[128]; float x, y; long ifilesize; int ne1, more1, curpos1; char buffer[1024], str[20], *cptr; int wrtoutfg, wrtwfofg, wrtsttfg; int grpnumbr1, grpnumbr2; int lintyp, jj, narea, areatype; int ne2, more2, curpos2; char strwfo[480], strstt[480], bufferlat[1024]; VG_DBStruct el; FILE *ifptr, *ofptr; /*---------------------------------------------------------------------*/ /* * Check if number of input arguments is correct. */ if ( argc < 2 ) { pagflg = G_FALSE; strcpy ( errgrp, "MDP" ); ip_help ( errgrp, &pagflg, &ier, strlen(errgrp) ); exit (0); } /* * First input on command line is input vgf file name. */ strcpy ( infile, argv[1] ); cfl_inqr ( infile, NULL, &ifilesize, ifname, &ier ); ifptr = (FILE *) cfl_ropn(ifname, "", &ier); if ( ier != 0 ) { printf("Error opening VGF file %s\n", infile ); exit (0); } /* * Output filename is input filename w/ "mdp" filename extension. */ strcpy ( outfile, infile ); cptr = strrchr( outfile, '.' ); if ( cptr != (char *)NULL ) { cptr[0] = '\0'; } strcat( outfile, ".mdp" ); /* * Loop through all the elements until a line is found. */ ne1 = 0; more1 = G_TRUE; curpos1 = 0; buffer[0] = '\0'; bufferlat[0] = '\0'; while ( ne1 < MAX_EDITABLE_ELEMS && more1 == G_TRUE ) { wrtoutfg = G_FALSE; wrtsttfg = G_FALSE; wrtwfofg = G_FALSE; cvg_rdrecnoc( ifname, ifptr, curpos1, &el, &ier ); if ( ier < 0 ) { more1 = G_FALSE; } else { curpos1 += el.hdr.recsz; vg_class = el.hdr.vg_class; vg_type = el.hdr.vg_type; grpnumbr1 = el.hdr.grpnum; if ( (int)vg_class == CLASS_LINES ) { /* * Open output file. */ ofptr = (FILE *)cfl_wopn ( outfile, &ier ); if ( ier != 0 ) { printf("Error opening/creating output file %s\n", outfile ); exit (0); } if ((int)vg_type == SPLN_ELM ) { /* * type of special line */ lintyp = el.elem.spl.info.spltyp; if (lintyp == 3 ) { /* * number of points in a line */ npts = el.elem.spl.info.numpts; /* * Format lats and lons into buffer. */ for ( ii = 0; ii < npts; ii++ ) { x = el.elem.spl.latlon[ii]; y = -el.elem.spl.latlon[ii+npts]; /* * Make sure lats and lons are rounded to 100ths of deg. */ x = ((int)(x*100)) / 100.0F; y = ((int)(y*100)) / 100.0F; if ( y >= 100.0F ) y -= 100.0F; ix = G_NINT(x*100.0F); iy = G_NINT(y*100.0F); sprintf( str, "%04d%04d ", ix, iy ); strcat ( bufferlat, str ); /* * this flag is here to ensure exit as soon * as a line is found */ more1 = G_FALSE; /* * this flag is here to ensure that lat-lon * pairs are written out even without wfo and states * grouped with it */ wrtoutfg = G_TRUE; } ne2 = 0; curpos2 = 0; more2 = G_TRUE; while ( ne2 < MAX_EDITABLE_ELEMS && more2 == G_TRUE ) { cvg_rdrecnoc( ifname, ifptr, curpos2, &el, &ier ); if ( ier < 0 ) { more2 = G_FALSE; } else { curpos2 += el.hdr.recsz; vg_class = el.hdr.vg_class; vg_type = el.hdr.vg_type; grpnumbr2 = el.hdr.grpnum; if (grpnumbr2 == grpnumbr1 && grpnumbr2 != 0) { if ((int)vg_type == LIST_ELM ) { areatype = 0; areatype = el.elem.lst.info.subtyp; if (areatype == 3) { wrtwfofg = G_TRUE; narea = el.elem.lst.data.nitems; strwfo[0] = '\0'; strcat( strwfo, "ATTN...WFO..."); jj = 0; for (jj = 0; jj < narea; jj++) { strcpy (str, el.elem.lst.data.item[jj]); strcat (strwfo, str); strcat (strwfo, "..." ); if ((jj+1)%9 == 0) { strcat (strwfo, "\n"); } } strcat (strwfo, "\n"); } if (areatype == 4) { wrtsttfg = G_TRUE; narea = el.elem.lst.data.nitems; strstt[0] = '\0'; jj = 0; for (jj = 0; jj < narea; jj++) { strcpy (str, el.elem.lst.data.item[jj]); strcat (strstt, str); strcat (strstt, "Z000-" ); } strcat (strstt, "\n"); } } } } ne2++; } } } } } ne1++; /* * Write to output file. */ if (wrtoutfg == G_TRUE) { /* * Wrap bufferlat such that only 6 pairs of lat,lons on one line */ ilen = 55; cst_wrap( bufferlat, blank, &ilen, "\n", (char *)NULL, bufferlat, &ier ); if (wrtsttfg == G_TRUE) { /* * Wrap strstt such that only 7 STATE IDs on one line * and dump strstt into buffer for further output */ ilen = 49; cst_wrap( strstt, blank, &ilen, "\n", (char *)NULL, strstt, &ier ); strcat ( buffer, strstt ); strcat ( buffer, "\n"); } if (wrtwfofg == G_TRUE) { /* * Wrap strwfo such that only 9 WFOs on one line * and dump strswo into buffer for further output */ ilen = 67; cst_wrap( strwfo, blank, &ilen, "\n", (char *)NULL, strwfo, &ier ); strcat ( buffer, strwfo ); strcat ( buffer, "\n"); } strcat ( buffer, bufferlat); strcat ( buffer, "\n"); cfl_writ( ofptr, (int)strlen(buffer), (unsigned char *)buffer, &ier ); bufferlat[0] = '\0'; } } /* * If no line is found, close files and exit. */ cfl_clos ( ifptr, &ier ); cfl_clos ( ofptr, &ier ); return(0); }
void clo_from ( int vgtype, int reorder, int npin, int flag, float *lat, float *lon, int maxchar, char *str, int *iret ) /************************************************************************ * clo_from * * * * This function returns a "from" line given a series of lat-lon * * coordinates. The format of the "from" line is determined by vgtype. * * The parameter reorder is an indicator whether the points consist of * * an area which is closed and the points should be re-ordered in a * * clockwise fashion, if necessary, and that the first point listed in * * the "from" line is the northernmost point. The flag parameter * * indicates whether lat-lon coordinates in International SIGMETs are to* * be formatted with direction prepended (flag==0) or with direction * * postpended (flag==1) or as VOR (flag==2). * * * * clo_from ( vgtype, reorder, npin, flag, lat, lon, maxchar, * * str, iret ) * * * * Input parameters: * * vgtype int VG type of "from" line * * reorder int VG reorder of "from" line * * npin int Number of points * * flag int Flag for coordinate format * * *lat float Latitudes * * *lon float Longitudes * * maxchar int Maximum number of chars in str * * * * Output parameters: * * *str char "From" line string * * *iret int Return value * * = 0 - OK * * * ** * * Log: * * D.W.Plummer/NCEP 7/99 Create * * D.W.Plummer/NCEP 8/99 Add CONVSIG, NCONVSIG, CONVOLK & AIRMET * * D.W.Plummer/NCEP 9/99 Sort area types northernmost & clockwise* * M. Li/GSC 10/99 Modified clo_direct and clo_compass code* * A. Hardy/GSC 12/99 Added flag for lat/lon * * D.W.Plummer/NCEP 12/99 Added processing for WSM_ELM vgtype * * F. J. Yen/NCEP 8/00 Made intl sig lat/lon at least 4 digits * * D.W.Plummer/NCEP 2/01 Changed units of WSM from NM to SM * * D.W.Plummer/NCEP 5/01 Simplified conversion of DD to DM * * D.W.Plummer/NCEP 5/01 Added chk of pt order for SIGTYP_LINE * * D.W.Plummer/NCEP 6/01 Change criteria for line point ordering * * D.W.Plummer/NCEP 10/01 Change meaning of flag for intl sigmets * * from dd or dms to pre or post ordinate * * m.gamazaychikov/SAIC 9/02 remove portion of the code duplicating * * function clo_reorder; * * add call to clo_reorder * * S. Jacobs/NCEP 10/02 Increased np for area type * * F. J. Yen/NCEP 1/04 Handled VOR format for intl SIGMETs. * * Updated and corrected prolog about flag.* * J. Lewis/AWC 3/05 Added chk for new from line format * * J. Lewis/AWC 6/05 remove reference to LLMXPT * * B. Yin/SAIC 6/05 increase indx size by 1 besause of np++ * * D.W.Plummer/NCEP 7/05 Add NEW_VAA_LATLON_FORMAT and VAA type * * S. Jacobs/NCEP 9/05 Add break to WSM case before VAA * * B. Yin/SAIC 10/05 Add separator flags for GFAs * * B. Yin/SAIC 1/06 remove the space around hyphen * * D.W.Plummer/NCEP 11/06 Explicit processing for GFAs * * D.W.Plummer/NCEP 01/07 clo_tmatch for GFAs, not clo_tclosest * * K. Tyle/UAlbany 11/10 Increased dimension of prefs_tag * ***********************************************************************/ { int ii, jj, idist, np, ier, icmp; float dist, dir, minlat, maxlat, dlat; char tstr[8], id[9], dir16[4], prefs_tag[22]; char vaafmt[20], vaasep[8]; int *indx; int lattmp, lontmp; int line_order, reverse, format_type; Boolean newcoord, newvaacoord; int n_nms, nclose; char nm[17]; float GFAtol=GFA_TOL; /*---------------------------------------------------------------------*/ *iret = 0; str[0] = '\0'; /* * Check if the new coordinate format is to be used. */ strcpy ( prefs_tag, "NEW_LATLON_FORMAT" ); ctb_pfbool ( prefs_tag, &newcoord, &ier ); strcpy ( prefs_tag, "NEW_VAA_LATLON_FORMAT" ); ctb_pfbool ( prefs_tag, &newvaacoord, &ier ); /* * Allocate memory. */ G_MALLOC ( indx, int, npin + 1, "CLO_FROM" ); np = npin; for ( jj = 0; jj < np; jj++ ) indx[jj] = jj; if ( reorder == SIGTYP_AREA ) { clo_reorder( np, lat, lon, indx, iret ); np++; } else if ( reorder == SIGTYP_LINE ) { /* * If reorder is a line, re-order processing of * points to do either west-to-east or north-to-south. * West-to-east defined as all points within W2ELIM * degrees of one another. */ minlat = lat[0]; maxlat = minlat; for ( jj = 1; jj < np; jj++ ) { minlat = G_MIN ( minlat, lat[jj] ); maxlat = G_MAX ( maxlat, lat[jj] ); } dlat = G_ABS( maxlat - minlat ); line_order = N2S; if ( dlat <= W2ELIM ) line_order = W2E; reverse = G_FALSE; if ( line_order == N2S && lat[0] < lat[np-1] ) reverse = G_TRUE; if ( line_order == W2E && lon[0] > lon[np-1] ) reverse = G_TRUE; if ( reverse ) { for ( jj = 0; jj < np; jj++ ) indx[jj] = np-1-jj; } } /* * Set format_type. */ if ( vgtype == SIGINTL_ELM ) { /* * International SIGMET */ if ( flag != 2 ) format_type = LATLON; else format_type = VOR_FMT; } else if ( vgtype == SIGNCON_ELM || vgtype == SIGCONV_ELM || vgtype == SIGOUTL_ELM || vgtype == SIGAIRM_ELM ) /* * Non-Convective SIGMET, Convective SIGMET, * Convective Outlook */ format_type = VOR_FMT; else if ( vgtype == GFA_ELM ) /* * AIRMET */ format_type = GFA_FMT; else if ( vgtype == WSM_ELM ) /* * Watch Status Message */ format_type = WSM; else if ( vgtype == VOLC_ELM || vgtype == ASHCLD_ELM ) /* * VAA volcano and ash clouds. */ format_type = VAA; else format_type = IMISSD; /* * Loop through all the points using the indx array. */ for ( jj = 0; jj < np; jj++ ) { ii = indx[jj]; switch ( format_type ) { case LATLON: /* latitude/longitude display */ /* eg., 3913N7705W 4134N8120W */ /* eg., N3913W07705 N4134W08120 */ if ( jj != 0 ) strcat ( str, " " ); if ( flag == 0 ) { if ( ( newcoord == G_TRUE ) && ( jj != 0 ) ) strcat ( str, "- " ); if ( lat[ii] >= 0.0F ) strcat ( str, "N" ); else strcat ( str, "S" ); /* * Convert degree, decimal to degree, minutes. */ lattmp = DDTODM ( G_ABS( lat[ii] ) ); sprintf( tstr, "%04d", lattmp ); strcat ( str, tstr ); if ( newcoord == G_TRUE ) strcat ( str, " " ); if ( lon[ii] >= 0.0F ) strcat ( str, "E" ); else strcat ( str, "W" ); /* * Convert degree, decimal to degree, minutes. */ lontmp = DDTODM ( G_ABS( lon[ii] ) ); sprintf( tstr, "%05d", lontmp ); strcat ( str, tstr ); } else { /* * Convert degree, decimal to degree, minutes. */ lattmp = DDTODM ( G_ABS( lat[ii] ) ); sprintf( tstr, "%04d", lattmp ); strcat ( str, tstr ); if ( lat[ii] >= 0.0F ) strcat ( str, "N" ); else strcat ( str, "S" ); /* * Convert degree, decimal to degree, minutes. */ lontmp = DDTODM ( G_ABS( lon[ii] ) ); sprintf( tstr, "%05d", lontmp ); strcat ( str, tstr ); if ( lon[ii] >= 0.0F ) strcat ( str, "E" ); else strcat ( str, "W" ); } break; case VOR_FMT: /* distance and 16-pt compass */ /* to closest VOR point */ /* eg., 20SSW EMI TO 20ENE CLE */ clo_tdirect( "VOR", lat[ii], lon[ii], id, &dist, &dir, &ier ); clo_compass ( &dir, dir16, &icmp, &ier ); /* * Round distance to the nearest 10 nautical miles; * If convective outlook and less than 30 nm, set to 0. */ idist = G_NINT ( dist * M2NM / 10.0F ) * 10; if ( vgtype == SIGOUTL_ELM && idist < 30 ) idist = 0; if ( jj > 0 ) { /* * Different separators for different products. */ if ( vgtype == SIGCONV_ELM || vgtype == SIGOUTL_ELM || vgtype == SIGINTL_ELM ) strcat ( str, "-" ); else if ( vgtype == SIGAIRM_ELM || vgtype == SIGNCON_ELM ) strcat ( str, " TO " ); } if ( idist != 0 ) { sprintf( tstr, "%d", idist ); strcat ( str, tstr ); if ( vgtype == SIGINTL_ELM ) strcat ( str, " " ); strcat ( str, dir16 ); strcat ( str, " " ); } strcat ( str, id ); break; case GFA_FMT: /* closest SNAP point */ /* * Use clo_tmatch since all points are already snapped */ clo_tmatch( "SNAP", lat[ii], lon[ii], GFAtol, &ier ); if ( ier != 0 ) { nclose = 1; clo_tclosest( "SNAP", lat[ii], lon[ii], nclose, &ier ); } clo_tgnm ( "SNAP", 1, (sizeof(nm)-1), &n_nms, nm, &ier ); cst_rpst ( nm, "_", " ", nm, &ier ); if ( jj > 0 ) { if ( flag == SEPARATOR_TO ) { strcat ( str, " TO " ); } else if ( flag == SEPARATOR_DASH ) { strcat ( str, "-" ); } } strcat ( str, nm ); break; case WSM: /* Watch status messages */ /* SM distance and 16-pt compass*/ /* to closest ANCHOR point */ /* eg., 10 N DCA TO 20 NW HGR */ clo_tdirect( "ANCHOR", lat[ii], lon[ii], id, &dist, &dir, &ier ); clo_compass ( &dir, dir16, &icmp, &ier ); /* * Round distance to the nearest 5 statute miles. */ idist = G_NINT ( dist * M2SM / 5.0F ) * 5; if ( jj > 0 ) strcat ( str, " TO " ); if ( idist != 0 ) { sprintf( tstr, "%d ", idist ); strcat ( str, tstr ); strcat ( str, dir16 ); strcat ( str, " " ); } strcat ( str, id ); break; case VAA: /* VAA volcano and ash clouds */ if ( newvaacoord == G_FALSE ) { strcpy ( vaafmt, "%s%04d%s%05d" ); strcpy ( vaasep, " - " ); } else if ( newvaacoord == G_TRUE ) { strcpy ( vaafmt, "%s%04d %s%05d" ); strcpy ( vaasep, " - " ); } /* * Convert degree, decimal to degree, minutes. */ lattmp = DDTODM ( G_ABS( lat[ii] ) ); lontmp = DDTODM ( G_ABS( lon[ii] ) ); sprintf( tstr, vaafmt, ( lat[ii] >= 0.0F ) ? "N" : "S", lattmp, ( lon[ii] >= 0.0F ) ? "E" : "W", lontmp ); strcat ( str, tstr ); if ( jj < (np-1) ) strcat ( str, vaasep ); break; } } G_FREE ( indx, int ); return; }
void gb2_gdtmerc( float *navblk, int *igdtmpl, int *iret ) /************************************************************************ * gb2_gdtmerc * * * * This routine converts a MER Gempak grid navigation block to a * * GRIB2 Grid Definition Template 3.10. * * * * gb2_gdtmerc ( navblk, igdtmpl, iret ) * * * * Input parameters: * * *navblk float Decoded GRIB2 structure * * * * Output parameters: * * *igdtmpl int GDT 3.10 values * * *iret int Return code * * -36 = Projection not MER * ** * * Log: * * S. Gilbert/NCEP 08/05 Calculations taken from GDS_MER * * S. Gilbert/NCEP 03/06 Chngs to remove compiler warnings * ***********************************************************************/ { double rlat1, rlon1, rlat2, rlon2, dx, dy; double tlat1, tlon1, tlat2, tlon2; double x1, y1, x2, y2, rnx, rny; int ier; int nx, ny; /*---------------------------------------------------------------------*/ *iret = 0; /* * ensure grid navigation block is MER */ if ( strncmp( (char *)(navblk+1), "MER", 3) != 0 ) { *iret=-36; ER_WMSG("GB", iret, (char *)(navblk+1), &ier, 2, 4 ); } nx = G_NINT(navblk[4]); ny = G_NINT(navblk[5]); rlat1 = navblk[6]; rlon1 = navblk[7]; rlat2 = navblk[8]; rlon2 = navblk[9]; /* * Calculate grid increments */ rnx = navblk[4]; rny = navblk[5]; tlat1 = rlat1 * DTR / 2.; tlat2 = rlat2 * DTR / 2.; if ( rlon2 < rlon1 ) tlon2 = rlon2 + 360.; else tlon2 = rlon2; tlon1 = rlon1 * DTR; tlon2 = tlon2 * DTR; x1 = 0.0; y1 = RADIUS * log ( tan ( PI4TH + tlat1 ) ); x2 = RADIUS * ( tlon2 - tlon1 ); y2 = RADIUS * log ( tan ( PI4TH + tlat2 ) ); dx = ( x2 - x1 ) / ( rnx - 1. ); dy = ( y2 - y1 ) / ( rny - 1. ); /* * Set Grid Definition Template */ igdtmpl[0] = 1; /* Earth Assumed Spherical */ igdtmpl[1] = 0; /* Radius scale factor */ igdtmpl[2] = G_NINT(RADIUS); /* Radius of Earth */ igdtmpl[3] = 0; /* Oblate info n/a */ igdtmpl[4] = 0; /* Oblate info n/a */ igdtmpl[5] = 0; /* Oblate info n/a */ igdtmpl[6] = 0; /* Oblate info n/a */ igdtmpl[7] = nx; /* Kx */ igdtmpl[8] = ny; /* Kx */ igdtmpl[9] = G_NINT(rlat1*1000000.0); /* Lat of 1st grid point */ if ( rlon1 < 0.0 ) rlon1 += 360.0; igdtmpl[10] = G_NINT(rlon1*1000000.0); /* Lon of 1st grid point */ igdtmpl[11] = 48; /* Res and Comp flags */ igdtmpl[12] = 0; /* LaD at equator */ igdtmpl[13] = G_NINT(rlat2*1000000.0); /* Lat of last grid point */ if ( rlon2 < 0.0 ) rlon2 += 360.0; igdtmpl[14] = G_NINT(rlon2*1000000.0); /* Lon of last grid point */ igdtmpl[15] = 64; /* Scanning mode */ igdtmpl[16] = 0; /* Orientation of grid */ igdtmpl[17] = G_NINT(dx*1000.0); /* Dx */ igdtmpl[18] = G_NINT(dy*1000.0); /* Dy */ }
void msdatt ( int *iunit, char *filnam, int *lenf, int *itype, float *xsize, float *ysize, int *ileft, int *ibot, int *iright, int *itop, int *iret ) /************************************************************************ * msdatt * * * * This subroutine is called to initialize the metafile attributes. * * * * msdatt ( iunit, filnam, lenf, itype, xsize, ysize, * * ileft, ibot, iright, itop, iret ) * * * * Input parameters: * * *iunit int Output type (Used for XW only) * * *filnam char Output metafile name * * *lenf int Length of file name * * *itype int Device color type * * *xsize float X size in pixels * * *ysize float Y size in pixels * * * * Output parameters: * * *ileft int Left device coordinate * * *ibot int Bottom device coordinate * * *iright int Right device coordinate * * *itop int Top device coordinate * * *iret int Return code * ** * * Log: * * S. Jacobs/NCEP 2/96 * * S. Jacobs/NCEP 5/96 Added new global variables for queries * * S. Jacobs/NCEP 2/97 Fixed check for same file name * * R. Tian/SAIC 4/02 Added init of ileft, ibot, iright, itop * * M. Li/SAIC 7/02 Added G_NINT * ***********************************************************************/ { int ier; char tmpfil[MAX_FNLEN]; int tmpxz, tmpyz; long flen; int nbin; FILE *fp; /*---------------------------------------------------------------------*/ *iret = G_NORMAL; /* * If the input length is greater than the maximum allowed, * return an error. */ if ( ( *lenf >= MAX_FNLEN ) || ( *lenf <= 0 ) ) { *iret = G_NOMETA; return; } /* * Copy the file name to a temporary variable and add a NULL. */ strncpy ( tmpfil, filnam, (size_t)*lenf ); tmpfil[*lenf] = CHNULL; /* * Compare the input file name to the current file name. If the * names are different, close the old file. Otherwise, do nothing. */ if ( strcmp ( curfil, tmpfil ) != 0 ) { mclose ( &ier ); /* * Set the current file name. */ strcpy ( curfil, tmpfil ); *iret = G_NEWWIN; /* * Set the global output and color scheme types. */ kctype = *itype; kunit = *iunit; /* * Check for the existence of the metafile. */ cfl_inqr(curfil, NULL, &flen, tmpfil, &ier); if ( ( ier == 0 ) && ( strcmp ( curfil, "Nmeta" ) != 0 ) ) { /* * Get frame size from the existing file */ if ( ( fp = cfl_ropn(curfil, NULL, &ier) ) == NULL ) { *iret = G_NOMETA; return; } cfl_read(fp, sizeof(nc_file_header), (unsigned char *)&meta_head, &nbin, &ier); if ( ier ) { *iret = G_NOMETA; cfl_clos(fp, &ier); return; } cfl_clos(fp, &ier); if ( meta_head.version == 2 ) { /* * Set the global CGM frame size */ fxsize = meta_head.fxsize; fysize = meta_head.fysize; /* * ileft = left device coordinate * ibot = bottom device coordinate * iright = right device coordinate * itop = top device coordinate */ *ileft = 0; *ibot = 0; *iright = (int)meta_head.fxsize; *itop = (int)meta_head.fysize; } } else { /* * The valid range of xsize and ysize is 0.1 ~ 1.0. If neither * value is 1.0, then set the larger value to be 1.0, and set the * smaller value to be the ratio of the smaller to the larger. */ tmpxz = G_NINT(*xsize * (float)XY_SCALE); tmpyz = G_NINT(*ysize * (float)XY_SCALE); tmpxz = (tmpxz < 0 || tmpxz > XY_SCALE) ? XY_SCALE : tmpxz; tmpyz = (tmpyz < 0 || tmpyz > XY_SCALE) ? XY_SCALE : tmpyz; if(tmpxz != XY_SCALE && tmpyz != XY_SCALE) { if(tmpxz > tmpyz) { tmpyz = G_NINT((((float)tmpyz)/(float)tmpxz)*(float)XY_SCALE); tmpxz = XY_SCALE; } else if(tmpxz < tmpyz) { tmpxz = G_NINT((((float)tmpxz)/(float)tmpyz)*(float)XY_SCALE); tmpyz = XY_SCALE; } else { tmpxz = XY_SCALE; tmpyz = XY_SCALE; } } tmpxz = (tmpxz < G_NINT(0.1F*(float)XY_SCALE)) ? G_NINT(0.1F*(float)XY_SCALE) : tmpxz; tmpyz = (tmpyz < G_NINT(0.1F*(float)XY_SCALE)) ? G_NINT(0.1F*(float)XY_SCALE) : tmpyz; /* * Set the global CGM frame size */ fxsize = (unsigned short)tmpxz; fysize = (unsigned short)tmpyz;; /* * ileft = left device coordinate * ibot = bottom device coordinate * iright = right device coordinate * itop = top device coordinate */ *ileft = 0; *ibot = 0; *iright = tmpxz; *itop = tmpyz; } } }
int main ( int argc, char **argv ) /************************************************************************ * mdp * * * * This program generates the mesoscale discussion latlon pairings. * * Pairings will be written to a file whose filename is based on the * * input filename (filename extension, if exists, is replaced w/ "mdp").* * * * Example: * * mdp input_vgf_file.vgf * * Produces latlon pairings in the ASCII file * * output_vgf_file.mdp * * * * main(argc, argv) * * * * Input parameters: * * argc int number of parameters of command line * * argv char** parameter array of command line * * * * Output parameters: * * Return parameters: * * NONE * * * ** * * Log: * * D.W.Plummer/NCEP 6/02 * * D.W.Plummer/NCEP 8/02 Bug fix for lons > 99.995 and < 100.0 * * G. Grosshans/SPC 11/02 Updated to decode multi-scalloped lines * * G. Grosshans/SPC 12/02 Updated to compute WFO/State * * S. Jacobs/NCEP 5/03 Clean up unused variables and headers * * G. Grosshans/SPC 10/03 Updated for precision * * T. Piper/SAIC 12/05 Updated cst_wrap for CSC * * J. Wu/SAIC 04/06 Added parameter in cst_wrap * * G. Grosshans/SPC 08/08 Updated for SCN 08-45 to add LAT...LON * * and list first point as last point * * to indicate a closed polygon. Add * * word wrapping for ATTN...WFO... * ***********************************************************************/ { int ii, ix, iy, ixfirst, iyfirst, pagflg, ne, ilen, npts, ier, iret, nitems, more, curpos; long ifilesize; float x, y, flat[MAXLISTITEMS], flon[MAXLISTITEMS]; char vg_class, vg_type, buffer[2048], bufferfinal[2048], bufferfinalwfo[2048],str[20], *cptr, errgrp[12], infile[128], ifname[128], outfile[128], info[2048], stpo[4], cstl_list[1000], cstl_liststate[1000], newLineStr[13]=" "; /* 13 spaces */ char blank[2]={' '}, device[13], dfilnam[73], pro[80]; int mode, istat, iunit, itype; float xsize, ysize, lllat, lllon, urlat, urlon, prjang1, prjang2, prjang3; VG_DBStruct el; FILE *ifptr, *ofptr; const int line_len = 66; /*---------------------------------------------------------------------*/ /* * Set defaults for gsdeva and gsmprj */ mode = 1; strcpy ( device, "GN" ); iunit = 1; strcpy ( dfilnam, "MDPSPC" ); itype = 1; xsize = 500.0F; ysize = 500.0F; lllat = 10.0F; lllon = -120.0F; urlat = 50.0F; urlon = -50.0F; strcpy ( pro, "str" ); prjang1 = 90.0F; prjang2 = -105.0F; prjang3 = 0.0F; cstl_list[0] = '\0'; cstl_liststate[0] = '\0'; in_bdta ( &ier ); ginitp ( &mode, &istat, &ier); gsdeva (device, &iunit, dfilnam, &itype, &xsize, &ysize, &iret, strlen(device), strlen(dfilnam)); gsmprj ( pro, &prjang1, &prjang2, &prjang3, &lllat, &lllon, &urlat, &urlon, &iret, strlen(pro)); clo_init ( &ier ); /* * Check if number of input arguments is correct. */ if ( argc < 2 ) { pagflg = G_FALSE; strcpy ( errgrp, "MDPSPC" ); ip_help ( errgrp, &pagflg, &ier, strlen(errgrp) ); gendp (&mode, &ier); exit (0); } /* * First input on command line is input vgf file name. */ strcpy ( infile, argv[1] ); cfl_inqr ( infile, NULL, &ifilesize, ifname, &ier ); ifptr = (FILE *) cfl_ropn(ifname, "", &ier); if ( ier != 0 ) { printf("Error opening VGF file %s\n", infile ); gendp (&mode, &ier); exit (0); } /* * Output filename is input filename w/ "mdp" filename extension. */ strcpy ( outfile, infile ); cptr = strrchr( outfile, '.' ); if ( cptr != (char *)NULL ) { cptr[0] = '\0'; } strcat( outfile, ".mdp" ); /* * Loop through all the elements until a line is found. */ ne = 0; more = G_TRUE; curpos = 0; buffer[0] = '\0'; bufferfinal[0] = '\0'; bufferfinalwfo[0] = '\0'; strcat ( buffer, "LAT...LON " ); while ( ne < MAX_EDITABLE_ELEMS && more == G_TRUE ) { cvg_rdrecnoc( ifname, ifptr, curpos, &el, &ier ); if ( ier < 0 ) { more = G_FALSE; } else { curpos += el.hdr.recsz; vg_class = el.hdr.vg_class; vg_type = el.hdr.vg_type; if ( ( (int)vg_class == CLASS_LINES ) && ( el.hdr.vg_type == SPLN_ELM ) && ( (int)el.elem.spl.info.spltyp == 3 ) ) { /* * Open output file. */ ofptr = (FILE *)cfl_wopn ( outfile, &ier ); if ( ier != 0 ) { printf("Error opening/creating output file %s\n", outfile ); gendp (&mode, &ier); exit (0); } /* * Find FIPS bounded by the closed line */ npts = el.elem.spl.info.numpts; /* FIND WHAT STATES ARE IN MD AREA */ clo_binpoly ( "CNTY_BNDS", npts, el.elem.spl.latlon, &(el.elem.spl.latlon[npts]), &ier ); clo_tgltln ( "CNTY_BNDS", MAXLISTITEMS, &nitems, flat, flon, &ier); for ( ii = 0; ii < nitems; ii++ ) { clo_bginfo( "CNTY_BNDS", ii, info, &ier ); cst_gtag( "STATE", info, "?", stpo, &ier); if (strstr(cstl_liststate, stpo)==NULL) { strcat(cstl_liststate, stpo); strcat(cstl_liststate, " "); } } /* FIND WHAT WFOs ARE IN MD AREA */ clo_binpoly ( "CWA_BNDS", npts, el.elem.spl.latlon, &(el.elem.spl.latlon[el.elem.spl.info.numpts]), &ier ); clo_tgltln ( "CWA_BNDS", MAXLISTITEMS, &nitems, flat, flon, &ier); for ( ii = 0; ii < nitems; ii++ ) { clo_bginfo( "CWA_BNDS", ii, info, &ier ); cst_gtag( "WFO", info, "?", stpo, &ier); strcat(cstl_list, stpo); strcat(cstl_list, "..."); } /* * Format lats and lons into buffer. */ if ( (int)vg_type == LINE_ELM ) { npts = el.elem.lin.info.numpts; } else if ( (int)vg_type == SPLN_ELM ) { npts = el.elem.spl.info.numpts; } for ( ii = 0; ii < npts; ii++ ) { if ( (int)vg_type == LINE_ELM ) { x = el.elem.lin.latlon[ii]; y = -el.elem.lin.latlon[ii+npts]; } else if ( (int)vg_type == SPLN_ELM ) { x = el.elem.spl.latlon[ii]; y = -el.elem.spl.latlon[ii+npts]; } /* * Make sure lats and lons are rounded * to 100ths of deg. */ x = ((int)(x*100.0F)) / 100.0F; y = ((int)(y*100.0F)) / 100.0F; if ( y >= 100.0F ) y -= 100.0F; ix = G_NINT(x*100.0F); iy = G_NINT(y*100.0F); sprintf( str, "%04d%04d ", ix, iy ); strcat ( buffer, str ); if ( ii == 0 ) { ixfirst = ix; iyfirst = iy; } } /* * Repeat first lat/lon point as last lat/lon point * to indicate a closed polygon. */ sprintf( str, "%04d%04d ", ixfirst, iyfirst); strcat ( buffer, str ); sprintf( str, "\n\n" ); strcat ( buffer, str ); /* * Wrap buffer such that only 6 pairs of lat,lons * on one line. * ilen = 55; * cst_wrap( buffer, blank, &ilen, "\n", (char *)NULL, buffer, &ier ); */ ilen = 66; cst_wrap( buffer, blank, &ilen, "\n", newLineStr, buffer, &ier ); } } ne++; } /* * wrap the ATTN...WFO... line */ strcat ( bufferfinalwfo, "ATTN...WFO..." ); strcat ( bufferfinalwfo, cstl_list ); cst_wrap( bufferfinalwfo, "...", &line_len, "\n", (char *)NULL, bufferfinalwfo, &ier ); /* * build the output file string and add the ATTN...WFO... string */ strcat ( bufferfinal,"STATES=" ); strcat ( bufferfinal, cstl_liststate ); strcat ( bufferfinal, "\n\n" ); strcat ( bufferfinal, bufferfinalwfo ); /* strcat ( bufferfinal,"ATTN...WFO..." ); strcat ( bufferfinal, cstl_list ); */ strcat ( bufferfinal, "\n\n" ); strcat ( bufferfinal, buffer ); /* * Write to output file. */ cfl_writ ( ofptr, (int)strlen(bufferfinal), (unsigned char *)bufferfinal, &ier ); /* * close files and exit. */ cfl_clos ( ifptr, &ier ); cfl_clos ( ofptr, &ier ); gendp (&mode, &ier); return(0); }
void df_hilo ( const int *hi, const int *lo, int *iret ) /************************************************************************ * df_hilo * * * * This subroutine finds the relative extrema over a grid. * * * * df_hilo ( hi, lo, iret ) * * * * Input parameters: * * *hi const int Flag for finding highs * * *lo const int Flag for finding lows * * * * Output parameters: * * *iret int Return code * * As for DG_GETS * ** * * Log: * * K. Brill/NMC 5/93 * * D. Keiser/GSC 7/95 Changed DC_HILO to DG_HILO * * D. Keiser/GSC 10/95 Add call to write error message after * * call to DG_HILO * * T. Lee/GSC 4/96 Single dimension for dgg * * K. Tyle/GSC 5/96 Moved IGDPT outside do-loop * * T. Piper/GSC 11/98 Updated prolog * * K. Brill/HPC 1/02 CALL DG_SSUB and DG_ESUB * * K. Brill/HPC 11/02 Eliminate use of the SUBA logical array * * R. Tian/SAIC 11/05 Recoded from Fortran * ************************************************************************/ { int num1, num2, no, nx, kxd, kyd, kxyd, ksub1, ksub2; int krad, nmax, nmin, ixmx, iymx, ivmx, ixmn, iymn, ivmn, intflg, nummx, nummn, ii, i, j, nxi,nxj, nxv, index, ier, ier2, izero; float *gnum1, *gnum2, *gno, *gnx, fzero; char namout[5]; /*----------------------------------------------------------------------*/ *iret = 0; izero = 0; fzero = 0.0; dg_ssub ( iret ); strcpy ( namout, "HILO" ); /* * Get the grid to be searched from the stack. */ dg_gets ( &num1, iret ); if ( *iret != 0 ) return; dg_getg ( &num1, &gnum1, &kxd, &kyd, &ksub1, &ksub2, iret ); /* * Get the radius value. */ dg_gets ( &num2, iret ); if ( *iret != 0 ) return; dg_getg ( &num2, &gnum2, &kxd, &kyd, &ksub1, &ksub2, iret ); krad = G_NINT ( gnum2[0] ); /* * Get a new grid number for the output highs and lows. */ dg_nxts ( &no, iret ); if ( *iret != 0 ) return; dg_getg ( &no, &gno, &kxd, &kyd, &ksub1, &ksub2, iret ); kxyd = kxd * kyd; nmax = kxyd / 6; nmin = nmax; /* * Store the HILO information in the NX grid. */ dg_nxts ( &nx, iret ); if ( *iret != 0 ) return; dg_getg ( &nx, &gnx, &kxd, &kyd, &ksub1, &ksub2, iret ); ixmx = 1; iymx = 1 + nmax; ivmx = iymx + nmax; ixmn = ivmx + nmin; iymn = ixmn + nmin; ivmn = iymn + nmin; if ( *hi == G_FALSE ) nmax = 0; if ( *lo == G_FALSE ) nmin = 0; intflg = G_FALSE; dg_hilo ( gnum1, &kxd, &kyd, &krad, &intflg, &nmax, &nmin, &fzero, &fzero, &fzero, &fzero, &nummx, &gnx[ixmx-1], &gnx[iymx-1], &gnx[ivmx-1], &nummn, &gnx[ixmn-1], &gnx[iymn-1], &gnx[ivmn-1], iret ); if ( *iret < 0 ) return; /* * Write out error message regarding internal buffers in DG_HILO. */ if ( *iret != 0 ) { er_wmsg ( "DG", iret, " ", &ier2, strlen("DG"), strlen(" ") ); } /* * Set all grid values to missing. */ for ( ii = ksub1; ii <= ksub2; ii++ ) { gno[ii-1] = RMISSD; } if ( *hi == G_TRUE ) { if ( *lo == G_FALSE ) strcpy ( namout, "HIGH" ); /* * Put the maxima on the grid. */ for ( ii = 1, nxi = ixmx-1, nxj = iymx-1, nxv = ivmx-1; ii <= nummx; ii++, nxi++, nxj++, nxv++ ) { i = G_NINT ( gnx[nxi] ); j = G_NINT ( gnx[nxj] ); index = ( j - 1 ) * kxd + i; gno[index-1] = gnx[nxv]; } } if ( *lo == G_TRUE ) { if ( *hi == G_FALSE ) strcpy ( namout, "LOWS" ); /* *Put the minima on the grid. */ for ( ii = 1, nxi = ixmn-1, nxj = iymn-1, nxv = ivmn-1; ii <= nummn; ii++, nxi++, nxj++, nxv++ ) { i = G_NINT ( gnx[nxi] ); j = G_NINT ( gnx[nxj] ); index = ( j - 1 ) * kxd + i; gno[index-1] = gnx[nxv]; } } /* * Get a name of the form NAMOUT //S and update header; * update stack. */ dg_updh ( namout, &no, &num1, &izero, iret ); dg_puts ( &no, iret ); dg_esub ( &no, &izero, &izero, &izero, &ier ); if ( ier != 0 ) *iret = ier; return; }
void df_rdfs ( int *iret ) /************************************************************************ * DF_RDFS (Resolution Dependent Filter for Scalar) * * * * This subroutine smoothes a scalar grid using a moving average * * low-pass filter whose weights are determined by the normal * * (Gaussian) probability distribution function for two dimensions. * * The weight given to any grid point within the area covered by the * * moving average for a target grid point is proportional to * * * * EXP [ -( D ** 2 ) ], * * * * where D is the distance from that point to the target point divided * * by the standard deviation of the normal distribution. The value of * * the standard deviation is determined by the degree of filtering * * requested. The degree of filtering is specified by giving an * * effective resolution in km for the output grid. From this value, * * an integer required as the input for the GWFS function is computed. * * * * See the documentation for the GWFS function for more details. * * * * When this function is invoked, the first argument is the grid to be * * smoothed, the second is the effective resolution as described above: * * * * RDFS ( S, dx ) * * * * where dx > 0. If the value of dx is less than the grid spacing * * on the internal grid, no filtering is done. * * * * DF_RDFS ( IRET ) * * * * Output parameters: * * IRET INTEGER Return code * * As for DG_GETS * ** * * Log: * * K. Brill/HPC 05/12 Developed from DF_GWFS * ************************************************************************/ { int nnw, kxd, kyd, ksub1, ksub2, zero, ier; int jj, ii, indx; int ixm, iym, ni, no; float *gnnw, *gnost; float gdx, gdy, dsg, eres, swl; /*----------------------------------------------------------------------*/ *iret = 0; zero = 0; dg_ssub ( iret ); /* * Compute map scale factors and grid increments. */ dg_mscl ( iret ); if ( *iret != 0 ) return; /* * Get the grid spacing values: */ dg_qmsl ( &ixm, &iym, &gdx, &gdy, iret ); if ( *iret != 0 ) return; if ( gdx > gdy ) { dsg = gdx; } else { dsg = gdy; } dsg = dsg / 1000.0; /*printf (" dsg = %f\n", dsg ); */ /* * Get the input grid number. */ dg_gets ( &ni, iret ); if ( *iret != 0 ) return; /* * Get the user specified effective resolution (km). */ dg_gets ( &nnw, iret ); if ( *iret != 0 ) return; dg_getg ( &nnw, &gnnw, &kxd, &kyd, &ksub1, &ksub2, iret ); eres = gnnw[0]; if ( eres < dsg ) { /*printf ( " No smoothing\n" );*/ /* * Do nothing -- return original grid without smoothing. */ /* * Make a name of the form 'RDF'//S and update header; * update stack. */ dg_updh ( "RDF", &ni, &ni, &zero, iret ); dg_puts ( &ni, iret ); dg_esub ( &ni, &zero, &zero, &zero, &ier ); if ( ier != 0 ) *iret = ier; return; } else { /* * Call the GWFS program to smooth the grid. The smoother footprint is chosen so as so suppress the 2 delta X wave on the coarse grid to 1/e of the original amplitude. */ swl = (float)G_NINT ( ( eres / dsg ) * 2.0 ); /*printf (" Smooth with footprint = %f\n", swl);*/ /* * Get a new grid number for the output. */ dg_nxts ( &no, iret ); if ( *iret != 0 ) return; dg_getg ( &no, &gnost, &kxd, &kyd, &ksub1, &ksub2, iret ); for ( jj = 1; jj <= kyd; jj++ ) { for ( ii = 1; ii <= kxd; ii++ ) { indx = ( jj - 1 ) * kxd + ii; gnost[indx-1] = swl; } } /* * Put two grids on the stack for the Gaussing weighted filter. */ dg_puts ( &no, iret ); if ( *iret != 0 ) return; dg_puts ( &ni, iret ); if ( *iret != 0 ) return; df_gwfs ( iret ); } return; }
void dgc_subg ( const char *ijskip, int *maxgrid, int *imll, int *jmll, int *imur, int *jmur, int *iret ) /************************************************************************ * dgc_subg * * * * This subroutine sets the internal subset grid given the reference * * grid navigation set in GPLT and the map projection set in GPLT. * * If the reference grid is globe wrapping with the addition of an * * extra grid column, then the navigation set in GPLT must be that for * * the grid with the extra column. * * * * The subset grid is larger by five grid points than that strictly * * needed to cover the map projection area. This extension permits * * more accurate computation of derivatives. The subset grid relative * * coordinates of the region strictly needed for the map are returned. * * * * * * IJSKIP is parsed by IN_GSKP. IJSKIP information is entered using * * the following format, where items in square brackets are optional: * * * * IJSKIP = Iskip[;Istart][;Iend][/Jskip[;Jstart][;Jend]], * * * * IJSKIP=Y[ES], or IJSKIP=N[O] * * * * The following rules apply in using IJSKIP input: * * * * 1. If only Iskip is entered, then I and J skips are Iskip. The * * beginning points and ending points are determined by querying * * the display projection to find the area on the reference grid * * needed to cover it. * * * * 2. If any bounding value is omitted, it is determined automatically * * by querying the display projection as in 1 above. * * * * 3. If IJSKIP is blank or NO, skipping is not used to determine the * * internal grid navigation. * * * * 4. If IJSKIP is YES, all skip parameters are determined * * automatically. * * * * dgc_subg ( ijskip, maxgrid, imll, jmll, imur, jmru, iret ) * * * * Input parameters: * * *ijskip const char User input for skip subsetting * * *maxgrid int Maximum grid size * * * * Output parameters: * * *IMLL int Lower left map I bound * * *JMLL int Lower left map J bound * * *IMUR int Upper right map I bound * * *JMUR int Upper right map J bound * * *IRET int Return code * * 0 = normal return * * -37 = no ref grid navigation set* * -38 = glb wrap grd inconsistency* * -39 = map projection is not set * * -40 = subset grd bound error * * -41 = subset grid is too big * * -43 = cannot rearrange grid * * -44 = error set subset grid nav * * -48 = both I bounds required * ** * * Log: * * K. Brill/HPC 08/02 * * K. Brill/HPC 9/02 Also initialize gparmd () to blank * * S. Jacobs/NCEP 11/02 Added check for current nav vs saved nav* * K. Brill/HPC 11/02 Eliminate use of the SUBA logical array * * K. Brill/HPC 12/02 Use IJSKIP input for subset by skipping * * R. Tian/SAIC 3/04 Add check for outflg * * R. Tian/SAIC 5/04 Added call to DG_CONE * * R. Tian/SAIC 2/06 Recoded from Fortran * * S. Gilbert/NCEP 5/07 Added maxgrid argument * ************************************************************************/ { char gprj[5], cnum[5]; float aglt1, agln1, aglt2, agln2, ag1, ag2, ag3, rimn, rjmn, rimx, rjmx, rglt[2], rgln[2], tnav[LLNNAV]; double a, b, c; int lmx, mx, my, imn, jmn, imx, jmx, nx, ny, ix1, ix2, nsx, iy1, iy2, nsy, n, idx, idy, ichk, iadlx, iadly, iadrx, iadry, kxsg, kysg, kxysg, nu, mxnu, imn2, jmn2, imx2, jmx2, iadd, navsz; int nc, tobig, autos, angflg, navflg, done, ishf, ier, ierr, iir, i, k; /* * timing vars */ struct timeb t_gsgprj1, t_gsgprj2, t_gsgprj3, t_gqgprj1, t_gqgprj2, t_gsgprj4, t_setr, t_gqbnd, t_gskp, t_gtrans1, t_mnav, t_cnav, t_cone, t_current; /*----------------------------------------------------------------------*/ *iret = 0; _dgsubg.dgsubg = G_TRUE; for ( i = 0; i < NGDFLS; i++ ) { if ( _nfile.outflg[i] == G_TRUE ) { *iret = -63; return; } } /* * Set LMX to maximum allowed threshold for ijskip=yes */ lmx = LLMXTH; /* * Set the reference grid navigation in GPLT. */ cst_itos ( (int *)(&_dgsubg.refnav[1]), 1, &nc, gprj, &ier ); cst_rmbl ( gprj, gprj, &nc, &ier ); mx = G_NINT ( _dgsubg.refnav[4] ); my = G_NINT ( _dgsubg.refnav[5] ); agln1 = _dgsubg.refnav[7]; if ( _dgfile.addcol == G_TRUE ) { mx += 1; agln2 = _dgsubg.refnav[7]; } else { agln2 = _dgsubg.refnav[9]; } ftime(&t_gsgprj1); gsgprj ( gprj, &_dgsubg.refnav[10], &_dgsubg.refnav[11], &_dgsubg.refnav[12], &mx, &my, &_dgsubg.refnav[6], &_dgsubg.refnav[7], &_dgsubg.refnav[8], &agln2, &ier, strlen(gprj) ); ftime(&t_current); if ( ier != 0 ) { er_wmsg ( "GEMPLT", &ier, " ", &ierr, strlen("GEMPLT"), strlen(" ") ); *iret = -37; return; } else if ( _dgsubg.gwrapg == G_TRUE && ( ! COMPAR ( agln1, agln2 ) && ! COMPAR ( (agln1+360.), agln2 ) ) ) { *iret = -38; return; } /* * Get the shift for re-arranging any globe wrapping grid. * ISHIFT is stored in DGCMN.CMN. */ ftime(&t_setr); grc_setr ( &mx, &my, &_dgsubg.ishift, &ier ); ftime(&t_current); if ( ier == -22 ) { *iret = -39; return; } else if ( ier != 0 ) { *iret = -43; return; } ftime(&t_gqgprj1); gqgprj ( gprj, &ag1, &ag2, &ag3, &mx, &my, &aglt1, &agln1, &aglt2, &agln2, &ier, sizeof(gprj) ); ftime(&t_current); gprj[4] = '\0'; cst_lstr ( gprj, &nc, &ier ); gprj[nc] = '\0'; /* * Get the grid index bounds for the subset grid. */ ftime(&t_gqbnd); gqbnd ( sys_G, &rimn, &rjmn, &rimx, &rjmx, &ier, strlen(sys_D) ); ftime(&t_current); if ( ier != 0 ) { er_wmsg ( "GEMPLT", &ier, " ", &ierr, strlen("GEMPLT"), strlen(" ") ); *iret = -40; return; } imn = (int)rimn; jmn = (int)rjmn; imx = G_NINT ( rimx + .5 ); if ( G_DIFFT((float)((int)rimx), rimx, GDIFFD) ) imx = (int)rimx; jmx = G_NINT ( rjmx + .5 ); if ( G_DIFFT((float)((int)rjmx), rjmx, GDIFFD) ) jmx = (int)rjmx; if ( imn < 1 ) imn = 1; if ( jmn < 1 ) jmn = 1; if ( imx > mx ) imx = mx; if ( jmx > my ) jmx = my; nx = imx - imn + 1; ny = jmx - jmn + 1; if ( nx * ny > lmx ) { tobig = G_TRUE; } else { tobig = G_FALSE; } /* * Check for subsetting by skipping. * * The bounds are returned from IN_GSKP as IMISSD if * not provided. The skip value returned is converted * to a stride value by adding one, i.e. IDX=1 means * no skipping, IDX=2 means skip one point. * * The mathematical relationship stating that the * original number of grid points from IMN to IMX must * equal the number of points skipped plus the number * kept is this: * * (IMX - IMN + 1) = N + (N - 1) * nskip * * where N is the number of points remaining after * skipping and nskip is the number of points skipped * between the points that are kept. * * This equation appears a number of times in various * forms below. */ ftime(&t_gskp); in_gskp ( ijskip, &ix1, &ix2, &nsx, &iy1, &iy2, &nsy, &autos, &ier ); ftime(&t_current); if ( ier != 0 ) { er_wmsg ( "IN", &ier, " ", &iir, strlen("IN"), strlen(" ") ); *iret = -40; return; } if ( ix2 > mx ) { ier = -49; er_wmsg ( "DG", &ier, "I", &iir, strlen("DG"), strlen("I") ); *iret = -40; return; } else if ( iy2 > my ) { ier = -49; er_wmsg ( "DG", &ier, "J", &iir, strlen("DG"), strlen("J") ); *iret = -40; return; } if ( autos == G_TRUE && tobig == G_TRUE ) { a = (double)( lmx - 1 ); b = (double)( nx + ny - 2 * lmx ); c = (double)( lmx - nx * ny ); n = (int)( ( b + sqrt ( b * b - 4. * a * c ) ) / ( 2. * a ) ); nsx = n + 1; nsy = nsx; cst_inch ( nsx, cnum, &ier ); ier = 7; er_wmsg ( "DG", &ier, cnum, &iir, strlen("DG"), strlen(cnum) ); } idx = nsx + 1; idy = nsy + 1; if ( nsx > 0 ) { ichk = nx / nsx; if ( ichk <= 4 ) { ier = 6; er_wmsg ( "DG", &ier, "I", &iir, strlen("DG"), strlen("I") ); } } if ( nsy > 0 ) { ichk = ny / nsy; if ( ichk <= 4 ) { ier = 6; er_wmsg ( "DG", &ier, "J", &iir, strlen("DG"), strlen("J") ); } } /* * Extend the grid bounds if possible. */ iadlx = 0; iadly = 0; iadrx = 0; iadry = 0; imn2 = imn; jmn2 = jmn; imx2 = imx; jmx2 = jmx; iadd = 0; done = G_FALSE; while ( done == G_FALSE && iadd < 5 ) { iadd += 1; if ( imn2 > idx ) { imn2 -= idx; iadlx += idx; } if ( jmn2 > idy ) { jmn2 -= idy; iadly += idy; } if ( imx2 < ( mx - idx ) ) { imx2 += idx; iadrx += idx; } if ( jmx2 < ( my - idy ) ) { jmx2 += idy; iadry += idy; } kxsg = G_NINT ( (float)( imx2 - imn2 + 1 + nsx ) / (float)( 1 + nsx ) ); kysg = G_NINT ( (float)( jmx2 - jmn2 + 1 + nsy ) / (float)( 1 + nsy ) ); kxysg = kxsg * kysg; if ( (kxysg > *maxgrid) && (*maxgrid != IMISSD) ) { done = G_TRUE; if ( imn != imn2 ) { imn = imn2 + idx; iadlx -= idx; } if ( jmn != jmn2 ) { jmn = jmn2 + idy; iadly -= idy; } if ( imx != imx2 ) { imx = imx2 - idx; iadrx -= idx; } if ( jmx != jmx2 ) { jmx = jmx2 - idy; iadry -= idy; } } else { imn = imn2; jmn = jmn2; imx = imx2; jmx = jmx2; } } /* * Adjust extend margins using the stride values. */ iadlx = iadlx / idx; iadrx = iadrx / idx; iadly = iadly / idy; iadry = iadry / idy; /* * Set the I dimension extraction bounds. No shifting * is done if the user provides these bounds. No * extend region is allowed if user provides bounds. */ ishf = _dgsubg.ishift; if ( ix1 > 0 ) { _dgsubg.ishift = 0; iadlx = 0; imn = ix1; } if ( ix2 > 0 ) { _dgsubg.ishift = 0; iadrx = 0; imx = ix2; } if ( ishf != _dgsubg.ishift ) { if ( ix1 < 0 || ix2 < 0 ) { *iret = -48; return; } /* * Reset the grid projection in GPLT. */ mx = G_NINT ( _dgsubg.refnav[4] ); my = G_NINT ( _dgsubg.refnav[5] ); agln1 = _dgsubg.refnav[7]; if ( _dgfile.addcol == G_TRUE ) { mx += 1; agln2 = _dgsubg.refnav[7]; } else { agln2 = _dgsubg.refnav[9]; } ftime(&t_gsgprj2); gsgprj ( gprj, &_dgsubg.refnav[10], &_dgsubg.refnav[11], &_dgsubg.refnav[12], &mx, &my, &_dgsubg.refnav[6], &_dgsubg.refnav[7], &_dgsubg.refnav[8], &agln2, &ier, strlen(gprj) ); ftime(&t_current); ftime(&t_gqgprj2); gqgprj ( gprj, &ag1, &ag2, &ag3, &mx, &my, &aglt1, &agln1, &aglt2, &agln2, &ier, sizeof(gprj) ); ftime(&t_current); if ( diagClbkPtr != NULL ) gprj[4] = '\0'; cst_lstr ( gprj, &nc, &ier ); gprj[nc] = '\0'; ierr = 5; er_wmsg ( "DG", &ierr, " ", &ier, strlen("DG"), strlen(" ") ); } /* * Adjust IMX and IMN for skipping. */ if ( idx > 1 ) { nu = G_NINT ( (float)( imx - imn + 1 + nsx ) / (float)( 1 + nsx ) ); mxnu = nu * ( 1 + nsx ) + imn - 1 - nsx; if ( mxnu > ( mx - idx ) && mxnu != ix2 ) { mxnu = mx; imn = mxnu - nu * ( 1 + nsx ) + 1 + nsx; if ( imn < 1 ) { /* * Start at 1 when full range is needed. */ imn = 1; nu = ( mxnu - imn + 1 + nsx ) / ( 1 + nsx ); mxnu = nu * ( 1 + nsx ) + imn - 1 - nsx; } } imx = mxnu; if ( ( ix2 > 0 && imx != ix2 ) || ( ix1 > 0 && imn != ix1 ) ) { ierr = 4; er_wmsg ( "DG", &ierr, "I", &ier, strlen("DG"), strlen("I") ); } } /* * Set the J dimension extraction bounds. No extend * region is allowed if user provides bounds. */ if ( iy1 > 0 ) { iadly = 0; jmn = iy1; } if ( iy2 > 0 ) { iadry = 0; jmx = iy2; } /* * Adjust JMX and JMN for skipping. */ if ( idy > 1 ) { nu = G_NINT ( (float)( jmx - jmn + 1 + nsy ) / (float)( 1 + nsy ) ); mxnu = nu * ( 1 + nsy ) + jmn - 1 - nsy; if ( mxnu > ( my - idy ) && mxnu != iy2 ) { mxnu = my; jmn = mxnu - nu * ( 1 + nsy ) + 1 + nsy; if ( jmn < 1 ) { /* * Start at 1 when full range is needed. */ jmn = 1; nu = ( mxnu - jmn + 1 + nsy ) / ( 1 + nsy ); mxnu = nu * ( 1 + nsy ) + jmn - 1 - nsy; } } jmx = mxnu; if ( ( iy2 > 0 && jmx != iy2 ) || ( iy1 > 0 && jmn != iy1 ) ) { ierr = 4; er_wmsg ( "DG", &ierr, "J", &ier, strlen("DG"), strlen("J") ); } } /* * Compute subset grid final dimensions. */ kxsg = ( imx - imn + 1 + nsx ) / ( 1 + nsx ); kysg = ( jmx - jmn + 1 + nsy ) / ( 1 + nsy ); if ( kxsg <= 0 || kysg <= 0 ) { *iret = -40; return; } kxysg = kxsg * kysg; /* * Set common block subset coordinates on reference grid. */ _dgsubg.jsgxmn = imn; _dgsubg.jsgymn = jmn; _dgsubg.jsgxmx = imx; _dgsubg.jsgymx = jmx; _dgsubg.jsgxsk = idx; _dgsubg.jsgysk = idy; /* * Set DG_HILO area bounds on subset grid. */ _dgarea.kgxmin = iadlx + 1; _dgarea.kgymin = iadly + 1; _dgarea.kgxmax = kxsg - iadrx; _dgarea.kgymax = kysg - iadry; /* * Strict map bounds are same as above. */ *imll = _dgarea.kgxmin; *jmll = _dgarea.kgymin; *imur = _dgarea.kgxmax; *jmur = _dgarea.kgymax; /* * Set the DGAREA common grid bounds calculation flag. */ _dgarea.jgxmin = 1; _dgarea.jgxmax = kxsg; _dgarea.jgymin = 1; _dgarea.jgymax = kysg; _dgarea.ksub1 = 1; _dgarea.ksub2 = kxysg; /* * Compute grid size and maximum number of internal grids * for the common block. */ if ( (kxysg > *maxgrid) && (*maxgrid != IMISSD) ) { /* * Here is the future location to set up some other * remapping. */ *iret = -41; return; } _dgfile.kxd = kxsg; _dgfile.kyd = kysg; _dgfile.kxyd = kxysg; _dggrid.maxdgg = NDGRD; /* * Compute the navigation of the internal (subset) grid. */ strcpy ( _dgfile.cprj, gprj ); rglt[0] = _dgsubg.jsgxmn; rgln[0] = _dgsubg.jsgymn; rglt[1] = _dgsubg.jsgxmx; rgln[1] = _dgsubg.jsgymx; nc = 2; ftime(&t_gtrans1); gtrans ( sys_G, sys_M, &nc, rglt, rgln, rglt, rgln, &ier, strlen(sys_G), strlen(sys_M) ); ftime(&t_current); if ( G_ABS ( rgln[0] - 180. ) < .01 || G_ABS ( rgln[0] + 180. ) < .01 ) rgln[0] = -180.; if ( G_ABS ( rgln[1] - 180. ) < .01 || G_ABS ( rgln[1] + 180. ) < .01 ) rgln[0] = 180.; if ( G_ABS ( rgln[0] - rgln[1]) < 0.01 ) rgln[1] = rgln[0]; ftime(&t_gsgprj3); gsgprj ( _dgfile.cprj, &ag1, &ag2, &ag3, &_dgfile.kxd, &_dgfile.kyd, &rglt[0], &rgln[0], &rglt[1], &rgln[1], &ier, strlen(_dgfile.cprj) ); ftime(&t_current); if ( ier != 0 ) { if ( _dgsubg.gwrapg == G_TRUE) { ag2 += 180.; if ( ag2 >= 360. ) ag2 -= 360.; ftime(&t_gsgprj4); gsgprj ( _dgfile.cprj, &ag1, &ag2, &ag3, &_dgfile.kxd, &_dgfile.kyd, &rglt[0], &rgln[0], &rglt[1], &rgln[1], &ier, strlen(_dgfile.cprj) ) ; ftime(&t_current); if ( ier != 0 ) { *iret = -44; return; } } else { *iret = -44; return; } } angflg = G_TRUE; ftime(&t_mnav); grc_mnav ( _dgfile.cprj, &_dgfile.kxd, &_dgfile.kyd, &rglt[0], &rgln[0], &rglt[1], &rgln[1], &ag1, &ag2, &ag3, &angflg, tnav, &ier ); ftime(&t_current); /* * Check the current navigation against the saved navigation. * If they are different, then set the navigation flag to False. */ navsz = LLNNAV; ftime(&t_cnav); grc_cnav ( tnav, _dgfile.snav, &navsz, &navflg, &ier ); ftime(&t_current); /* * Save the current navigation. */ for ( k = 0; k < LLNNAV; k++ ) { _dgfile.snav[k] = tnav[k]; } db_retsubgcrs (_dgfile.cprj, _dgfile.kxd, _dgfile.kyd, rglt[0], rgln[0], rglt[1], rgln[1],ag1, ag2, ag3,&ier); /* * Set the constant of the cone for various projections (code * duplicated from UPDCON.FOR in GEMPLT). */ _dgfile.anglr1 = ag1 * DTR; _dgfile.anglr2 = ag2 * DTR; _dgfile.anglr3 = ag3 * DTR; ftime(&t_cone); dg_cone ( _dgfile.cprj, &_dgfile.anglr1, &_dgfile.anglr3, &_dgfile.concon, iret ); ftime(&t_current); /* * Set lat/lon, map scale factor, and rotation matrix * internal grid pointers to zero. */ _dgfile.idglat = 0; _dgfile.idglon = 0; _mapscl.ixmscl = 0; _mapscl.iymscl = 0; _mapscl.ixmsdy = 0; _mapscl.iymsdx = 0; _dgrtwd.irtcos = 0; _dgrtwd.irtsin = 0; _dglndc.lndsea = 0; /* * Initialize orientation angle. */ _dgovec.ornang = RMISSD; /* * Free all existing grids since navigation is changed. */ if ( navflg == G_FALSE ) { dg_fall ( &ier ); } /* * Initialize the origin for M calculation. */ _dgorig.orglat = RMISSD; _dgorig.orglon = RMISSD; _dgorig.orgxpt = RMISSD; _dgorig.orgypt = RMISSD; /* * Since there were no errors, set flag saying dg package has * been initialized. */ _dgfile.dgset = G_TRUE; /* * Initialize the pointer in the internal grid arrays. */ _dggrid.idglst = 0; return; }
void psatim ( char *imgnam, int *xispace0, int *yispace0, int *xispace1, int *yispace1, int *iret ) /************************************************************************ * psatim * * * * This subroutine writes satellite images to the PostScript file. * * It is capable of displaying raw satellite images and remapped images.* * * * psatim ( imgnam, xispace0, yispace0, xispace1, yispace1,iret) * * * * Input parameters: * * *imgnam char Name of image file * * *xispace0 int Left of image in plot coord * * *yispace0 int Top of image in plot coord * * *xispace1 int Right of image in plot coord * * *yispace1 int Bottom of image in plot coord * * * * Output parameters: * * *iret int Return code * * G_NORMAL = normal return * * G_NIMGFL = cannot open img file* * G_NMEMRY = Memory alloc failure* * G_NIMCORD = invalid image coord * * G_BADPXV = bad min/max pxl vals* ** * * Log: * * S. Jacobs/NCEP 12/96 Copied from XSATIM * * S. Jacobs/NCEP 4/97 Removed #define IMGDEF; Changed imgDpy * * to imgDpy and reworked malloc * * S. Jacobs/NCEP 6/99 Added NetCDF file type * * R. Curtis/EAI 8/00 Updated for NetCDF files * * S. Chiswell/Unidata 11/00 Updated for ZLIB compressed NIDS files * * R. Tian/SAIC 05/02 Updated for fax image * * D.W.Plummer/NCEP 3/03 Changes for 10-bit GVAR imagery * * A. Hardy/NCEP 4/04 Modified to display 10-bit VIS imagery * * T. Piper/SAIC 10/05 Dynamically allocate coltrans & rowtrans* * T. Piper/SAIC 08/06 Moved byte swapping to crarea * * T. Piper/SAIC 11/06 Restore coltrans[0] back to original * * X. Guo/CWS 04/10 Added codes to support 94 product * * X. Guo/CWS 05/10 Added IFHINIDS to process 8 bit product * ***********************************************************************/ { int *coltrans, drange, element_size, ier, ierr; int ii, imghght, imgwdth, indx, isGVARRAW; int iwdth, lenp, linestart, ncolors, *rowtrans; int ximage0, ximage1, yimage0, yimage1; char buff[80], dev[] = "PS", hdrstr[1024]; float *fpix, *tmpk; size_t dpysize, imgsize; double dbltmp, doffset, imgratio, plotratio, ratio, sf_hght, sf_wdth; unsigned char *ddptr, *dptr, *imgptr; unsigned char background, datamap[256], *imgDpy; unsigned int col, jj, linesize, newdim, *pix, plothght, plotwdth; unsigned int remainder, row, xhght, xwdth; /*---------------------------------------------------------------------*/ /* * Check the input for valid bounds. Then set the image dimensions. */ if ( ( imtop <= imbot ) || ( imrght <= imleft ) || ( *xispace1 <= *xispace0 ) || ( *yispace1 <= *yispace0 ) ) { *iret = G_NIMCORD; return; } imgwdth = (imrght - imleft) + 1; imghght = (imtop - imbot) + 1; /* * Make sure that plot file is open. Put terminal in vector mode. */ if ( ! opnfil ) { psopen ( iret ); if ( *iret != G_NORMAL ) return; } psplot = G_TRUE; /* * Initialize the image data arrays. */ csinit ( &ier ); /* * Read image data file if this is a new file. */ if ( strcmp ( lastimg.filename, imgnam ) != 0 ) { /* * Allocate image data space. */ imgsize = (size_t)(imnpix * imnlin * imdpth); if ( ( imgData != (unsigned char *)NULL ) && ( imgsize <= lastimg.imgsize ) ) { memset ( (unsigned char *)imgData, 0, imgsize ); } else { if ( imgData != (unsigned char *)NULL ) { free ( imgData ); } imgData = (unsigned char *) calloc ( imgsize, sizeof ( unsigned char ) ); if ( imgData == (unsigned char *)NULL ) { *iret = G_NMEMRY; return; } } /* * Get the image data for the type of image file format. */ switch ( imftyp ) { case IFAREA: /* Area file */ crarea ( imgnam, &ier ); break; case IFGINI: /* AWIPS GINI files */ crgini ( imgnam, &ier ); break; case IFNIDS: /* NIDS radar files */ crnids ( imgnam, &ier ); break; case IFHINIDS: /*Higher Resolution NIDS radar files*/ crnexbz (imgnam, &ier ); break; case IFNOWR: /* WSI NOWRAD radar files */ crnowr ( imgnam, &ier ); break; case IFNCDF: /* NetCDF files */ crncdf ( imgnam, &ier ); break; case IFNEXZ: /* ZLIB NEXRAD files */ crnexz ( imgnam, &ier ); break; case IFNFAX: /* 6-bit FAX product files */ crnfax ( dev, imgnam, &ier ); prtfax ( flun, imnpix, imnlin, xsize, ysize, &ier); return; case IFNEX2: /* NEXRAD Level2 files */ crnex2 ( imgnam, &ier ); break; default: /* Error in format */ ier = G_NIMGFMT; break; } /* * Check for error. Set this file as the 'last' one if OK. */ if ( ier != G_NORMAL ) { *iret = ier; return; } strcpy ( lastimg.filename, imgnam ); lastimg.imgsize = imgsize; } /* * Check image data range. */ if ( immxpx == immnpx ) { *iret = G_BADPXV; return; } /* * Request image area. Set image scaling. */ imgratio = (double)imghght / (double)imgwdth; if ( ( !G_DIFF(rmxysc, 1.0F) ) && ( rmxysc > MNSCAL ) ) { imgratio /= (double)rmxysc; } /* * Compute the plot area. */ plotwdth = (*xispace1 - *xispace0) + 1; plothght = (*yispace1 - *yispace0) + 1; plotratio = (double)plothght / (double)plotwdth; /* * Calculate final image size. * ( ximage0, ximage1, yimage0, yimage1 ) */ if ( plotratio > imgratio ) { /* * If the height to width of the space available for the image * is greater than the height to width of the image, width is * the limiting factor, and scale the height to keep the * appropriate aspect ratio. */ ximage0 = *xispace0; ximage1 = *xispace1; /* * Center the image in the plot area. */ newdim = (unsigned int)((double)plotwdth * imgratio); remainder = plothght - newdim; yimage0 = G_NINT ( (double)*yispace0 - (double)remainder / 2.0 ); yimage1 = G_NINT ( (double)*yispace1 + (double)remainder / 2.0 ); } else { /* * Otherwise, if the height to width of the space available for * the image is less than the height to width of the image, * height is the limiting factor, and scale the width to keep * the appropriate aspect ratio. */ yimage0 = *yispace0; yimage1 = *yispace1; /* * Center the image in the plot area. */ newdim = (unsigned int)((double)plothght / imgratio); remainder = plotwdth - newdim; ximage0 = G_NINT ( (double)*xispace0 + (double)remainder / 2.0 ); ximage1 = G_NINT ( (double)*xispace1 - (double)remainder / 2.0 ); } /* * Final image size. */ xwdth = G_NINT ( (double)((ximage1 - ximage0) + 1) / 32.0 ); xhght = G_NINT ( (double)((yimage1 - yimage0) + 1) / 32.0 ); /* * Construct the mapping from the image data to the final color * pixel index -- datamap[]. */ isGVARRAW = G_FALSE; if ( strcmp ( cmstyp, "GVAR" ) == 0 && strcmp ( cmcalb, "RAW" ) == 0 ) isGVARRAW = G_TRUE; /* * Compute image data range. */ if ( isGVARRAW != G_TRUE ) { dbltmp = pow (2.0, (double)(imdpth * 8) ); } else { /* * Treat GVAR RAW data as 0-255. * (10-bit GVAR count scaled to 8-bit brightness temperature) */ dbltmp = pow(2.0, 8.0); } drange = (int)dbltmp; ncolors = clrbank[imbank].ncolr; ratio = (double)(ncolors - 1) / (double)(immxpx - immnpx); /* * Compute offset for data mapping. */ doffset = (double)immnpx * ratio - 0.5; if ( imdpth < 2 || isGVARRAW == G_TRUE ) { /* * One byte data. */ for ( ii = 0; ii < drange; ii++ ) { if ( ii < immnpx ) datamap[ii] = 0; else if ( ii > immxpx ) datamap[ii] = ncolors - 1; else { if ( ! isGVARRAW == G_TRUE) indx = (int)((double)ii * ratio - doffset); else indx = (int)( (double)(ii * (ncolors-1)) / (double)drange - doffset); datamap[ii] = indx; } } } /* * Fill the column translation array with incremental indices * into the original image columns with respect to the previous * column. Off-image values are set to -1. */ G_MALLOC(coltrans, int, xwdth, "coltrans"); sf_wdth = (double)(imgwdth - 1) / (double)(xwdth - 1); for ( col = 0; col < xwdth; col++ ) { coltrans[col] = (imleft - 1) + (int)(sf_wdth * (double)col + 0.5); if ( coltrans[col] < 0 || coltrans[col] >= imnpix ) { coltrans[col] = -1; } else if ( col != 0 && coltrans[col-1] != -1 ) { coltrans[col] -= (imleft - 1) + (int)(sf_wdth*(double)(col-1) + 0.5); } } /* * Fill the row translation array with indices into the * original image rows. Set off-image values to -1. */ G_MALLOC(rowtrans, int, xhght, "rowtrans"); sf_hght = (double)(imghght - 1) / (double)(xhght -1); for ( row = 0; row < xhght; row++ ) { rowtrans[row] = (imbot - 1) + (int)(sf_hght * (double)row + 0.5); if ( rowtrans[row] < 0 || rowtrans[row] >= imnlin ) { rowtrans[row] = -1; } } /* * Construct the final image for display. */ dpysize = xhght * xwdth; G_CALLOC(imgDpy, unsigned char, (int)dpysize, "imgDpy"); if ( imgDpy == (unsigned char *)NULL ) { G_FREE ( coltrans, int ); G_FREE ( rowtrans, int ); *iret = G_NMEMRY; return; } imgptr = imgDpy; background = 255; *iret = G_NORMAL; element_size = imdpth; linesize = (unsigned int)(imnpix * element_size); /* * Allocate memory for one row/line of pixel data. */ G_MALLOC(pix, unsigned int, xwdth, "pix"); if ( imdpth == 2 && isGVARRAW == G_TRUE ) { G_MALLOC(tmpk, float, xwdth, "tmpk"); G_MALLOC(fpix, float, xwdth, "fpix"); }
void dg_snav ( const float *rnav, int *iret ) /************************************************************************ * dg_snav * * * * This subroutine sets the DGCMN grid navigation related elements for * * the navigation in the input navigation block. * * * * dg_snav ( rnav, iret ) * * * * Input parameters: * * *rnav const float Navigation block * * * * Output parameters: * * *iret int Return code * * 0 = normal return * ** * * Log: * * K. Brill/HPC 02/04 * * R. Tian/SAIC 05/04 Added call to DG_CONE * * R. Tian/SAIC 2/06 Recoded from Fortran * ************************************************************************/ { float ag1, ag2, ag3; int nc, ier; /*----------------------------------------------------------------------*/ *iret = 0; cst_itos ( (int *)(&rnav[1]), 1, &nc, _dgfile.cprj, &ier ); cst_rmbl ( _dgfile.cprj, _dgfile.cprj, &nc, &ier ); _dgfile.kxd = G_NINT ( rnav[4] ); _dgfile.kyd = G_NINT ( rnav[5] ); _dgfile.kxyd = _dgfile.kxd * _dgfile.kyd; ag1 = rnav[10]; ag2 = rnav[11]; ag3 = rnav[12]; /* * Set the constant of the cone for various projections (code * duplicated from UPDCON.FOR in GEMPLT). */ _dgfile.anglr1 = ag1 * DTR; _dgfile.anglr2 = ag2 * DTR; _dgfile.anglr3 = ag3 * DTR; dg_cone ( _dgfile.cprj, &_dgfile.anglr1, &_dgfile.anglr3, &_dgfile.concon, iret ); /* * Set lat/lon, map scale factor, and rotation matrix * internal grid pointers to zero. */ _dgfile.idglat = 0; _dgfile.idglon = 0; _mapscl.ixmscl = 0; _mapscl.iymscl = 0; _mapscl.ixmsdy = 0; _mapscl.iymsdx = 0; _dgrtwd.irtcos = 0; _dgrtwd.irtsin = 0; _dglndc.lndsea = 0; /* * Initialize orientation angle. */ _dgovec.ornang = RMISSD; /* * Initialize the origin for M calculation. */ _dgorig.orglat = RMISSD; _dgorig.orglon = RMISSD; _dgorig.orgxpt = RMISSD; _dgorig.orgypt = RMISSD; return; }