This archive contains answers to questions sent to Unidata support through mid-2025. Note that the archive is no longer being updated. We provide the archive for reference; many of the answers presented here remain technically correct, even if somewhat outdated. For the most up-to-date information on the use of NSF Unidata software and data services, please consult the Software Documentation first.
Jim, attatched is the updated read_front.c to fix the new time strings and flip the pip side. If they decide to change the side of the warm front pips again, just change the imul for fnum==2 back to .5: else /* this draws a semi-circle pip */ { imul = .5; if(fnum == 5) imul = -.5; /* occluded pip on top side */ if(fnum == 2) imul = -.5; /* warm fronts sitched sides too */ At this point, the occluded and stationary fronts look ok with the warm front pips on the correct side. Only the warm front orientation has changed. Chiz
/********************************************************* ** Collection of subroutines to read a frontal file, ** ** parse the symbols to be plotted and plot them on a ** ** map. ** ** ** ** S. Chiswell Unidata 3/98 ** *********************************************************/ #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <string.h> #include <math.h> #define MAXP 100 #define SOH 1 #define ETX 3 #ifdef UNDERSCORE #define read_front read_front_ #define gtext gtext_ #define gscolr gscolr_ #define gsline gsline_ #define gline gline_ #define gfill gfill_ #define gspcl gspcl_ #define gsspcl gsspcl_ #define gflush gflush_ #endif #ifdef LINUX #define read_front_ read_front__ #endif typedef struct features { int npoints; float lat[MAXP],lon[MAXP]; float press[MAXP]; struct features *next; } features; typedef struct wxbull { char *valid; struct features *low, *high, *warm, *cold, *occluded, *trof, *stationary; } wxbull; /* read a bulletin from a file */ char *getbull(fp,offset) int fp; int *offset; { struct stat buf; int ier,FOUND; char ch; ssize_t nbyte; int start,stop,i; char *rbuf=NULL; if((ier = fstat(fp,&buf)) != 0) { perror("Could not stat file\0"); return(rbuf); } if(*offset >= buf.st_size) { printf("offset past end of file\n"); return(rbuf); } FOUND = 0; while((FOUND == 0)&&(*offset < buf.st_size)) { lseek(fp, *offset, SEEK_SET); nbyte = read(fp, &ch, 1); if(ch == SOH) { start = *offset; FOUND = 1; } *offset += 1; } while((FOUND == 1)&&(*offset < buf.st_size)) { lseek(fp, *offset, SEEK_SET); nbyte = read(fp, &ch, 1); if(ch == ETX) { stop = *offset; FOUND = 2; } *offset += 1; } if(FOUND == 2) { rbuf = (char *)malloc(stop - start); lseek(fp, start+1, SEEK_SET); nbyte = read(fp, rbuf ,(stop - start - 2)); for(i=0;i<(stop - start -3);i++) if(rbuf[i] < ' ') rbuf[i] = ' '; /* get rid of ctrl and bull chars! */ rbuf[stop - start - 2] = '\0'; *offset = stop + 1; } return(rbuf); } /* get frontal location coordinates from a string */ void *getfront(pos) char **pos; { struct features *feat_obj; char *cpos,*subs,*apos; double dval; cpos = *pos; while((cpos[0] != NULL)&&((cpos[0] < '0')||(cpos[0] > '9'))) cpos += 1; *pos = cpos; if(cpos[0] == NULL) return(NULL); while((cpos[0] != NULL)&&(cpos[0] < 'A')) cpos += 1; subs = (char *)malloc(cpos - *pos); subs[0] = '\0'; strncat(subs,*pos,cpos - *pos - 1); *pos = cpos; feat_obj = (struct features *)malloc(sizeof(struct features)); feat_obj->npoints = 0; feat_obj->next = NULL; cpos = subs; while(cpos != NULL) { apos = cpos; dval = strtod(apos,&cpos); if(cpos != apos) { if(dval < 10000) { feat_obj->lat[feat_obj->npoints] = (float)(((int)dval)/100); feat_obj->lon[feat_obj->npoints] = (float)(((int)dval)%100); } else { feat_obj->lat[feat_obj->npoints] = (float)(((int)dval)/1000); feat_obj->lon[feat_obj->npoints] = (float)(((int)dval)%1000); } if(feat_obj->npoints == 0) /** try doubling first point */ { /** for a spline closer to end */ feat_obj->npoints += 1; feat_obj->lat[1] = feat_obj->lat[0]; feat_obj->lon[1] = feat_obj->lon[0]; } feat_obj->npoints += 1; apos = cpos; } else cpos = NULL; } feat_obj->lat[feat_obj->npoints] = feat_obj->lat[feat_obj->npoints - 1]; feat_obj->lon[feat_obj->npoints] = feat_obj->lon[feat_obj->npoints - 1]; feat_obj->npoints += 1; return(feat_obj); } /* get map features from a list of pressure & latlon points */ void *getfeat(pos) char *pos; { char *cpos; char *subs; struct features *feat_obj; int i; double dval; cpos = pos + 5; while((cpos != NULL)&&(cpos[0] < 'A')) cpos += 1; subs = (char *)malloc(cpos - pos - 5 + 1); subs[0] = '\0'; strncat(subs,pos+5,cpos - pos - 5); feat_obj = (struct features *)malloc(sizeof(struct features)); feat_obj->npoints = 0; feat_obj->next = NULL; cpos = subs; i = 0; while(cpos != NULL) { pos = cpos; dval = strtod(pos,&cpos); if(cpos != pos) { if(i == 0) { feat_obj->press[feat_obj->npoints] = (float)dval; } else { if(dval < 10000) { feat_obj->lat[feat_obj->npoints] = (float)(((int)dval)/100); feat_obj->lon[feat_obj->npoints] = (float)(((int)dval)%100); } else { feat_obj->lat[feat_obj->npoints] = (float)(((int)dval)/1000); feat_obj->lon[feat_obj->npoints] = (float)(((int)dval)%1000); } feat_obj->npoints += 1; } i = (i + 1) % 2; pos = cpos; } else cpos = NULL; } return(feat_obj); } /* parse out highs, lows, and fronts from a bulletin */ void *read_asus1(prod,fhr) char *prod; int fhr; { struct wxbull *bull=NULL; struct features *feat_obj; char *pos,*cpos,*valid,*bullp; char searchstr[80]; int i,done,fcst=0; double dval; if((bull = (void *)malloc(sizeof(struct wxbull))) == NULL) return(NULL); bull->low = NULL; bull->high = NULL; bull->warm = NULL; bull->cold = NULL; bull->occluded = NULL; bull->trof = NULL; bull->stationary = NULL; bull->valid = NULL; /* see if we are dealing with a forecast front file */ pos = strstr(prod,"PROG VALID"); if((pos != NULL)&&(fhr < 0)) fhr = 12; if(pos != NULL) { fcst = 1; searchstr[0] = '\0'; sprintf(searchstr,"%02dHR PROG VALID\0",fhr); pos = strstr(prod,searchstr); if(pos == NULL) { printf("forecast hour %d not found\n",fhr); return(NULL); } else { bullp = pos; pos = strstr(pos+15,searchstr+2); if(pos != NULL) bullp[(pos - bullp)-3] = '\0'; } } else bullp = prod; pos = strstr(bullp,"VALID"); if(pos != NULL) { valid = (char *)malloc(30); valid[0] = '\0'; if(fcst != 1) { strncat(valid,"FRONTS ",7); strncat(valid,pos,18); /* dumb check for 3 spaces (\r\r\n since NWS keeps screwing up time*/ cpos = (char *)strstr(valid," "); if(cpos != NULL) cpos[0] = '\0'; } else { strncat(valid,"PROG FRONTS ",12); strncat(valid,pos,13); } bull->valid = valid; } pos = strstr(bullp,"HIGHS"); if(pos != NULL) bull->high = getfeat(pos); pos = strstr(bullp,"LOWS"); if(pos != NULL) bull->low = getfeat(pos); pos = strstr(bullp,"COLD"); while(pos != NULL) { feat_obj = getfront(&pos); if(feat_obj != NULL) { feat_obj->next = bull->cold; bull->cold = feat_obj; } pos = strstr(pos,"COLD"); } pos = strstr(bullp,"WARM"); while(pos != NULL) { feat_obj = getfront(&pos); if(feat_obj != NULL) { feat_obj->next = bull->warm; bull->warm = feat_obj; } pos = strstr(pos,"WARM"); } pos = strstr(bullp,"STNRY"); while(pos != NULL) { feat_obj = getfront(&pos); if(feat_obj != NULL) { feat_obj->next = bull->stationary; bull->stationary = feat_obj; } pos = strstr(pos,"STNRY"); } pos = strstr(bullp,"TROF"); while(pos != NULL) { feat_obj = getfront(&pos); if(feat_obj != NULL) { feat_obj->next = bull->trof; bull->trof = feat_obj; } pos = strstr(pos,"TROF"); } pos = strstr(bullp,"OCFNT"); while(pos != NULL) { feat_obj = getfront(&pos); if(feat_obj != NULL) { feat_obj->next = bull->occluded; bull->occluded = feat_obj; } pos = strstr(pos,"OCFNT"); } return(bull); } /* draw frontal pips */ void draw_pip(X,Y,ptype,fnum,color,pipcnt) float X[],Y[]; int ptype,color,pipcnt; { float thta,PIPX[14],PIPY[14]; float imul,dist; int np,k,iret,pf1,pf2; char nav[2]; if(ptype >= 0) { pf1 = 0; pf2 = pipcnt - 1; dist = sqrt(pow(X[pf2]-X[pf1],2.0) + pow(Y[pf2]-Y[pf1],2.0)); if(dist < .3) return; /* don't draw really short segments */ thta = atan2((Y[pf2] - Y[pf1]),(X[pf2] - X[pf1])); if(ptype == 0) /* this draws a triangle pip */ { PIPX[1] = (X[pf2] + X[pf1])/2.0 + 1.0 * cos(thta - (M_PI/2.0)); PIPY[1] = (Y[pf2] + Y[pf1])/2.0 + 1.0 * sin(thta - (M_PI/2.0)); PIPX[0] = (X[pf2] + X[pf1])/2.0 + .7 * cos(thta); PIPX[2] = (X[pf2] + X[pf1])/2.0 + .7 * cos(thta - M_PI); PIPY[0] = (Y[pf2] + Y[pf1])/2.0 + .7 * sin(thta); PIPY[2] = (Y[pf2] + Y[pf1])/2.0 + .7 * sin(thta - M_PI); np = 3; } else /* this draws a semi-circle pip */ { imul = .5; if(fnum == 5) imul = -.5; /* occluded pip on top side */ if(fnum == 2) imul = -.5; /* warm fronts sitched sides too */ for(k=0;k<14;k++) { if(pipcnt < 3) { PIPX[k] = (X[pf1] + X[pf2])/2.0 + imul * cos(thta + (M_PI*k)/13.0); PIPY[k] = (Y[pf1] + Y[pf2])/2.0 + imul * sin(thta + (M_PI*k)/13.0); } else { PIPX[k] = X[(pipcnt-1)/2] + imul * cos(thta + (M_PI*k)/13.0); PIPY[k] = Y[(pipcnt-1)/2] + imul * sin(thta + (M_PI*k)/13.0); } } np = 14; } nav[0] = 'M'; nav[1] = '\0'; gfill(nav,&np,PIPX,PIPY,&iret,strlen(nav)); } } /* calculate a spline through the frontal points and plot the frontal symbols */ void draw_front(fobj,fnum) struct features *fobj; int fnum; { int ltype,lhw,lwidth,whw; int color; int iret,npoints,i,j,k,np,pips,pipcnt=20; char nav[2]; float X[26],Y[26],Xt,Yt,jx,step=.05,imul; float B0,B1,B2,B3; float P0,P1,P2,P3; switch(fnum) { case 1: color = 4; ltype = 1; break; case 2: color = 2; ltype = 1; break; case 3: color = 4; ltype = 1; break; case 4: color = 5; ltype = 25; break; case 5: color = 7; ltype = 1; break; default: color = 6; ltype = 1; } lhw = 0; lwidth = 2; whw = 0; gsline(<ype,&lhw,&lwidth,&whw,&iret); nav[0] = 'M'; nav[1] = '\0'; if(iret == 0) { gscolr(&color,&iret); npoints = 2; j = 0; if(fobj->npoints > 3) /* use a B-spline */ { for(i=3;i<fobj->npoints;i++) { np = 0; jx = 0; while(jx < (1.0 + step)) { B0 = pow((1.0 - jx),3.0) / 6.0; B1 = ((3 * pow(jx,3.0)) - (6 * jx * jx) + 4 ) / 6.0; B2 = ((-3 * pow(jx,3.0)) + (3 * jx * jx) + (3 * jx) + 1) / 6.0; B3 = pow(jx,3.0) / 6.0; P0 = fobj->lat[i-3]; P1 = fobj->lat[i-2]; P2 = fobj->lat[i-1]; P3 = fobj->lat[i]; Xt = P0 * B0 + P1 * B1 + P2 * B2 + P3 * B3; P0 = -fobj->lon[i-3]; P1 = -fobj->lon[i-2]; P2 = -fobj->lon[i-1]; P3 = -fobj->lon[i]; Yt = P0 * B0 + P1 * B1 + P2 * B2 + P3 * B3; X[np] = Xt; Y[np] = Yt; np += 1; jx = jx + step; } gline(nav,&np,X,Y,&iret,strlen(nav)); pips = -1; if(fnum == 1) pips = 0; if(fnum == 2) pips = 1; if(fnum == 3) pips = j; if(fnum == 5) pips = j; draw_pip(X,Y,pips,fnum,color,pipcnt); if(fnum == 3) { if(j == 0) color = 2; else color = 4; j = (j + 1) % 2; gscolr(&color,&iret); } if(fnum == 5) j = (j + 1) % 2; } } else { for(i=0;i<(fobj->npoints - 1);i++) { X[0] = fobj->lat[i]; X[1] = fobj->lat[i+1]; Y[0] = -fobj->lon[i]; Y[1] = -fobj->lon[i+1]; gline(nav,&npoints,X,Y,&iret,strlen(nav)); pips = -1; if(fnum == 1) pips = 0; if(fnum == 2) pips = 1; if(fnum == 3) pips = j; if(fnum == 5) pips = j; draw_pip(X,Y,pips,fnum,color,2); if(fnum == 3) { if(j == 0) color = 2; else color = 4; j = (j + 1) % 2; gscolr(&color,&iret); } if(fnum == 5) j = (j + 1) % 2; } } /* end no B-spline */ } } /* subroutine to read a file and plot frontal information */ void read_front(wwfil,wwlen,valtim,vallen,atts,attlen,ashr,ashrlen,ier) char *wwfil; int *wwlen; char *valtim; int *vallen; char *atts; int *attlen; char *ashr; int *ashrlen; int *ier; { int fp; int offset,i; struct wxbull *wxsyms; struct features *feat_obj; char *bullp; char *fname; char navigate[2],pstr[10],*pos; int xioff,yioff,iret; int color,np,width,fhr,labels=1; float midx,midy,rotate,spcode; float size,scale; fname = (char *)malloc(*wwlen + 1); fname[0] = '\0'; for(i=0;i<*wwlen;i++) if(wwfil[i] > ' ') strncat(fname,wwfil+i,1); if((fp = open(fname,O_RDONLY,NULL)) == -1) { printf("could not open file: %s\n",fname); *ier = -1; return; } offset = 0; atts[*attlen - 1] = '\0'; if((pos = (char *)strchr(atts,'/')) != NULL) { if((pos[1] == 'N')||(pos[1] == 'n')) labels=0; scale = (float)strtod(atts,&pos); } else scale = atof(atts); if(scale <= 0) scale = 1; if(labels == 0) printf("no labels for extrema\n"); ashr[*ashrlen - 1] = '\0'; if((pos = (char *)strchr(ashr,'/')) != NULL) fhr = strtol(ashr,&pos,10); else fhr = atol(ashr); /* can be generalized for multiple bulletins in a file later if I decide that we need to pass a plot time! */ /*while(offset >=0) {*/ bullp = getbull(fp,&offset); /*if(bullp == NULL) { offset = -1; continue; }*/ wxsyms = (void *)read_asus1(bullp,fhr); if(wxsyms != NULL) { navigate[0] = 'M'; navigate[1] = '\0'; feat_obj = wxsyms->cold; while(feat_obj != NULL) { draw_front(feat_obj,1); feat_obj = feat_obj->next; } feat_obj = wxsyms->warm; while(feat_obj != NULL) { draw_front(feat_obj,2); feat_obj = feat_obj->next; } feat_obj = wxsyms->stationary; while(feat_obj != NULL) { draw_front(feat_obj,3); feat_obj = feat_obj->next; } feat_obj = wxsyms->trof; while(feat_obj != NULL) { draw_front(feat_obj,4); feat_obj = feat_obj->next; } feat_obj = wxsyms->occluded; while(feat_obj != NULL) { draw_front(feat_obj,5); feat_obj = feat_obj->next; } if(wxsyms->high != NULL) { color = 4; gscolr(&color,&iret); size = 1.5 * scale; width = 2; gsspcl(&size,&width,&iret); np = 1; spcode = 2; for(i=0;i<wxsyms->high->npoints;i++) { xioff = 0; yioff = 0; rotate = 0; midx = wxsyms->high->lat[i]; midy = -wxsyms->high->lon[i]; gspcl(navigate,&np,&spcode,&midx,&midy,&xioff,&yioff,&iret,strlen(navigate)); if(labels != 0) { yioff = (int)(-3*scale); xioff = -3; if(wxsyms->high->press[i] < 1000) xioff = -2; if(yioff > -2) yioff = -2; pstr[0] = '\0'; sprintf(pstr,"%3.0f\0",wxsyms->high->press[i]); gtext(navigate,&midx,&midy,pstr,&rotate,&xioff,&yioff,&iret,strlen(navigate),strlen(pstr)); } } } if(wxsyms->low != NULL) { color = 2; gscolr(&color,&iret); size = 1.5 * scale; width = 2; gsspcl(&size,&width,&iret); np = 1; spcode = 3; for(i=0;i<wxsyms->low->npoints;i++) { xioff = 0; yioff = 0; rotate = 0; midx = wxsyms->low->lat[i]; midy = -wxsyms->low->lon[i]; gspcl(navigate,&np,&spcode,&midx,&midy,&xioff,&yioff,&iret,strlen(navigate)); if(labels != 0) { yioff = (int)(-3*scale); xioff = -3; if(wxsyms->low->press[i] < 1000) xioff = -2; if(yioff > -2) yioff = -2; pstr[0] = '\0'; sprintf(pstr,"%3.0f\0",wxsyms->low->press[i]); gtext(navigate,&midx,&midy,pstr,&rotate,&xioff,&yioff,&iret,strlen(navigate),strlen(pstr)); } } } while(wxsyms->cold != NULL) { feat_obj = wxsyms->cold->next; free(wxsyms->cold); wxsyms->cold = feat_obj; } while(wxsyms->warm != NULL) { feat_obj = wxsyms->warm->next; free(wxsyms->warm); wxsyms->warm = feat_obj; } while(wxsyms->trof != NULL) { feat_obj = wxsyms->trof->next; free(wxsyms->trof); wxsyms->trof = feat_obj; } while(wxsyms->occluded != NULL) { feat_obj = wxsyms->occluded->next; free(wxsyms->occluded); wxsyms->occluded = feat_obj; } while(wxsyms->stationary != NULL) { feat_obj = wxsyms->stationary->next; free(wxsyms->stationary); wxsyms->stationary = feat_obj; } if(wxsyms->high != NULL) free(wxsyms->high); if(wxsyms->low != NULL) free(wxsyms->low); if(wxsyms->valid != NULL) { strncpy(valtim,wxsyms->valid,*vallen); free(wxsyms->valid); } free(wxsyms); } /*}*/ gflush(&iret); *ier = 0; return; } /* debug stubs */ #ifdef MAIN main(argc, argv) int argc; char *argv[]; { int ier,wwlen,vallen,attlen,ashrlen; char valtim[72],atts[72],ashr[72]; wwlen = strlen(argv[1]); vallen=71; strcpy(atts," \0"); attlen = strlen(atts); strcpy(ashr," \0"); ashrlen = strlen(ashr); read_front(argv[1],&wwlen,valtim,&vallen,atts,&attlen,ashr,&ashrlen,&ier); } #endif