/** * Appends the name of the parameter in a GEMPAK field to a string-buffer. * * Not atomic, * Not idempotent, * Thread-safe * * @param[in,out] buf Pointer to string-buffer. * @param[in] gemInfo Pointer to GEMPAK information on the parameter. * @retval 0 Success. \c buf is set. * @retval 3 System error. */ static int appendParameterName( StringBuf* const buf, const Geminfo* const gemInfo) { char g2name[13]; int nameLen; int status; strncpy(g2name, gemInfo->parm, sizeof(g2name))[sizeof(g2name)-1] = 0; cst_rmbl(g2name, g2name, &nameLen, &status); if (strBuf_getLength(buf)) { if (strBuf_appendString(buf, ";")) { log_add("Couldn't append parameter-name separator"); return 3; } } if (strBuf_appendString(buf, g2name)) { log_add("Couldn't append parameter-name \"%s\"", g2name); return 3; } return 0; }
void gds_mak ( const int *navchg, const float *rnvblk, const int *nnv, int *nbytes, unsigned char *cgds, int *iret ) /************************************************************************ * gds_mak * * * * This subroutine uses the GEMPAK grid navigation block to decide * * which GDS maker to call. * * * * gds_mak ( navchg, rnvblk, nnv, nbytes, cgds, iret ) * * * * Input parameters: * * *navchg const int Flag for navigation change * * *rnvblk const float GEMPAK grid navigation block * * *nnv const int Size of the navigation block * * * * Input and output parameter: * * *nbytes int Input: # of bytes available in * * CGDS * * Output: # of bytes filled in * * CGDS * * * * Output parameters: * * *cgds unsigned char GRIB GDS section * * *iret int Return code * * 0 = normal return * * -75 = map proj not supported * ** * * Log: * * K. Brill/HPC 8/99 * * K. Brill/HPC 3/00 Added NAVCHG flag * * R. Tian/SAIC 9/06 Recoded from Fortran * ************************************************************************/ { int nc, ier; char proj[4]; /*----------------------------------------------------------------------*/ *iret = 0 ; cst_itos ( (int *)&rnvblk[1], 1, &nc, proj, &ier ); cst_rmbl ( proj, proj, &nc, &ier ); /* * Select appropriate GDS maker routine. */ if ( strcmp ( proj, "CED" ) == 0 ) { gds_ced ( rnvblk, nnv, nbytes, cgds, iret ); } else if ( strcmp ( proj, "MER" ) == 0 ) { gds_mer ( rnvblk, nnv, nbytes, cgds, iret ); } else if ( strcmp ( proj, "STR" ) == 0 ) { gds_str ( navchg, rnvblk, nnv, nbytes, cgds, iret ); } else if ( strcmp ( proj, "SCC" ) == 0 ) { gds_lcc ( navchg, rnvblk, nnv, nbytes, cgds, iret ); } else if ( strcmp ( proj, "LCC" ) == 0 ) { gds_lcc ( navchg, rnvblk, nnv, nbytes, cgds, iret ); } else { *iret = -75; } return; }
static void gemInfo_init( Geminfo* const gemInfo, Gribmsg* const gribMsg) { gb2_2gem(&curr_g2, &curr_gem, tbllist, &ier); if (ier != 0) { sprintf(g2name,"UNK\0"); sprintf(levelstmp,"LVL\0"); sprintf(fdats,"FHRS\0"); } else { sprintf(g2name,"%s\0",curr_gem.parm); cst_rmbl (g2name, g2name, &ilen, &ier ); if ( n > 0 ) strncat ( prods, ";", 1); sprintf(prods+strlen(prods),"%s\0",g2name); strptr[0] = (char *)malloc(12); cst_itoc ( &curr_gem.vcord, 1, (char **)(&strptr), &ier); cst_rxbl (curr_gem.unit, curr_gem.unit, &ilen, &ier); if ( ilen == 0 ) sprintf (curr_gem.unit, "-\0"); if ( curr_gem.level[1] == -1 ) sprintf(levelstmp,"%d %s %s\0",curr_gem.level[0],curr_gem.unit,strptr[0]); else sprintf(levelstmp,"%d-%d %s %s\0",curr_gem.level[0],curr_gem.level[1],curr_gem.unit,strptr[0]); cst_rmbl (curr_gem.gdattm1, curr_gem.gdattm1, &ilen, &ier ); cst_rmbl (curr_gem.gdattm2, curr_gem.gdattm2, &ilen, &ier ); if ( ilen > 0 ) sprintf(fdats,"%s-%s\0",curr_gem.gdattm1,curr_gem.gdattm2); else sprintf(fdats,"%s\0",curr_gem.gdattm1); ilen = 1; while ( ilen > 0 ) cst_rmst(fdats, "/", &ilen, fdats, &ier); free(strptr[0]); } }
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; }
/** * Generates an LDM product-identifier from a GRIB edition 2 message. * * Atomic, * Idempotent, * Not thread-safe * * @param[in] data Pointer to the GRIB message. * @param[in] sz Length of the GRIB message in bytes. * @param[in] wmohead Pointer to the associated WMO header string. * @param[out] ident Pointer to a buffer to receive the LDM * product-identifier. * @param[in] identSize Size of the \c ident buffer in bytes. * @retval 0 Success. \c ident is set and NUL-terminated. * @retval 1 Invalid GRIB message. * @retval 2 GRIB message isn't edition 2. * @retval 3 System error. */ int grib2name ( char* const data, const size_t sz, const char* const wmohead, char* const ident, const size_t identSize) { #if USE_GRIB2_DECODER int status; DecodedGrib2Msg* decoded; if (status = g2d_new(&decoded, (unsigned char*)data, sz)) { log_add("Couldn't decode GRIB message"); status = G2D_INVALID == status ? 1 : G2D_NOT_2 ? 2 : 3; } else { if (status = setIdent(ident, identSize, decoded, wmohead)) { log_add("Couldn't set LDM product-identifier"); status = 1; } g2d_free(decoded); } /* "decoded" allocated */ return status; #else static StringBuf* paramNames; /* Buffer for parameter name(s) */ int iField; /* GRIB-2 field index */ int status; /* Function return code */ g2int listsec0[3]; /* GRIB-2 section 0 parameters */ g2int listsec1[13]; /* GRIB-2 section 1 parameters */ g2int numlocal; /* Number of GRIB section 2-s */ int model_id; /* ID of model */ int grid_id; /* ID of grid */ char fdats[80]; /* No idea */ char levelstmp[80]; /* Level? */ Gribmsg g2Msg; /* GRIB-2 message structure */ if (paramNames) { strBuf_clear(paramNames); } else { paramNames = strBuf_new(127); if (NULL == paramNames) { log_add("Couldn't allocate buffer for parameter name(s)"); return 3; } } g2Msg.cgrib2 = (unsigned char*)data; g2Msg.mlength = sz; g2Msg.gfld = NULL; g2Msg.field_tot = 0; if ((status = g2_info(g2Msg.cgrib2, g2Msg.mlength, listsec0, listsec1, &(g2Msg.field_tot), &numlocal)) != 0) return (2 == status) ? 2 : 1; if (g2Msg.field_tot <= 0) { log_add("GRIB-2 message has no data fields"); return 1; } for (iField = 0; iField < g2Msg.field_tot; iField++) { static char g2tables[5][LLMXLN]; /* GRIB tables */ static char* tbllist[5] = {g2tables[0], g2tables[1], g2tables[2], g2tables[3], g2tables[4]}; /* Addresses of GRIB tables */ Geminfo gemInfo; /* GEMPAK structure */ int const lastField = iField == g2Msg.field_tot - 1; status = g2_getfld(g2Msg.cgrib2, g2Msg.mlength, iField+1, 0, 0, &g2Msg.gfld); if (status) { log_add("Invalid GRIB-2 message: g2_getfld() status=%d", status); return (2 == status) ? 2 : 1; } /* "g2Msg.gfld" is allocated */ /* Initialize strings in Geminfo structure */ (void)memset(gemInfo.cproj, 0, sizeof(gemInfo.cproj)); (void)memset(gemInfo.parm, 0, sizeof(gemInfo.parm)); (void)memset(gemInfo.gdattm1, 0, sizeof(gemInfo.gdattm1)); (void)memset(gemInfo.gdattm2, 0, sizeof(gemInfo.gdattm2)); /* * In the original code, the last field determined the model ID. */ if (lastField) model_id = g2Msg.gfld->ipdtmpl[4]; /* * This assignment to "grid_id" isn't under the above "lastField" * conditional because "decode_g2gnum()" might have side-effects upon * which "gb2_2gem()" depends. */ grid_id = (g2Msg.gfld->griddef == 0) ? decode_g2gnum(g2Msg.gfld) : g2Msg.gfld->griddef; gb2_2gem(&g2Msg, &gemInfo, tbllist, &status); if (status) { log_add("Couldn't decode GRIB2 message. WMO header=\"%s\"", wmohead); log_flush_error(); if (lastField) { (void)strcpy(fdats, "FHRS"); /* safe */ (void)strcpy(levelstmp, "LVL"); /* safe */ } } else { char g2name[13]; /**< Name of product/parameter */ int ilen; /**< Length of resulting string */ (void)strcpy(g2name, gemInfo.parm); /* both 13 bytes */ cst_rmbl(g2name, g2name, &ilen, &status); if (iField) strBuf_appendString(paramNames, ";"); strBuf_appendString(paramNames, g2name); cst_rxbl(gemInfo.unit, gemInfo.unit, &ilen, &status); if (ilen == 0) (void)strcpy(gemInfo.unit, "-"); /* safe */ cst_rmbl(gemInfo.gdattm1, gemInfo.gdattm1, &ilen, &status); cst_rmbl(gemInfo.gdattm2, gemInfo.gdattm2, &ilen, &status); /* * In the original code, the last field determined the following * parameters. */ if (lastField) { static char strBuf[5]; /* Holds 4-char string */ static char* strptr = strBuf; /* For "cst_itoc()" */ if (ilen > 0) (void)snprintf(fdats, sizeof(fdats), "%s-%s", gemInfo.gdattm1, gemInfo.gdattm2); else (void)snprintf(fdats, sizeof(fdats), "%s", gemInfo.gdattm1); for (ilen = 1; ilen > 0; cst_rmst(fdats, "/", &ilen, fdats, &status)); cst_itoc(&gemInfo.vcord, 1, &strptr, &status); if (gemInfo.level[1] == -1) (void)snprintf(levelstmp, sizeof(levelstmp), "%d %s %s", gemInfo.level[0], gemInfo.unit, strptr); else (void)snprintf(levelstmp, sizeof(levelstmp), "%d-%d %s %s", gemInfo.level[0], gemInfo.level[1], gemInfo.unit, strptr); } } g2_free(g2Msg.gfld); g2Msg.gfld = NULL; } /* * See if the WMO header can be used for grid 0 products */ if ((grid_id == 0) && (strlen(wmohead) > 11) && (wmohead[7] == 'K') && (wmohead[8] == 'W')) { int wmoGridId = wmo_to_gridid(&wmohead[0], &wmohead[2]); if (wmoGridId > 0) grid_id = wmoGridId; } (void)snprintf(ident, identSize, "grib2/%s/%s/#%03d/%s/%s/%s", s_pds_center((int)listsec1[0], (int)listsec1[1]), s_pds_model((int)listsec1[0], model_id), grid_id, fdats, strBuf_toString(paramNames), levelstmp); return 0; #endif }
void dcflnam ( char *gemfil, char *filnam, int *maxgrids, int *ier) { int itime[3],iaccm; char dattim[DTTMSZ]; char ftmpl[256]; char *cpos; int lens, iret; *ier = 0; gb_ftim ( itime, &iaccm, &iret); /*tg_itoc ( itime, dattim, &iret, sizeof(dattim) - 1 );*/ dattim[0] = '\0'; ctg_itoc ( itime, dattim, &iret); cst_rmbl ( dattim, dattim, &lens, &iret); if((gemfil != NULL)&&(gemfil[0] != '\0')) { strcpy(filnam,gemfil); cfl_mnam ( dattim, gemfil, filnam, &iret); } else { tbtmpl(pds.center,pds.izero,pds.process,pds.grid_id,ftmpl,maxgrids,&iret); if(iret != 0) { *ier = -1; filnam[0] = '\0'; return; } strcpy(filnam,ftmpl); cfl_mnam ( dattim, ftmpl, filnam, &iret); } if((cpos = (char *)strstr(filnam,"@@@")) != NULL) { cpos[0] = 48 + (pds.grid_id / 100); cpos[1] = 48 + ((pds.grid_id / 10)%10); cpos[2] = 48 + (pds.grid_id % 10); } if((cpos = (char *)strstr(filnam,"###")) != NULL) { cpos[0] = 48 + (pds.process / 100); cpos[1] = 48 + ((pds.process / 10)%10); cpos[2] = 48 + (pds.process % 10); } if((cpos = (char *)strstr(filnam,"%%%")) != NULL) { cpos[0] = 48 + (pds.izero / 100); cpos[1] = 48 + ((pds.izero / 10)%10); cpos[2] = 48 + (pds.izero % 10); } if((cpos = (char *)strstr(filnam,"%subc%")) != NULL) { if(pds.izero != 0) { char *subtemp; subtemp = tbsubcenter(&pds.center,&pds.izero); cst_rpst(filnam,"%subc%", subtemp, ftmpl, &iret); } else cst_rpst(filnam,"%subc%", "", ftmpl, &iret); if(iret == 0) sprintf(filnam,"%s\0",ftmpl); } }
void dg_qlyr ( const char *gfunc, int *lflag, int *iret ) /************************************************************************ * dg_qlyr * * * * This subroutine determines if the function specification contains * * a layer-averaged quantity. * * * * dg_qlyr ( gfunc, lflag, iret ) * * * * Input parameters: * * *gfunc const char Grid Function * * * * Output parameters: * * *lflag int Flag for layer quantities * * *iret int Return code * * 0 = normal return * * -3 = GFUNC is blank * ** * * Log: * * T. Lee/SAIC 3/05 Based on GDXCLA * * R. Tian/SAIC 2/06 Recoded from Fortran * ************************************************************************/ { char parms[NPARM][5] = { "LAV(", "LDF(", "MASS", "MDIV", "MSDV", "PVOR", "RICH", "STAB", "LTRN", "VLAV", "VLDF", "QVCL", "WSHR", "BVSQ", "THRM" }; char pfunc[257]; int lens, lnx, i; /*----------------------------------------------------------------------*/ *iret = 0; *lflag = G_FALSE; /* * Check to see if GFUNC was specified. */ cst_lstr ( (char *)gfunc, &lens, iret ); if ( lens == 0 ) { *iret = -3; return; } /* * Convert GFUNC to upper case. */ cst_lcuc ( (char *)gfunc, pfunc, iret ); /* * Remove blanks from pfunc. */ cst_rmbl ( pfunc, pfunc, &lnx, iret ); /* * Check for the occurrence of a layer quantity. */ for ( i = 0; i < NPARM; i++ ) { if ( strstr ( pfunc, parms[i] ) ) { *lflag = G_TRUE; break; } } return; }
void ctb_permccrd ( char *tblnam, char *dirsym, Permclust_t *pc, int *iret ) /************************************************************************ * ctb_permccrd * * * * This routine will read the permanent clustered county table into a * * structure. * * * * ctb_permccrd ( tblnam, dirsym, pc, iret ) * * * * Input parameters: * * *tblnam char Data type table name * * *dirsym char Directory * * * * Output parameters: * * *pc Permclust_t Perm. clustered cnty structure * * *iret int Return code * ** * * Log: * * A. Hardy/NCEP 10/04 copied from ctb_ccrd * * A. Hardy/NCEP 1/05 Added creation of virtual cluster combos* * & added error check on 1st cst_split * ***********************************************************************/ { FILE *ftbl; char buff[256], pcname[32], *next; int ii, jj, ij, in, inx, numclust, fips[50], nfips, len, ier, ierr; int ik, kk, ll, nn, itotal, srchfip, inum, ivfips, cfips[20]; Boolean found, match; static Permclust_t vpc, tpc; /*---------------------------------------------------------------------*/ *iret = 0; /* * Open the table. */ ftbl = cfl_tbop ( tblnam, dirsym, iret ); if ( *iret != 0 ) { tpc.nclust = 0; return; } /* * Get number of valid table entries. */ cfl_tbnr( ftbl, &numclust, &ier ); if ( numclust != 0 ) { /* * Allocate the structure elements. */ tpc.nclust = numclust; tpc.clust = (PCinfo *) malloc( numclust * sizeof(PCinfo) ); } else { /* * Problem opening table file; set error code and return. */ cfl_clos( ftbl, &ier ); *iret = -2; return; } rewind ( ftbl ); /* * For every valid table entry, read in, parse, put in structure */ ii = 0; while ( ii < numclust ) { cfl_trln( ftbl, sizeof(buff), buff, &ier ); if ( ier == 0 ) { next = cst_split ( buff, '|', 4, tpc.clust[ii].pcwfo, &ier ); if ( ier == 0 ) { next = cst_split ( next, '|', 32, pcname, &ier ); tpc.clust[ii].pcname = (char *)malloc( (strlen(pcname)+1) * sizeof(char) ); strcpy ( tpc.clust[ii].pcname, pcname ); cst_rmbl ( next, next, &len, &ier ); cst_ilst ( next, '+', IMISSD, sizeof(fips)/sizeof(fips[0]), fips, &nfips, &ier ); tpc.clust[ii].npc = nfips; tpc.clust[ii].pc = (int *)malloc( nfips * sizeof(int) ); for ( jj = 0; jj < nfips; jj++ ) { tpc.clust[ii].pc[jj] = fips[jj]; } } else { ierr = 3; er_wmsg ( "CTB", &ierr, buff, &ier, 3, strlen (buff) ); } ii++; } } cfl_clos ( ftbl, &ier ); /* * Create virtual clusters. * Allocate the structure elements. */ vpc.nclust = 0; vpc.clust = (PCinfo *) malloc( (numclust*4) * sizeof(PCinfo) ); inum = vpc.nclust; ii = 0; /* * Loop over all perm clusters. */ while ( ii < numclust ) { for ( jj = 1;jj < tpc.clust[ii].npc; jj++ ) { found = False; srchfip = tpc.clust[ii].pc[jj]; /* * Compare search fip value to the other 1st fips codes. * Search permanent table first. */ ij = 0; while ( (!found) && (ij < numclust ) ) { if ( srchfip == tpc.clust[ij].pc[0] ) { found = True; } ij++; } /* * Search virtual cluster table next. */ ij = 0; while ( (!found) && (ij < vpc.nclust ) ) { if ( srchfip == vpc.clust[ij].pc[0] ) { found = True; } ij++; } /* * Didn't find a cluster group with search fip as first key. * Find all cluster groups in perm. table with this key in * the cluster groups. Create a new virtual cluster entry. */ if ( !found ) { cfips[0] = srchfip; ik = 0; /* Loop over rest of current clustered combo fips * and store the codes temporarily. */ for ( ij = 0; ij < tpc.clust[ii].npc;ij++ ) { if ( tpc.clust[ii].pc[ij] != srchfip ) { ik++; cfips[ik] = tpc.clust[ii].pc[ij]; } } /* Set the number of virtual fips codes we have so far*/ ivfips = ik+1; /* * Check rest of perm clusters combox for srchfip. * Start with the next perm cluster combo. */ inx = ii + 1; match = False; /* loop over rest of combo clusters */ for ( kk= inx; kk < numclust; kk++ ) { /* loop over number of counties in each cluster */ for ( ll = 0; ll < tpc.clust[kk].npc; ll++ ) { /* look for a match in a cluster */ if ( tpc.clust[kk].pc[ll] == srchfip ) { /* store all new codes in cfips array */ for ( nn = 0; nn < tpc.clust[kk].npc; nn++ ) { /* loop over current cluster array, store one's we don't have*/ in = 0; while ( (in < ivfips ) && ( !match) ) { if ( tpc.clust[kk].pc[nn] == cfips[in] ) { match = True; } in++; } /* didn't find fips in cfips array, keep it */ if ( !match ) { cfips[ivfips] = tpc.clust[kk].pc[nn]; ivfips++; } match = False; } } } } /* * Put temporary pcname, pcwfo, npc and fips array into * virtual perm clust. combos. * Increment number of virtual fip cluster combos */ strcpy ( vpc.clust[inum].pcwfo, tpc.clust[ii].pcwfo ); vpc.clust[inum].pcname = (char *)malloc( (strlen(pcname)+1) * sizeof(char) ); /* * Store the number of fips codes and the code numbers */ vpc.clust[inum].npc = ivfips; vpc.clust[inum].pc = (int *)malloc( ivfips * sizeof(int) ); for ( ij= 0; ij < ivfips; ij++ ) { vpc.clust[inum].pc[ij] = cfips[ij]; } vpc.nclust++; inum++; } /* (!found) loop */ } /* for jj loop */ ii++; } /* while ii loop */ /* * Fill out output permanent cluster structure. * Allocate the structure elements. */ itotal = numclust + vpc.nclust; pc->nclust = itotal; pc->clust = (PCinfo *) malloc( itotal * sizeof(PCinfo) ); ii = 0; /* * Write out permanent table cluster combos first. */ while ( ii < numclust ) { strcpy (pc->clust[ii].pcwfo, tpc.clust[ii].pcwfo); pc->clust[ii].pcname = (char *)malloc( (strlen(tpc.clust[ii].pcname)+1) * sizeof(char) ); strcpy ( pc->clust[ii].pcname, tpc.clust[ii].pcname ); pc->clust[ii].npc = tpc.clust[ii].npc; pc->clust[ii].pc = (int *)malloc( tpc.clust[ii].npc * sizeof(int) ); for ( jj = 0; jj < pc->clust[ii].npc; jj++ ) { pc->clust[ii].pc[jj] = tpc.clust[ii].pc[jj]; } ii++; } /* * Write out virtual cluster combos next. */ jj = 0; while ( ii < pc->nclust ) { strcpy (pc->clust[ii].pcwfo, vpc.clust[jj].pcwfo); pc->clust[ii].pcname = (char *)malloc( 12 * sizeof(char) ); sprintf ( pc->clust[ii].pcname, "VClust %d", jj+1 ); pc->clust[ii].npc = vpc.clust[jj].npc; pc->clust[ii].pc = (int *)malloc( vpc.clust[jj].npc * sizeof(int) ); for ( ij = 0; ij < pc->clust[ii].npc; ij++ ) { pc->clust[ii].pc[ij] = vpc.clust[jj].pc[ij]; } ii++; jj++; } }
void cst_crnm ( char *str, float *value, int *iret ) /************************************************************************ * cst_crnm * * * * This routine converts a character string to a real number. If the * * conversion fails for any reason (including overflow and underflow), * * RMISSD is returned with an error code of -2. * * * * cst_crnm ( str, value, iret ) * * * * Input parameters: * * *str char String * * * * Output parameters: * * *value float Conversion result * * *iret int Return code * * 0 = normal return * * -2 = conversion error * ** * * Log: * * L. Williams/EAI 4/96 * * M. Linda/GSC 10/97 Corrected the prologue format * * G. Krueger/EAI 11/97 Remove blanks beforehand; Fix RMISSD * * D.W.Plummer/NCEP 8/00 Add check for length of incoming string * * D.W.Plummer/NCEP 6/06 Recode using strtod (chks 'E' exponent) * ***********************************************************************/ { char *buffer, *endptr; int ier, lens; double dval; /*---------------------------------------------------------------------*/ ier = 0; *iret = 0; errno = 0; *value = RMISSD; G_MALLOC ( buffer, char, strlen(str)+1, "cst_crnm - Error allocating buffer" ); /* * remove blanks from string. */ cst_rmbl( str, buffer, &lens, &ier ); dval = strtod( buffer, &endptr ); /* * 'strtod' returns a double but we will be casting to a float. * Therefore, check double value against the float limits first. * Set error code if outside of these limits. */ if ( dval > FLT_MAX || dval < -FLT_MAX || ( dval > 0.0 && dval < FLT_MIN ) || ( dval < 0.0 && dval > -FLT_MIN ) ) { *iret = -2; } else { *value = (float)dval; /* * If the conversion is successful, 'endptr' will point to the * training NULL; otherwise not. Other indicators or conversion * failure lies with 'errno' and the actual value of 'value'. */ if ( endptr[0] != CHNULL || errno != 0 || ( !(*value < HUGE_VAL) && !(*value > HUGE_VAL) ) || ( !(*value < -HUGE_VAL) && !(*value > -HUGE_VAL) ) ) { *value = RMISSD; *iret = -2; } } G_FREE ( buffer, char ); }
void inc_outt ( const char *output, const char *def, int *termflg, int *fileflg, char *filnam, int *iret ) /************************************************************************ * inc_outt * * * * This subroutine processes the OUTPUT variable. The requested output * * types are determined and appropriate flags are set. Output may be * * directed to the terminal and/or a file. OUTPUT will be searched for * * 'T' and 'F' to determine the output devices. If the output devices * * are followed by a slash and a string, the string will be used as the * * name of the output file. If file output is requested and no file * * name is specified, the default will be used. If no valid devices are * * specified, output will be sent to the terminal. If the output * * request contains an 'N' before the slash, no output will be written. * * * * inc_outt ( output, default, termflg, fileflg, filnam, iret ) * * * * Input parameters: * * *output const char Output variable * * *def const char Default file name * * * * Output parameters: * * *termflg int Flag for terminal output * * *fileflg int Flag for file output * * *filnam char Output file name * * *iret int Return code * * 0 = normal return * * -17 = invald input * ** * * Log: * * R. Tian/SAIC 8/06 * * R. Tian/SAIC 1/07 Fixed bug file name has '/' * ************************************************************************/ { char carr[2][LLMXLN], *cp; int len, ier; /*----------------------------------------------------------------------*/ *iret = 0; *termflg = G_FALSE; *fileflg = G_FALSE; carr[0][0] = '\0'; carr[1][0] = '\0'; /* * Break output into two strings separated by /. The string * before the / contains devices; after the / is the file name. */ cp = strchr ( output, '/' ); if ( cp ) { len = (int)( cp - output ); strncpy ( carr[0], output, len ); carr[0][len] = '\0'; strcpy ( carr[1], &output[len+1] ); cst_rmbl ( carr[1], carr[1], &len, &ier ); } else { strcpy ( carr[0], output ); } cst_lcuc ( carr[0], carr[0], &ier ); /* * Check for no output first. */ if ( strchr ( carr[0], 'N' ) ) { return; } /* * Check for terminal output. */ if ( strchr ( carr[0], 'T' ) ) { *termflg = G_TRUE; } /* * Check for output file requested. */ if ( strchr ( carr[0], 'F' ) ) { *fileflg = G_TRUE; if ( carr[1][0] != '\0' ) { strcpy ( filnam, carr[1] ); } else if ( def[0] != '\0' ) { strcpy ( filnam, def ); } else { *iret = -17; return; } } /* * If no valid devices were selected, send output to terminal. */ if ( *termflg == G_FALSE && *fileflg == G_FALSE ) { *termflg = G_TRUE; } return; }
void db_setsubgnav ( float lllat, float lllon, float urlat, float urlon, int *iret ) /************************************************************************ * db_setsubgnav * * * * This subroutine initializes internal sub grid navigation. * * dgc_setsubgnav (lllat, lllon, urlat, urlon, irer ) * * Input parameters: * * lllat float Lower left latitude * * lllon float Lower left Longitude * * urlat float Upper right latitude * * urlon float Upper right Longitude * * Output parameters: * * *iret int Return code * * 0 = normal return * * -46 = invalid grid point * ** * * Log: * * X. Guo 12/04 Initial * ***********************************************************************/ { int nc,ier; char gprj[5]; float rltmin, rlnmin, rltmax, rlnmax; float dlatll, dlonll, dlatur, dlonur; /*----------------------------------------------------------------------*/ *iret = 0; cst_itos ( (int *)&_dgsubg.refnav[1], 1, &nc, gprj, &ier ); cst_rmbl ( gprj, gprj, &nc, &ier ); /* * Define sub-grid area */ rltmin = G_MIN ( lllat, urlat ); rlnmin = G_MIN ( lllon, urlon ); rltmax = G_MAX ( lllat, urlat ); rlnmax = G_MAX ( lllon, urlon ); /* * Take care of the sub-grid area across the date-line */ if ( ( rlnmax - rlnmin ) > 180. ) { dlatll = rltmin; dlonll = rlnmax; dlatur = rltmax; dlonur = rlnmin; } else { dlatll = rltmin; dlonll = rlnmin; dlatur = rltmax; dlonur = rlnmax; } /* * *Set internal sub-grid navigation */ gsmprj ( gprj, &_dgsubg.refnav[10], &_dgsubg.refnav[11], &_dgsubg.refnav[12], &dlatll, &dlonll, &dlatur, &dlonur, &ier, strlen(gprj) ); /* * IF set sub-grid navigation fail, change center longitude */ if ( ier != 0 ) { *iret = -46; } }
void ctb_rdprf ( char *tblnam, char *dirsym, char *tag, char *value, int *iret ) /************************************************************************ * ctb_rdprf * * * * This subroutine reads a prefs table and returns a single value * * associated with a single tage in the table. * * * * ctb_rdprf ( tblnam, dirsym, tag, value, iret ) * * * * Input parameters: * * *tblnam char Prefs table file name * * *dirsym char Lowest level directory name * * *tag char Tags for prefs table definition * * * * Output parameters: * *value char Value for prefs table tag * * *iret int Return code * * -1 = table cannot be opened * * -2 = entry not found * ** * * Log: * * M. Li/SAIC 10/04 Modified from ctb_rdwou * ***********************************************************************/ { FILE *ftbl; char chname[25], label[120], buffer[180]; int ier, ilen2, lens; Boolean found; /*---------------------------------------------------------------------*/ /* * Initialize output variables. */ *iret = -2; ilen2 = 0; chname[0] = '\0'; label[0] = '\0'; value[0] = '\0'; found = False; /* * Open the prefs table file. */ ftbl = cfl_tbop ( tblnam, dirsym, &ier ); if ( ier != 0 ) { *iret = -1; return; } cst_lstr ( tag, &lens, &ier ); /* * Read in the next record, check for a comment, * and process valid table entries. */ while ( ( fgets ( buffer, 180, ftbl ) != NULL ) && ( !found ) ) { if ( buffer[0] != '!' ) { if ( sscanf ( buffer,"%s %s", chname, label) ) { cst_rmbl ( chname, chname, &ilen2, &ier ); cst_lstr ( label, &lens, &ier ); if (strcmp ( chname, tag ) == 0 ) { cst_ncpy ( value, label, lens, &ier ); found = True; *iret = 0; } else { chname[0] = '\0'; label[0] = '\0'; } } } } if ( !found ) { *iret = -2; } cfl_clos ( ftbl, &ier ); }
void dgc_vecr ( const char *gdattm, const char *glevel, const char *gvcord, const char *gvect, char *pfunc, float *ugrid, float *vgrid, int *igx, int *igy, char *time1, char *time2, int *level1, int *level2, int *ivcord, char *parmu, char *parmv, int *iret ) /************************************************************************ * dgc_vecr * * * * This subroutine computes a grid diagnostic vector quantity. The * * u and v components returned in UGRID and VGRID are in grid relative * * coordinates. GDATTM, GLEVEL, GVCORD and GVECT should have the * * values entered by the user. * * * * dgc_vecr ( gdattm, glevel, gvcord, gvect, pfunc, ugrid, vgrid, igx, * * igy, time1, time2, level1, level2, ivcord, parmu, parmv, * * iret ) * * * * Input parameters: * * gdattm const char Input date/time * * glevel const char Input level * * gvcord const char Input vertical coordinate * * gvect const char Diagnostic function * * * * Output parameters: * * pfunc char Diagnostic error string * * ugrid float Output u component grid * * vgrid float Output v component grid * * igx int Number of points in x dir * * igy int Number of points in y dir * * time1 char Output date/time * * time2 char Output date/time * * level1 int Output level * * level2 int Output level * * ivcord int Output vertical coordinate * * parmu char Parameter name for u component * * parmv char Parameter name for v component * * iret int Return code * * 3 = user typed EXIT * * 0 = normal return * * -3 = parsing table is empty * * -5 = output grid not a vector * * -6 = wrong number of operands * * -7 = grid cannot be found * * -8 = grid is the wrong size * * -9 = incorrect operands * * -10 = internal grid list full * * -11 = operand must be a vector * * -12 = operand must be a scalar * * -13 = operand must be from file * * -14 = DG_INIT not initialized * * -15 = polar grid cent. not valid* * -16 = map proj is invalid * * -17 = LEVEL must be a layer * * -18 = TIME must be a range * * -19 = invalid operator * * -20 = stack is full * * -21 = stack is empty * * -22 = TIME is invalid * * -23 = LEVEL is invalid * * -24 = IVCORD is invalid * * -26 = layer of layers invalid * * -27 = time range layer invalid * * -47 = internal grid is too big * * -70 = cannot computer ensemble * * -71 = cannot computer layer * ** * * Log: * * M. desJardins/GSFC 10/85 * * M. desJardins/GSFC 4/86 Cleaned up errors; add GR_FIND * * M. desJardins/GSFC 5/88 Documentation * * G. Huffman/GSC 9/88 Error messages * * M. desJardins/GSFC 4/89 Added grid rel and north rel subs * * S. Schotz/GSFC 6/90 Removed respnd flag * * M. desJardins/NMC 3/92 Removed scale from common * * K. Brill/NMC 5/93 Initialize the grid-in-use flag * * K. Brill/NMC 5/93 Capitalize GDATTM,GLEVEL,GVCORD,GFUNC * * L. Sager/NMC 7/93 Permit vector grid rename * * M. desJardins/NMC 7/93 Eliminate ; as separator for name * * L. Sager/NMC 8/93 Correct misstore of GDATTIM * * T. Lee/GSC 4/96 Changed NDGRD to maxdgg; single * * dimension for dgg * * K. Tyle/GSC 5/96 Moved IGDPT outside do-loop * * K. Brill/HPC 11/01 Change for IUSESV replacing USEFLG * * K. Brill/HPC 12/01 Initialize ISUBID * * K. Brill/HPC 11/02 Check for KXYD > LLMXGD * * K. Brill/HPC 5/03 Falsify SAVFLG for previous grids saved * * with the same name using // * * T. Lee/SAIC 12/04 Added ensemble function * * T. Lee/SAIC 3/05 Added layer diagnostic * * R. Tian/SAIC 3/06 Recoded from Fortran * * S. Gilbert/NCEP 7/07 Removed LLMXGD limit check * * H. Zeng/SAIC 08/07 Initialized output variables * ************************************************************************/ { char carr1[133], carr2[13], ctst[13], gf[133], gvc[5], glv[LLMXLN+1]; char *savptr; int ng, itype, num, numu, numv, zero, i, ier; /*----------------------------------------------------------------------*/ /* * Initialize output parameters. */ pfunc[0] = '\0'; *ugrid = 0.0F; *vgrid = 0.0F; *igx = 0; *igy = 0; time1[0] = '\0'; time2[0] = '\0'; *level1 = 0; *level2 = 0; *ivcord = 0; parmu[0] = '\0'; parmv[0] = '\0'; /* * Initialize constant variables. */ zero = 0; /* * Check that the diagnostic package has been initialized. */ if ( _dgfile.dgset == G_FALSE ) { *iret = -14; return; } else { *iret = 0; } /* * If GFUNC includes both layer and ensemble diagnostics, * return with an error for now. */ cst_rmbl ( (char *)gvect, gf, &ng, &ier ); cst_lcuc ( gf, gf, &ier ); if ( strstr ( gf, "ENS_" ) && strstr ( gf, "LYR_" ) ) { *iret = -72; return; } /* * Break gvect into two strings separated at //. */ savptr = strstr ( gf, "//" ); if ( ! savptr ) { strcpy ( carr1, gf ); carr2[0] = '\0'; } else { ng = (int)(savptr - gf ); strncpy ( carr1, gf, ng ); carr1[ng] = '\0'; strcpy ( carr2, savptr + 2 ); } /* * Initialize subroutine ID # & the grid-in-use flag. */ _dggrid.isubid = 0; for ( i = 0; i < _dggrid.maxdgg; i++ ) { _dggrid.iusesv[i] = 0; } /* * Increment subroutine ID. */ dg_ssub ( &ier ); /* * Save date/time, level and vertical coordinate in common. */ cst_lcuc ( (char *)gvcord, gvc, &ier ); cst_lcuc ( (char *)glevel, glv, &ier );; dg_stlv ( gdattm, glv, gvc, "GVECT", carr1, iret ); if ( *iret != 0 ) { dg_esub ( &zero, &zero, &zero, &zero, &ier ); return; } /* * Compute the layer function. */ dl_driv ( carr1, iret ); if ( *iret != 0 ) { dg_esub ( &zero, &zero, &zero, &zero, &ier ); *iret = -71; return; } /* * Compute the ensemble function. */ de_driv ( carr1, iret ); if ( *iret != 0 ) { dg_esub ( &zero, &zero, &zero, &zero, &ier ); *iret = -70; return; } /* * Parse the input function. */ dg_pfun ( carr1, iret ); if ( *iret != 0 ) { dg_esub ( &zero, &zero, &zero, &zero, &ier ); return; } /* * Compute the output grid. */ itype = 2; dg_driv ( &itype, iret ); if ( *iret != 0 ) { strcpy ( pfunc, _dgerr.errst ); dg_esub ( &zero, &zero, &zero, &zero, &ier ); return; } /* * Retrieve the output grids from the stack. */ num = _dgstck.istack[0]; numu = num / 100; numv = num - numu * 100; if ( ( _dgstck.itop != 0 ) || ( numu <= 0 ) || ( numv <= 0 ) ) { *iret = -5; dg_esub ( &zero, &zero, &zero, &zero, &ier ); return; } if ( carr2[0] != '\0' ) { /* * Falsify the SAVFLG for grids also having the name * stored in CARR2. */ for ( i = 0; i < _dggrid.maxdgg; i++ ) { strcpy ( ctst, "U" ); strcat ( ctst, carr2 ); if ( strcmp ( _dggrid.gparmd[i], ctst ) == 0 ) _dggrid.savflg[i] = G_FALSE; strcpy ( ctst, "V" ); strcat ( ctst, carr2 ); if ( strcmp ( _dggrid.gparmd[i], ctst ) == 0 ) _dggrid.savflg[i] = G_FALSE; } _dggrid.savflg[numu-1] = G_TRUE; _dggrid.savflg[numv-1] = G_TRUE; strcpy ( _dggrid.gparmd[numu-1], "U" ); strcat ( _dggrid.gparmd[numu-1], carr2 ); strcpy ( _dggrid.gparmd[numv-1], "V" ); strcat ( _dggrid.gparmd[numv-1], carr2 ); } /* * Move u- and v- components into output arrays. */ for ( i = 0; i < _dgfile.kxyd; i++ ) { ugrid[i] = _dggrid.dgg[numu-1].grid[i]; vgrid[i] = _dggrid.dgg[numv-1].grid[i]; } /* * Get output variables. */ *igx = _dgfile.kxd; *igy = _dgfile.kyd; strcpy ( time1, _dggrid.dttimd1[numu-1] ); strcpy ( time2, _dggrid.dttimd2[numu-1] ); *level1 = _dggrid.leveld1[numu-1]; *level2 = _dggrid.leveld2[numu-1]; *ivcord = _dggrid.ivcrdd[numu-1]; strcpy ( parmu, _dggrid.gparmd[numu-1] ); strcpy ( parmv, _dggrid.gparmd[numv-1] ); if ( strcmp ( parmu, "UOBS" ) == 0 ) strcpy ( parmu, "UREL" ); if ( strcmp ( parmv, "VOBS" ) == 0 ) strcpy ( parmv, "VREL" ); /* * Free the internal grid. */ dg_esub ( &zero, &zero, &zero, &zero, &ier ); return; }
void clo_blasso ( char *bndtyp, char *key, int *npts, char *btags, gpc_polygon *union_poly, int *iret ) /************************************************************************ * clo_blasso * * * * This function takes a string of bound tags, semi-colon separated, and* * returns a polygon structure from the union of the polygons designated* * by the bound tags. A return code of 1 due to a bad bounds key tag * * could mean the tag name (eg., <FIPS>) is invalid and/or the tag value* * (eg., 51059 -- a FIPS code) is invalid. Processing continues, so the* * invoking routine may also want to check the number of polygons for 0,* * in which case it would most likely be caused by an invalid tag name. * * * * Note that the tag name may or may not be enclosed with '<' and '>'. * * If it is not, they will be added to the tag name. * * * * clo_blasso ( bndtyp, key, npts, btags, union_poly, iret ) * * * * Input parameters: * * *bndtyp char Bounds file alias name (eg., WBCMZ_BNDS)* * *key char Search tag name in bounds file * * (eg., <FIPS> or FIPS, <STATE> or STATE)* * *npts int No. of bounds tag values in string btags* * *btags char Bounds tag values, delimited by ";" * * (eg., 51059;51057;51053) * * * * Output parameters: * * *union_poly gpc_polygon GPC polygon structure of union * * iret int Return code * * = 0 Normal * * = 1 No bound area found for a tag * * due to bad tag name or value * * = -1 Bounds file open error return * * or illegal bounds name * * * ** * * Log: * * F. J. Yen/NCEP 1/05 * * F. J. Yen/NCEP 2/05 Increased size of btagkey; Enclosed tag * * name with '<' and '>' if missing. * * J. Wu/SAIC 6/05 remove reference to LLMXPT * * F.Yen&D.Plummer/NCEP 7/05 Redesigned for performance. * * D.W.Plummer/NCEP 8/05 Add final GPC_UNION to rm spurious pts * ***********************************************************************/ { char **arrptr, btagkey[80]; char *tag_start = { "<" }; char *tag_end = { ">" }; int ii, maxexp, minp, ier, ierro, mxpts, end; int narr, numTmp, len, hole, initl; float *xTmp, *yTmp; float rlatmn, rlonmn, dlatmx, dlonmx, filter; gpc_polygon polygon; gpc_vertex_list verts; /*---------------------------------------------------------------------*/ *iret = 0; ier = 0; minp = 0; hole = 0; filter = 0.0; maxexp = 400; /* * Initalize the gpc polygon structure variables */ union_poly->num_contours = 0; union_poly->hole = (int *)NULL; union_poly->contour = (gpc_vertex_list *)NULL; clo_bstype ( bndtyp , &ier ); /* Set the bounds file */ if ( ier != 0 ) { *iret = -1; return; } /* * Set the bounds area */ rlatmn = -90.0; dlatmx = +90.0; rlonmn = -180.0; dlonmx = +180.0; clo_bsarea ( &rlatmn, &rlonmn, &dlatmx, &dlonmx, &ier ); /* * Initialize the clo library */ clo_init ( &ier); /* * Allocate memory */ clo_qmxpts ( "BOUNDS", &mxpts, &ier ); G_MALLOC ( xTmp, float, mxpts, "CLO_BLASSO" ); G_MALLOC ( yTmp, float, mxpts, "CLO_BLASSO" ); /* * Break apart the bounds tag values */ arrptr = (char **)malloc(*npts * sizeof(char *)); for (ii = 0; ii < *npts; ii++) { arrptr[ii] = (char *) malloc(maxexp); } cst_clst ( btags, ';', " ", *npts, maxexp, arrptr, &narr, &ier ); /* * initialize single bounds polygon */ polygon.num_contours = 0; polygon.hole = (int *)NULL; polygon.contour = (gpc_vertex_list *)NULL; /* * Loop over bounds tag values */ for (ii=0;ii < narr; ii++) { cst_rmbl ( arrptr[ii], arrptr[ii], &len, &ier ); if ( len > 0 ) { ierro = 0; /* * Create the key tag to search on ( eg. <FIPS>51097 ). First, * check for '<' at beginning of tag. Add it if it isn't there. */ btagkey[0] = '\0'; if( key[0] != '<' ) { strcpy( btagkey, tag_start ); } strcat ( btagkey, key ); /* * Check for '>' at end of key tag. Add it if it isn't there. */ end = strlen ( key ); if ( key [ end - 1 ] != '>' ) { strcat ( btagkey, tag_end ); } strcat ( btagkey, arrptr[ii]); clo_bstype ( bndtyp , &ier ); /* Set the bounds file */ clo_bstag ( btagkey, &ier ); /* Set the bounds key tag (eg <FIPS>51097 ) */ /* * Find the bound key tag polygon */ initl = 1; while ( ierro == 0 ) { /* * Get next bounds */ clo_bgnext (&minp, &mxpts, &filter, &numTmp, xTmp, yTmp, &ierro ); if ( initl == 1 ) { initl = 0; if ( ierro != 0 ) { /* * No bound area (polygon) found for current bounds * key tag in btagkey due to either an invalid tag * name (eg, <FIPS> or <STATE>) and/or invalid tag * value (ie, if the tag name is <FIPS>, the tag * value would be a FIPS code such as 13009). */ *iret = 1; } } if ( ierro == 0 ) { /* * initialize vertex list */ verts.vertex = (gpc_vertex*)NULL; verts.num_vertices =0; gpc_cvlist (numTmp, xTmp, yTmp, &verts, &ier ); gpc_add_contour ( &polygon, &verts, hole); free ( verts.vertex ); } } /* end for while loop */ } /* end for length check */ } /* end for loop */ /* * union the polygon with a NULL polygon (union) to get the union */ gpc_polygon_clip (GPC_UNION, &polygon, union_poly, union_poly ); gpc_free_polygon ( &polygon); gpc_polygon_clip (GPC_UNION, &polygon, union_poly, union_poly ); /* * Free memory space. */ G_FREE ( xTmp, float ); G_FREE ( yTmp, float ); for ( ii = 0; ii < *npts; ii++ ) { free ( arrptr[ii] ); } free ( arrptr); }
void shp_gkey ( shp_record *onerec, char *reckey, int *iret ) /************************************************************************ * shp_gkey * * * * This function gets the record key in order to combine those * * records with the same key. * * * * shp_gkey ( onerec, reckey, iret ) * * * * Input parameters: * * *onerec shp_record One shape record * * * * Output parameters: * * *reckey char Record key * * *iret int Return code * * 0 = Normal * ** * * Log: * * R. Tian/SAIC 3/04 Initial coding * * R. Tian/SAIC 2/05 Added MAP_FIRE/RECR/CWAB * * R. Tian/SAIC 4/05 Added MAP_RFCB * * R. Tian/SAIC 6/05 Added MAP_TMZN/USST * * S. Jacobs/NCEP 4/10 Added MAP_NPSA * * S. Jacobs/NCEP 3/11 Changed keys for MAP_MZCN * * X. Guo/CWS 9/11 Changed SHAPE_LENG to COUNTYNAME* * X. Guo/CWS 4/12 Changed AREA to Shape_Area for * * MAP_NPSA * ***********************************************************************/ { char stabbr[3]; int ifips, izone, istno; int ifld, jfld; int len, ier; static long seqnum = 0; /*---------------------------------------------------------------------*/ *iret = 0; seqnum++; switch ( maptyp ) { case MAP_CNTY: /* * County. */ for ( ifld = 0; ifld < onerec->numfld; ifld++ ) { if ( strncmp ( onerec->fields[ifld].name, "FIPS", strlen("FIPS") ) == 0 ) { ifips = strtol ( onerec->fields[ifld].data, NULL, 10 ); if ( ifips == 0 ) { *iret = 1; } sprintf ( reckey, "%d", ifips ); break; } } break; case MAP_MARI: /* * Marine. */ for ( ifld = 0; ifld < onerec->numfld; ifld++ ) { if ( strncmp ( onerec->fields[ifld].name, "ID", strlen("ID") ) == 0 ) { strncpy ( reckey, onerec->fields[ifld].data, 6 ); reckey[6] = '\0'; if ( strlen ( reckey ) == (size_t)0 ) { *iret = 1; } break; } } break; case MAP_MZCN: /* * Combined marine-county. */ for ( jfld = 0; jfld < onerec->numfld; jfld++ ) { if ( strncmp ( onerec->fields[jfld].name, "COUNTYNAME", strlen("COUNTYNAME") ) == 0 ) { /* * County. */ for ( ifld = 0; ifld < onerec->numfld; ifld++ ) { if ( strncmp ( onerec->fields[ifld].name, "FIPS", strlen("FIPS") ) == 0 ) { ifips = strtol ( onerec->fields[ifld].data, NULL, 10 ); if ( ifips == 0 ) { *iret = 1; } sprintf ( reckey, "%d", ifips ); break; } } break; } else if ( strncmp ( onerec->fields[jfld].name, "NAME", strlen("NAME") ) == 0 ) { /* * Marine. */ for ( ifld = 0; ifld < onerec->numfld; ifld++ ) { if ( strncmp ( onerec->fields[ifld].name, "ID", strlen("ID") ) == 0 ) { strncpy ( reckey, onerec->fields[ifld].data, 6 ); reckey[6] = '\0'; if ( strlen ( reckey ) == (size_t)0 ) { *iret = 1; } break; } } break; } } break; case MAP_ZONE: case MAP_FIRE: /* * Public Forecast Zones and Fire Weather Zone. */ for ( ifld = 0; ifld < onerec->numfld; ifld++ ) { if ( strcmp ( onerec->fields[ifld].name, "STATE" ) == 0 ) { strcpy ( stabbr, onerec->fields[ifld].data ); } else if ( strncmp ( onerec->fields[ifld].name, "ZONE", strlen("ZONE") ) == 0 ) { izone = strtol ( onerec->fields[ifld].data, NULL, 10 ); } } for ( istno = 0; istno < NUMSTNO; istno++ ) { if ( strncmp ( stateno[istno], stabbr, 2 ) == 0 ) { break; } } if ( istno == NUMSTNO ) { *iret = 1; return; } ifips = istno * 10000 + izone * 10; sprintf ( reckey, "%d", ifips ); break; case MAP_IEDG: /* * Ice Edge. */ sprintf ( reckey, "%ld", seqnum ); break; case MAP_RFCR: /* * River Forecast Center Regions. */ for ( ifld = 0; ifld < onerec->numfld; ifld++ ) { if ( strncmp ( onerec->fields[ifld].name, "BASIN_ID", strlen("BASIN_ID") ) == 0 ) { strncpy ( reckey, onerec->fields[ifld].data, 5 ); reckey[5] = '\0'; cst_rmbl ( reckey, reckey, &len, &ier ); if ( len == 0 ) { *iret = 1; } break; } } break; case MAP_CWAB: /* * County Warning Area. */ for ( ifld = 0; ifld < onerec->numfld; ifld++ ) { if ( strncmp ( onerec->fields[ifld].name, "WFO", strlen("WFO") ) == 0 ) { strncpy ( reckey, onerec->fields[ifld].data, 3 ); reckey[3] = '\0'; cst_rmbl ( reckey, reckey, &len, &ier ); if ( len == 0 ) { *iret = 1; } break; } } break; case MAP_RFCB: /* * River Forecast Center Basins. */ for ( ifld = 0; ifld < onerec->numfld; ifld++ ) { if ( strncmp ( onerec->fields[ifld].name, "ID", strlen("ID") ) == 0 ) { strncpy ( reckey, onerec->fields[ifld].data, 8 ); reckey[8] = '\0'; cst_rmbl ( reckey, reckey, &len, &ier ); if ( len == 0 ) { sprintf ( reckey, "%ld", seqnum ); } break; } } break; case MAP_TMZN: /* * Time Zone. */ for ( ifld = 0; ifld < onerec->numfld; ifld++ ) { if ( strncmp ( onerec->fields[ifld].name, "TIMEZONE", strlen("TIMEZONE") ) == 0 ) { strcpy ( reckey, onerec->fields[ifld].data ); cst_rmbl ( reckey, reckey, &len, &ier ); if ( len == 0 ) { sprintf ( reckey, "%ld", seqnum ); } break; } } break; case MAP_USST: /* * US State and Territories. */ for ( ifld = 0; ifld < onerec->numfld; ifld++ ) { if ( strncmp ( onerec->fields[ifld].name, "FIPS", strlen("FIPS") ) == 0 ) { ifips = strtol ( onerec->fields[ifld].data, NULL, 10 ); if ( ifips == 0 ) { *iret = 1; } sprintf ( reckey, "%d", ifips ); break; } } break; case MAP_NPSA: /* * Predictive Service Areas */ for ( ifld = 0; ifld < onerec->numfld; ifld++ ) { if ( strncmp ( onerec->fields[ifld].name, "Shape_Area", strlen("Shape_Area") ) == 0 ) { strncpy ( reckey, onerec->fields[ifld].data, 19 ); reckey[19] = '\0'; if ( strlen ( reckey ) == (size_t)0 ) { *iret = 1; } break; } } break; } }
static void bnd_tmzn ( shp_record *onerec, char *header, char *subhdr, char *hdrnam, float *cenlat, float *cenlon, int *iret ) /************************************************************************ * bnd_tmzn * * * * This function generates the time zone boundaries bound header and * * sub-header lines. * * * * bnd_tmzn ( onerec, header, subhdr, hdrnam, cenlat, cenlon, iret ) * * * * Input parameters: * * *onerec shp_record One shape record * * * * Output parameters: * * *header char Bound header line * * *subhdr char Bound sub-header line * * *hdrnam char Bound header name * * *cenlat float Center latitude * * *cenlon float Center longitude * * *iret int Return code * * 0 = Normal * * 1 = Incomplete record * ** * * Log: * * R. Tian/SAIC 6/05 Initial coding * ***********************************************************************/ { char tzname[80], symbol[80], gmt_offset[80], gmt_dst_offset[80]; int iclat, iclon, nparts, ifld; int len, ier; static int seqnum = 0; /*---------------------------------------------------------------------*/ *iret = 0; seqnum++; nparts = onerec->numprt; for ( ifld = 0; ifld < onerec->numfld; ifld++ ) { if ( strncmp ( onerec->fields[ifld].name, "TIMEZONE", strlen("TIMEZONE") ) == 0 ) { strcpy ( tzname, onerec->fields[ifld].data ); cst_rmbl ( tzname, tzname, &len, &ier ); } else if ( strncmp ( onerec->fields[ifld].name, "SYMBOL", strlen("SYMBOL") ) == 0 ) { strcpy ( symbol, onerec->fields[ifld].data ); cst_rmbl ( symbol, symbol, &len, &ier ); } else if ( strncmp ( onerec->fields[ifld].name, "GMT_OFFSET", strlen("GMT_OFFSET") ) == 0 ) { strcpy ( gmt_offset, onerec->fields[ifld].data ); cst_rmbl ( gmt_offset, gmt_offset, &len, &ier ); } else if ( strncmp ( onerec->fields[ifld].name, "GMT_DST_OF", strlen("GMT_DST_OF") ) == 0 ) { strcpy ( gmt_dst_offset, onerec->fields[ifld].data ); cst_rmbl ( gmt_dst_offset, gmt_dst_offset, &len, &ier ); } } iclat = (int)(ROUNDUP(onerec->cenlat)*100.); iclon = (int)(ROUNDUP(onerec->cenlon)*100.); *cenlat = onerec->cenlat; *cenlon = onerec->cenlon; sprintf ( header, "B%5.5d %-32.32s %5d %6d %3d %s", seqnum, tzname, iclat, iclon, nparts, symbol ); sprintf ( subhdr, "<TIME_ZONE>%s<GMT_OFFSET>%s<GMT_DST_OFFSET>%s", tzname, gmt_offset, gmt_dst_offset ); sprintf ( hdrnam, "%s", tzname ); }
int rsrc_readFile ( char *fname ) /************************************************************************ * rsrc_readFile * * * * This function opens an NMAP resource file and read it into memory. * * * * int rsrc_readFile(fname) * * * * Input parameters: * * *fname char resource filename * * * * Output parameters: * * NONE * * * * Return parameters: * * int 0 = successful * * -1 = file can not be opened * * -2 = syntax error * * * ** * * Log: * * C. Lin/EAI 9/96 * * C. Lin/EAI 1/97 add check after cfl_trln * ***********************************************************************/ { FILE *fp; char buffer[LINE_BUF], *ptr, *ptr1; int len, iret; rsrc_t *current, *next; /*---------------------------------------------------------------------*/ /* * free the previous resource when necessary */ if ( _rsrcTbl ) { current = _rsrcTbl; while(current) { next = current->next; free((rsrc_t *)current); current = next; } _rsrcTbl = NULL; } /* * open resource file */ fp = cfl_tbop(fname, "nmap", &iret); if (iret != 0) { return(-1); } else { /* parse each line */ while ( ! feof(fp) ) { cfl_trln(fp, LINE_BUF, buffer, &iret); if ( iret == 0 ) { if ( strstr(buffer, "=") == NULL ) continue; if ( _rsrcTbl == NULL ) { /* head */ _rsrcTbl = current = (rsrc_t *)malloc(sizeof(rsrc_t)); } else { current->next = (rsrc_t *)malloc(sizeof(rsrc_t)); current = current->next; } /* * get the name */ ptr = &buffer[0]; while ( *ptr == ' ' || *ptr == '\t' ) ptr++; /* remove leading space */ ptr1 = current->name; while ( *ptr && *ptr != '=' ) *ptr1++ = *ptr++; *ptr1 = '\0'; cst_rmbl(current->name, current->name, &len, &iret); /* * get the parm */ ptr++; while ( *ptr == ' ' || *ptr == '\t' ) ptr++; /* remove leading space */ strcpy(current->parm, ptr); cst_rmbl(current->parm, current->parm, &len, &iret); current->next = NULL; } } fclose(fp); } return(0); }
void grib2name ( char *filename, int seqno, char *data, size_t sz, char *ident ) { int i, n, ier, ilen; int unpack=0, expand=0; g2int listsec0[3],listsec1[13],numlocal; int model_id, grid_id; char g2name[13], fdats[80]; char prodtmp[255]; char levelstmp[80]; char prods[128]; static char datyp[]="grib2", slashstr[]="/"; static int tblinit=0; static char *strptr[5]; Gribmsg curr_g2; Geminfo curr_gem; static char g2tables[5][LLMXLN] = { 0 }, *tbllist[5]; curr_g2.cgrib2 = (unsigned char *)data; curr_g2.mlength = sz; curr_g2.gfld = NULL; curr_g2.field_tot = 0; if ( !tblinit) { for (i = 0; i < 5; i++) tbllist[i] = g2tables[i]; tblinit = !0; } /* modify below to pass message size as a failsafe check */ /*if ( ( ier = g2_info ( curr_g2.cgrib2, listsec0,listsec1, &(curr_g2.field_tot), &numlocal) ) != 0 ) */ if ( ( ier = g2_info ( curr_g2.cgrib2, curr_g2.mlength, listsec0,listsec1, &(curr_g2.field_tot), &numlocal) ) != 0 ) return; prods[0] = '\0'; for ( n=0; n < curr_g2.field_tot; n++) { ier=g2_getfld( curr_g2.cgrib2, curr_g2.mlength, n+1, unpack, expand, &curr_g2.gfld); /* initialize strings in geminfo structure */ memset ( curr_gem.cproj, 0, sizeof(curr_gem.cproj)); memset ( curr_gem.parm, 0, sizeof(curr_gem.parm)); memset ( curr_gem.gdattm1, 0, sizeof(curr_gem.gdattm1)); memset ( curr_gem.gdattm2, 0, sizeof(curr_gem.gdattm2)); model_id = curr_g2.gfld->ipdtmpl[4]; grid_id = curr_g2.gfld->griddef; gb2_2gem (&curr_g2, &curr_gem, tbllist, &ier); if ( ier != 0 ) { sprintf(g2name,"UNK\0"); sprintf(levelstmp,"LVL\0"); sprintf(fdats,"FHRS\0"); } else { sprintf(g2name,"%s\0",curr_gem.parm); cst_rmbl (g2name, g2name, &ilen, &ier ); if ( n > 0 ) strncat ( prods, ";", 1); sprintf(prods+strlen(prods),"%s\0",g2name); strptr[0] = (char *)malloc(12); cst_itoc ( &curr_gem.vcord, 1, (char **)(&strptr), &ier); cst_rxbl (curr_gem.unit, curr_gem.unit, &ilen, &ier); if ( ilen == 0 ) sprintf (curr_gem.unit, "-\0"); if ( curr_gem.level[1] == -1 ) sprintf(levelstmp,"%d %s %s\0",curr_gem.level[0],curr_gem.unit,strptr[0]); else sprintf(levelstmp,"%d-%d %s %s\0",curr_gem.level[0],curr_gem.level[1],curr_gem.unit,strptr[0]); cst_rmbl (curr_gem.gdattm1, curr_gem.gdattm1, &ilen, &ier ); cst_rmbl (curr_gem.gdattm2, curr_gem.gdattm2, &ilen, &ier ); if ( ilen > 0 ) sprintf(fdats,"%s-%s\0",curr_gem.gdattm1,curr_gem.gdattm2); else sprintf(fdats,"%s\0",curr_gem.gdattm1); ilen = 1; while ( ilen > 0 ) cst_rmst(fdats, slashstr, &ilen, fdats, &ier); free(strptr[0]); } g2_free(curr_g2.gfld); curr_g2.gfld = NULL; } sprintf(prodtmp,"%s/%s/%s/#%03d/%s/%s/%s! %06d\0", datyp, s_pds_center((int)listsec1[0],(int)listsec1[1]), s_pds_model((int)listsec1[0],model_id), grid_id, fdats, prods, levelstmp,seqno); if(strlen(filename) < 253) { strcpy(ident,filename); strncat(ident," !",2); strncat(ident,prodtmp,253-strlen(filename)); } else { strncpy(ident,filename,255); ident[255] = '\0'; } return; }
void gb2_vcrd ( char *wmolvltbl, char *lcllvltbl, Gribmsg *cmsg, int *levels, int *vcord, char *unit, 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 * ***********************************************************************/ { int ret, ier, lvl1, lvl2, iver, lclver, ilen; 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; } /*cst_lstr ( g2lev.unit, &ilen, &ier );*/ cst_rmbl ( g2lev.unit, unit, &ilen, &ier ); if ( ( strcmp(unit,"Pa") == 0 ) && ( g2lev.scale == -2 ) ) sprintf ( unit, "hPa\0" ); /*else strncat( unit, g2lev.unit, ilen);*/ /* * 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] = (int)rint( rlevel[0] * sfact ); if ( rlevel[1] == -1.0 ) { levels[1] = -1; } else { levels[1] = (int)rint( rlevel[1] * sfact ); } if ( lvl1 == 1 ) { /* Surface */ levels[0] = 0; levels[1] = -1; } }
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; }