/***************************************************************/ /* SHARP-95 */ /* Advanced Interactive Sounding Analysis Program */ /* */ /* XW Video Graphics Routines (Part #1) */ /* These are the routines that pertain specifically to */ /* representing the Skew/t and Hodograph on the screen. */ /* */ /* John A. Hart */ /* National Severe Storms Forecast Center */ /* Kansas City, Missouri */ /* -------------------------------------------------- */ /* List of Routines in this module: */ /* */ /* MAKE_SCREEN */ /* DRAW_SKEWT */ /* DRAW_HODO */ /* HODO_TO_PIX */ /* PIX_TO_HODO */ /* TRACE_HODO */ /* DRY_ADIABAT */ /* ISOTHERM */ /* ISOBAR */ /* TRACE_TEMP */ /* TRACE_VTMP */ /* TRACE_DWPT */ /* TRACE_WETBULB */ /* PRES_TO_PIX */ /* PIX_TO_PRES */ /* TEMP_TO_PIX */ /* PIX_TO_TEMP */ /* TRACE_PARCEL */ /* WIND_BARB */ /* PLOT_BARBS */ /* */ /***************************************************************/ #define GLOBAL #define VIDEO #include #include #include #include #include "winline.h" typedef struct { /* for drawing moving crosshairs or zoom boxes */ int start_x, start_y, last_x, last_y; GC gc; XPoint points[4]; int itype; /* 0 = temp 1 = dwpt */ int ilev; /* 0 = bottom 1 = top 2 = inbetween */ short yy, i; } rubber_band_data; rubber_band_data rbdata; int g_Parcel=-1; int g_TvParcelCor=-1; /*NP*/ void make_screen( int argc, char *argv[]) /*************************************************************/ /* MAKE_SCREEN */ /* John Hart NSSFC KCMO */ /* */ /* Draws basic SHARP graphic template on screen, including */ /* areas, buttons, and tables. */ /* */ /*************************************************************/ { char st[80], *t; int i; float ix1, ix2; pagenum = 1; X_Init(argc, argv); /* ----- RAOB Title Line ----- */ setcolor(1); set_font( 1 ); /* ----- Parameter Area ----- */ setcolor(4); rectangle( 1, skv.brx + 20, skv.tly, xwdth-5, xhght-5); setcolor(1); rectangle( 0, skv.brx + 20, skv.tly, xwdth-5, xhght-5); /* ----- Cursor Data Area ----- */ setcolor(3); strcpy( st, "CURSOR DATA" ); outgtext ( st, (((skv.brx + 20 + xwdth) / 2) - (getgtextextent( st ) / 2)), skv.tly + 5 ); setcolor(0); rectangle( 1, skv.brx + 30, skv.tly + 22, xwdth-15, 100); setcolor(1); rectangle( 0, skv.brx + 30, skv.tly + 22, xwdth-15, 100); mode = 1; pagenum = 1; /* ----- Begin Main Processing Loop ----- */ StartLoop(); } /*NP*/ void draw_skewt( void ) /*************************************************************/ /* DRAW_SKEWT */ /* John Hart NSSFC KCMO */ /* */ /* Draws a standard Skew-T/LogP diagram. */ /*************************************************************/ { short x1, y1, x2, y2, y, i, j; float a, thta, thtae, ix1; float lvl[] = {1050,1000,850,700,500,300,200,100}; float mixratios[] = {0.5,1,2,4,8,16,32}; int mixratiocount=7; char rtitle[200]; setcliprgn(1, 1, xwdth, xhght ); setcolor(0); rectangle( 1, 1, 1, skv.brx+14, skv.bry+skv.tly+14); setcolor(1); set_font( 2 ); setcliprgn(skv.tlx, skv.tly, skv.brx, skv.bry); setlinestyle( 1, 1 ); rectangle( 0, skv.tlx, skv.tly, skv.brx, skv.bry); /* ----- Draw Skewed Temperature Lines ----- */ setcolor(24); setcolor(21); setlinestyle( 1, 1 ); for( i=-160; i<=50; i=i+10 ) { isotherm( i ); } /* ----- Draw Dry Adiabats ----- */ setcolor(24); setlinestyle( 1, 1 ); for( thta=-70; thta<=350; thta=thta+20) { dry_adiabat(thta); }; /* ----- Draw Moist Adiabats ---- */ setcolor(14); setlinestyle (4, 1); for (thtae=-2+273.16;thtae<=38+273.16;thtae+=4) {moist_adiabat(thtae); }; /* ----- Draw Mixing ratio Lines ---- */ setcolor(23); setlinestyle (2,1); for (i=0;i 0) && (overlay_previous == 1)) { trace_temp2(3); trace_dwpt2(3); } /* ----- Plot Environmental Temperature Data ----- */ setcolor(2); if ( numlvl > 0 ) trace_temp( 3 ); /* ----- Plot Environmental Dew Point Data ----- */ setcolor(3); if ( numlvl > 0 ) trace_dwpt( 3 ); /* ----- Plot Environmental Virtual Temperature Data ----- */ setcolor(2); if ( numlvl > 0 ) trace_vtmp( 1 ); /* ----- Plot Environmental Wetbulb Temperature Data ----- */ setcolor(6); setlinestyle( 1, 1 ); if ( numlvl > 0 ) trace_wetbulb( 1 ); setcolor(1); rectangle( 0, skv.tlx, skv.tly, skv.brx, skv.bry); /* ----- Plot Wind Barbs ----- */ setcolor(5); setlinestyle( 1, 1 ); if ( numlvl > 0 ) plot_barbs(); /* ----- If Available, plot VVEL profile ----- */ if (numlvl > 0) vvel_profile(); /* ----- Display Skew-T Inset ----- */ draw_skinset(); setcliprgn ( 1, 1, xwdth, xhght ); setcolor(1); set_font( 1 ); sprintf( rtitle, "%s (%s)", raobtitle, raob_type); outgtext ( rtitle, skv.tlx, 1 ); update_text_values(); /*XCopyArea ( XtDisplay(draw_reg), canvas, XtWindow(draw_reg), gc, 0, 0, xwdth, xhght, 0, 0 ); */ } /*NP*/ void drawWindbarbs(int rwx) /****************************************************************/ /* DRAWWINDBARBS */ /****************************************************************/ { int lastpres, i, x, y; /*Draw Wind Barbs*/ setcolor(8); lastpres = 1100; for( i = 0; i < numlvl && sndg[i][1]>=100; i++) { if( qc( sndg[i][5] ) ) { y = pmap(fnP(sndg[i][1]),1); x = rwx+35; if((sndg[i][2]-i_hght(lastpres)) > 400) { wind_barb( sndg[i][5], sndg[i][6], x, y, 4); lastpres = sndg[i][1]; } } } } /*NP*/ void draw_ICG() /*****************************************************************/ /* DRAW_ICG */ /* LARRY J. HINSON AWC/KCMO */ /*****************************************************************/ { char buf[80]; register i,j; int X0=-30,Y0=260,XM=30,YM=1200; int count=0; int width,height; setcliprgn(1,1,xwdth,xhght); setcolor(0); rectangle(1,1,1,skv.brx+14,skv.bry+skv.tly+14); setcolor(1); set_font(2); setlinestyle(1,1); sprintf( buf, "%s (%s)", raobtitle, raob_type); outgtext ( buf, skv.tlx, 1 ); update_text_values(); /*Get font height*/ height=getfontheight(); /*Establish Coordinate System*/ view(1,1,skv.brx+14,skv.bry+skv.tly+14); setwindow(X0,fnP(Y0),XM,fnP(YM)); /*Draw and label Pressure lines*/ for (j=1000;j>=300;j-=100) { line_w(-25,fnP(j),25,fnP(j)); itoa((short)j,buf,80); outgtext(buf,pmap(-25,0)-getgtextextent(buf)-2,pmap(fnP(j),1)); } /*Draw and label Temperature lines and RH*/ count=0; for (i=-25;i<=25;i+=5) { setcolor(1); line_w(i,fnP(1000),i,fnP(300)); itoa((short)i,buf,80); setcolor(2); outgtext(buf,pmap(i,0)-getgtextextent(buf)/2,pmap(fnP(1000),1)+height); itoa((short)count,buf,80); count+=10; setcolor(3); outgtext(buf,pmap(i,0)-getgtextextent(buf)/2,pmap(fnP(300),1)-height); } setcolor(0); setlinestyle(2,1); line_w(0,fnP(1000),0,fnP(300)); setcolor(2); sprintf(buf,"TEMPERATURE (C)"); outgtext(buf,pmap(0,0)-getgtextextent(buf)/2,pmap(fnP(1000),1)+2*height+3); setcolor(3); sprintf(buf,"RELATIVE HUMIDITY"); outgtext(buf,pmap(0,0)-getgtextextent(buf)/2,pmap(fnP(300),1)-2*height-3); setcolor(7); sprintf(buf,"EQUIVALENT POTENTIAL INSTABILITY x 1E-3 K/m"); outgtext(buf,pmap(0,0)-getgtextextent(buf)/2,pmap(fnP(1000),1)+3*height+3); /*Plot Temperature/RH Trace*/ if (numlvl>0) { int x1,x2,nx1w,nx2w,x,y,first; float RH; float const1,theta1,thetase1,theta2,thetase2,dthetasedz,midpres; drawWindbarbs(pmap(25,0)); /*setcliprgn(pmap(-25,0),pmap(fnP(300),1),pmap(25,0),pmap(fnP(1000),1));*/ /* Draw Temperature */ setcolor(2); first=-1; for (i=0;i=300;i++) { if (sndg[i][3]>-900.0) if (first) { moveto_w(sndg[i][3],fnP(sndg[i][1])); first=0; } else lineto_w(sndg[i][3],fnP(sndg[i][1])); ; } /*RH plot in x-direction requires re-scale of window*/ /*Grab x/y coordinate @ T,p=-25,300 & T,p=25,300 */ x1=pmap(-25,0);x2=pmap(25,0); /*Extrapolate new x1 and x2 external window coords*/ nx1w=100.0/(x2-x1)*(-x1); nx2w=100.0/(x2-x1)*(skv.brx+14-x1); setwindow(nx1w,fnP(Y0),nx2w,fnP(YM)); setcolor(3); first=-1; for(i=0;i=300;i++) { if (sndg[i][3]>-900.0) { RH=100*mixratio(sndg[i][1],sndg[i][4])/mixratio(sndg[i][1],sndg[i][3]); if (first) { moveto_w(RH,fnP(sndg[i][1])); first=0; } else lineto_w(RH,fnP(sndg[i][1])); } } /*Plot Equivalent Potential Instability*/ /*dTheta-E/dz plot set to re-scale to temperature x 1E-3*/ setwindow(X0,fnP(Y0),XM,fnP(YM)); setcliprgn(pmap(-25,0),pmap(fnP(300),1),pmap(25,0),pmap(fnP(1000),1)); setcolor(7); const1=2500000.0/1004.0; first=-1; for (i=0;i=100;i++) { if (sndg[i][3] > -900.0 && sndg[i+1][3]>-900) { theta1=theta(sndg[i][1],sndg[i][3],1000)+273.15; thetase1=theta1*exp(const1*mixratio(sndg[i][1],sndg[i][3])*.001/(sndg[i][3]+273.15)); theta2=theta(sndg[i+1][1],sndg[i+1][3],1000)+273.15; thetase2=theta2*exp(const1*mixratio(sndg[i+1][1],sndg[i+1][3])*.001/(sndg[i][3]+273.15)); /*Do D-Theta-se/dz*/ dthetasedz=(thetase2-thetase1)/(sndg[i+1][2]-sndg[i][2]); midpres=(sndg[i][1]+sndg[i+1][1])/2; if (first) { moveto_w(dthetasedz*1E3,fnP(midpres)); first=0; } else lineto_w(dthetasedz*1E3,fnP(midpres)); } } setcliprgn(1,1,xwdth,xhght); } } /*NP*/ void draw_TURB() /*****************************************************************/ /* DRAW_TURB */ /* LARRY J. HINSON AWC/KCMO */ /*****************************************************************/ { char buf[80]; register i,j; int X0=9,Y0=80,XM=-3.0,YM=1300; int count=0; int width,height; float x1,x2,nx1w,nx2w; setcliprgn(1,1,xwdth,xhght); setcolor(0); rectangle(1,1,1,skv.brx+14,skv.bry+skv.tly+14); setcolor(1); set_font(2); setlinestyle(1,1); sprintf( buf, "%s (%s)", raobtitle, raob_type); outgtext ( buf, skv.tlx, 1 ); update_text_values(); /*Get font height*/ height=getfontheight(); /*Establish Coordinate System*/ view(1,1,skv.brx+14,skv.bry+skv.tly+14); setwindow(X0,fnP(Y0),XM,fnP(YM)); /*Draw and label Pressure lines*/ for (j=1000;j>=100;j-=100) { line_w(8,fnP(j),-2,fnP(j)); itoa((short)j,buf,80); outgtext(buf,pmap(8,0)-getgtextextent(buf)-2,pmap(fnP(j),1)); } /*Draw and label Richardson Number Lines from Top*/ for (i=8;i>=-2;i--) { setcolor(1); if (i % 2 == 0) line_w(i,fnP(100),i,fnP(1000)); setcolor(7); itoa((short)i,buf,80); outgtext(buf,pmap(i,0)-getgtextextent(buf)/2,pmap(fnP(100),1)-height-2); } setcolor(0); setlinestyle(2,1); line_w(0,fnP(1000),0,fnP(100)); /*SHEAR plot in x-direction requires re-scale of window*/ /*Grab x/y coordinate @ Ri,p=8,300 & Ri,p=-2,300 */ x1=pmap(8,0);x2=pmap(-2,0); /*Extrapolate new x1 and x2 external window coords*/ nx1w=50.0/(x2-x1)*(-x1); nx2w=50.0/(x2-x1)*(skv.brx+14-x1); setwindow(nx1w,fnP(Y0),nx2w,fnP(YM)); setcolor(11); /* Label Wind Shear Lines from Bottom*/ for (i=0;i<=50;i+=5) { itoa((short)i,buf,80); outgtext(buf,pmap(i,0)-getgtextextent(buf)/2,pmap(fnP(1000),1)+height+2); } /* Labels */ sprintf(buf,"%s","LN(RICHARDSON NUMBER)"); setcolor(7); outgtext(buf,pmap(25,0)-getgtextextent(buf)/2,pmap(fnP(100),1)-2*height-2); setcolor(11); sprintf(buf,"%s","WIND SHEAR TKE PRODUCTION x 1E3 joules/sec"); outgtext(buf,pmap(25,0)-getgtextextent(buf)/2,pmap(fnP(1000),1)+2*height+2); if (numlvl>0) { float g,gammadry,meanT,meanTd,meanVirtualT,gamma,windshear,Ri,midpres; float dthetadz,theta1,theta2,meanTheta; float u1,v1,u2,v2,u,v,windshearsqrd,midPres; float dz,tke_windshear_prod; float lastptx,lastpty,lastpts; int s1,s2; FILE *fil1; int first=-1; drawWindbarbs(pmap(50,0)); /*Plot Graph of Richardson Number */ setcolor(4); setcliprgn(pmap(0,0),pmap(fnP(100),1),pmap(50,0),pmap(fnP(1000),1)); g=9.8; /* m/s**2 */ for (i=0;i=100;i++) { s1=i; s2=i+1; if (sndg[s1][3] > -900 & sndg[s2][3]> -900.0) { u1=-sndg[s1][6]*sin(sndg[s1][5]*PI/180); v1=-sndg[s1][6]*cos(sndg[s1][5]*PI/180); u2=-sndg[s2][6]*sin(sndg[s2][5]*PI/180); v2=-sndg[s2][6]*cos(sndg[s2][5]*PI/180); u=u2-u1;v=v2-v1; windshear=sqrt(u*u+v*v)*.51479/(sndg[s2][2]-sndg[s1][2]); midPres=(sndg[s1][1]+sndg[s2][1])/2; theta1=theta(sndg[s1][1],sndg[s1][3],1000)+273.16; theta2=theta(sndg[s2][1],sndg[s2][3],1000)+273.16; meanTheta=(theta1+theta2)/2.0; dz=sndg[s2][2]-sndg[s1][2]; dthetadz=(theta2-theta1)/dz; if (windshear != 0.0) { windshearsqrd=(windshear*windshear); Ri=(g/meanTheta)*(dthetadz/windshearsqrd); if (! first) { setcolor(7); setwindow(X0,fnP(Y0),XM,fnP(YM)); line_w(lastptx,lastpty,log(Ri),fnP(midPres)); setcolor(11); setwindow(nx1w,fnP(Y0),nx2w,fnP(YM)); tke_windshear_prod=0.54*dz*windshearsqrd; /*line_w(lastpts,lastpty,windshearsqrd*10000,fnP(midPres));*/ line_w(lastpts,lastpty,tke_windshear_prod*100,fnP(midPres)); } lastptx=log(Ri); lastpty=fnP(midPres); lastpts=0.54*dz*windshearsqrd*100; first=0; } } } } setcliprgn(1,1,xwdth,xhght); } /*NP*/ void draw_Clouds( void ) /*****************************************************************/ /* DRAW_CLOUDS */ /* LARRY J. HINSON AWC/KCMO */ /*****************************************************************/ { int startflag,endflag,s1,s2,s3,i,spsub,epsub; float T1,T2,T3,dz,d2T,R1,R2,R3,d2R,startpres,endpres,x1,x2,y,t2,p2; float Tavg,DDavg,DD; float dd1,dd2,dd3,d2x; int cloudAmt,top,basefound; float d2xparam=0.0000; float Taccum=0.0; float DDaccum=0.0; float TCount=0.0; char buf[80]; startflag=0; endflag=0; /*******/ pagenum = 1; clear_paramarea(); draw_skewt(); /*show_page( pagenum );*/ mode=6; /*******/ for (i=1;i-900.0 && sndg[s2][3] > -900.0 && sndg[s3][3]>-900) { T1=sndg[s1][3]; T2=sndg[s2][3]; T3=sndg[s3][3]; dz=sndg[s3][2]-sndg[s1][2]; if (dz==0) dz=1; d2T=(T3-2*T2+T1)/(dz*dz); R1=100*mixratio(sndg[s1][1],sndg[s1][4])/mixratio(sndg[s1][1],sndg[s1][3]); R2=100*mixratio(sndg[s2][1],sndg[s2][4])/mixratio(sndg[s2][1],sndg[s2][3]); R3=100*mixratio(sndg[s3][1],sndg[s3][4])/mixratio(sndg[s3][1],sndg[s3][3]); d2R=(R3-2*R2+R1)/(dz*dz); if (d2T>=0 && d2R<=0 && !startflag) { startflag=-1; startpres=sndg[s2][1]; spsub=s2; } else if ( !(d2T>=0 && d2R<=0) && startflag) { startflag=0; endpres=sndg[s2][1]; epsub=s2; Tavg=Taccum/TCount; DDavg=DDaccum/TCount; cloudAmt=getCloudAmount(Tavg,DDavg); Taccum=0.0; DDaccum=0.0; TCount=0; switch (cloudAmt) { case 1: strcpy(buf,"OVC"); break; case 2: strcpy(buf,"BKN"); break; case 3: strcpy(buf,"SCT"); break; case 4: strcpy(buf,"FEW"); break; } if (cloudAmt != 4) { setcolor(5); XFillRectangle(XtDisplay(draw_reg), canvas, gc,90,pres_to_pix(endpres), 140-90,pres_to_pix(startpres)-pres_to_pix(endpres)); setcolor(8); set_font(2); setlinestyle(1,1); outgtext(buf,100,pres_to_pix(endpres)); } } ; if ((d2T>=0 && d2R<=0) && startflag) { Taccum+=sndg[s2][3]; DD=sndg[s2][3]-sndg[s2][4]; DDaccum+=DD; TCount++; } } } top=0; for (i=numlvl-1;i>0; i--) { basefound=0; s1=i-1; s2=i; s3=i+1; if (sndg[s1][3]>-900.0 && sndg[s2][3] > -900.0 && sndg[s3][3]>-900) { if (! top) { dd1=sndg[s1][3]-sndg[s1][4]; dd2=sndg[s2][3]-sndg[s2][4]; dd3=sndg[s3][3]-sndg[s3][4]; dz=(sndg[s3][2]-sndg[s1][2])/2.0; if (dz==0) dz=1; d2x=(dd3-2*dd2+dd1)/(dz*dz); if (d2x>0 && dd2<4.5) { top=-1; endpres=sndg[s2][1]; epsub=s2; /* Now work downward till you get moistening with height */ /* Do this until you reach lowest level of this condition */ ; while(i>1 && ! basefound) { i--; s1=i-1; s2=i; s3=i+1; if (sndg[s1][3]>-900.0 && sndg[s2][3] > -900.0 && sndg[s3][3]>-900) { dd1=sndg[s1][3]-sndg[s1][4]; dd2=sndg[s2][3]-sndg[s2][4]; dd3=sndg[s3][3]-sndg[s3][4]; dz=(sndg[s3][2]-sndg[s1][2])/2.0; if (dz==0) dz=1; d2x=(dd3-2*dd2+dd1)/(dz*dz); if (d2x < -d2xparam) { while ((d2x < -d2xparam && dd2<4.5) && i>1) { i--; s1=i-1; s2=i; s3=i+1; if (sndg[s1][3]>-900.0 && sndg[s2][3] > -900.0 && sndg[s3][3]>-900) { dd1=sndg[s1][3]-sndg[s1][4]; dd2=sndg[s2][3]-sndg[s2][4]; dd3=sndg[s3][3]-sndg[s3][4]; dz=(sndg[s3][2]-sndg[s1][2])/2.0; if (dz==0) dz=1; d2x=(dd3-2*dd2+dd1)/(dz*dz); } } /* Lowest level of drying found...compute LCL from s1*/ drylift(sndg[s1][1],sndg[s1][3],sndg[s1][4],&p2,&t2); startpres=p2; if (startpres 0 ) trace_hodo( 3 ); /* ----- Plot Mean Wind Vector ----- */ setcolor(5); mean_wind( -1, -1, &mnu, &mnv, &wdir, &wspd); hodo_to_pix( wdir, wspd, &x1, &y1); moveto( x1, y1); rectangle( 0, x1-4, y1-4, x1+4, y1+4); /* ----- Plot 30/75 Storm Motion Vector ----- */ mean_wind( sndg[sfc()][1], i_pres(msl(6000)), &ix1, &ix2, &ix3, &ix4); setcolor(11); setlinestyle( 1, 1 ); ix4 *= .75; ix3 += 30; if(ix3>360) ix3 -= 360; hodo_to_pix( ix3, ix4, &x1, &y1); moveto(x1-3, y1); lineto(x1+3, y1); moveto(x1, y1-3); lineto(x1, y1+3); ellipse( 0, x1-3, y1-3, x1+3, y1+3 ); /* ----- Plot 15/85 Storm Motion Vector ----- */ mean_wind( sndg[sfc()][1], i_pres(msl(6000)), &ix1, &ix2, &ix3, &ix4); setcolor(12); setlinestyle( 1, 1 ); ix4 *= .85; ix3 += 15; if(ix3>360) ix3 -= 360; hodo_to_pix( ix3, ix4, &x1, &y1); moveto(x1-3, y1); lineto(x1+3, y1); moveto(x1, y1-3); lineto(x1, y1+3); ellipse( 0, x1-3, y1-3, x1+3, y1+3 ); /* ----- Plot Current Storm Motion Vector ----- */ setcolor(31); setlinestyle( 1, 1 ); hodo_to_pix( st_dir, st_spd, &x1, &y1); moveto(x1-6, y1); lineto(x1+6, y1); moveto(x1, y1-6); lineto(x1, y1+6); ellipse( 0, x1-6, y1-6, x1+6, y1+6 ); /* ----- Display Hodograph Inset ----- */ draw_hoinset(); /* ----- Draw final outline of hodograph ----- */ setcolor(1); setlinestyle( 1, 1 ); rectangle( 0, hov.tlx, hov.tly, hov.brx, hov.bry); setcliprgn ( 1, 1, xwdth, xhght ); setcolor(1); set_font( 1 ); sprintf( rtitle, "%s (%s)", raobtitle, raob_type); outgtext ( rtitle, skv.tlx, 1 ); XCopyArea ( XtDisplay(draw_reg), canvas, XtWindow(draw_reg), gc, 0, 0, xwdth, xhght, 0, 0 ); } /*NP*/ void hodo_to_pix( float dir, float mag, short *x, short *y ) /*************************************************************/ /* HODO_TO_PIX */ /* John Hart NSSFC KCMO */ /* */ /* Calculates the screen location (x,y) in pixels of the */ /* wind vector (dir,mag). */ /*************************************************************/ { float midx, midy; float scle; scle = (hov.brx - hov.tlx) / hov.hodomag; midx = hov.tlx + ((hov.brx - hov.tlx) / 2) + (hov.xshift * scle); midy = hov.tly + ((hov.bry - hov.tly) / 2) - (hov.yshift * scle); *x = (short)(midx - (ucomp( dir, mag ) * scle)); *y = (short)(midy + (vcomp( dir, mag ) * scle)); } /*NP*/ void pix_to_hodo( short x, short y, float *dir, float *mag ) /*************************************************************/ /* PIX_TO_HODO */ /* John Hart NSSFC KCMO */ /* */ /* Calculates the wind vector (dir, mag) in knots of the */ /* screen location (x,y). */ /*************************************************************/ { float midx, midy, scle, u, v; scle = (hov.brx - hov.tlx) / hov.hodomag; /* pixels/knot */ midx = hov.tlx + ((hov.brx - hov.tlx) / 2) + (hov.xshift * scle); midy = hov.tly + ((hov.bry - hov.tly) / 2) - (hov.yshift * scle); u = (midx - x) / scle; v = (y - midy) / scle; *dir = angle(u, v); *mag = (float)sqrt((u * u) + (v * v)); } /*NP*/ void trace_hodo( short width ) /*************************************************************/ /* TRACE_HODO */ /* John Hart NSSFC KCMO */ /* */ /* Plots environmental wind shear vectors on Hodograph. */ /*************************************************************/ { short i, j, x, y, xold, yold, ok = 0; setlinestyle( 1, width ); for( i=0; i < numlvl; i++) { if( qc(sndg[i][5]) && qc(sndg[i][6])) { if ( sndg[i][2] <= msl(3000) ) setcolor(2); else if ( sndg[i][2] > msl(3000) && sndg[i][2] <= msl(6000) ) setcolor(3); else if ( sndg[i][2] > msl(6000) && sndg[i][2] <= msl(9000) ) setcolor(5); else if ( sndg[i][2] > msl(9000) && sndg[i][2] <= msl(12000) ) setcolor(6); else if ( sndg[i][2] > msl(12000) ) setcolor(28); xold = x; yold = y; hodo_to_pix( sndg[i][5], sndg[i][6], &x, &y); if( ok == 0) { moveto( x, y); ok = 1; } else { moveto( xold, yold); lineto( x, y); } } } } /*NP*/ void dry_adiabat( float thta) /*************************************************************/ /* DRY_ADIABAT */ /* John Hart NSSFC KCMO */ /* */ /* Draws dry adiabat of theta (thta, c) on SkewT graphic. */ /*************************************************************/ { float pres, temp; short x, y; setcliprgn(skv.tlx, skv.tly, skv.brx, skv.bry); for( pres = 1050; pres >= 100; pres = pres - 50 ) { temp = ((thta + 273.15) / pow( 1000.0 / pres, ROCP )) - 273.15; x = temp_to_pix( temp , pres ); y = pres_to_pix( pres ); /* if( pres <= 200) { printf( "%f %f %d\n", pres, temp, x);} */ if(pres == 1050) { moveto(x, y); } else { lineto(x, y); } } } /*NP*/ void moist_adiabat(float thetae) /******************************************************************/ /* Draw Moist adiabat of constant thetae from surface to top. */ /******************************************************************/ { float pres, startpres, temp,t1,t2; short x,y; setcliprgn(skv.tlx, skv.tly, skv.brx, skv.bry); /* start at pres 1000 */ startpres=1000; t1=thetae-273.16; /* x=temp_to_pix(virtemp(startpres,t1,t1),startpres); */ x=temp_to_pix(t1,startpres); y=pres_to_pix(startpres); moveto(x,y); for(pres =950; pres>=100;pres-=50) { t2=wetlift(startpres,t1,pres); /* x=temp_to_pix(virtemp(pres,t2,t2),pres); */ x=temp_to_pix(t2,pres); y=pres_to_pix(pres); lineto(x,y); } } void mixingratio(float w) /*****************************************************************/ /* Draw line of constant mixing ratio from sfc to top of sounding*/ /*****************************************************************/ { float pres, startpres, temp,t1,t2; short x,y; setcliprgn(skv.tlx, skv.tly, skv.brx, skv.bry); for (pres=1000;pres>=100;pres-=50) { t1=temp_at_mixrat(w,pres); x=temp_to_pix(t1,pres); y=pres_to_pix(pres); if (pres==1000) moveto(x,y); else lineto(x,y); } } /*NP*/ void isotherm( float temp) /*************************************************************/ /* ISOTHERM */ /* John Hart NSSFC KCMO */ /* */ /* Draws temperature lines (temp, c) on SkewT graphic. */ /*************************************************************/ { short x, y; char st[10]; setcolor(24); x = temp_to_pix( temp, 1050 ); y = skv.bry; if((temp >= -30) && (temp <= 50)) { setcliprgn(1, 1, xwdth, xhght); itoa( (short)temp, st, 10 ); setcolor(1); outgtext ( st, x - (getgtextextent( st ) / 2), y ); if (temp != 0) setcolor(24); else { setcolor(26); } } setcliprgn(skv.tlx, skv.tly, skv.brx, skv.bry); moveto( x, y ); x = temp_to_pix( temp, 100 ); y = skv.tly; lineto( x, y ); } /*NP*/ void isobar( float pres, short flag) /*************************************************************/ /* ISOBAR */ /* John Hart NSSFC KCMO */ /* */ /* Draws pressure lines (pres, mb) on SkewT graphic. */ /* */ /* flag = 0 Draw complete horizontal line */ /* = 1 Draw small tick marks along sides of chart */ /*************************************************************/ { short y; char st[10]; setcliprgn(1, 1, xwdth, xhght); y = pres_to_pix( pres ); if( flag == 0 ) { moveto( skv.tlx, y); itoa( (short)pres, st, 10 ); outgtext ( st, skv.tlx - getgtextextent( st ) - 2, y - 5 ); setcliprgn(skv.tlx, skv.tly, skv.brx, skv.bry); moveto( skv.tlx, y); lineto( skv.brx, y); } else { moveto( skv.tlx, y); lineto( skv.tlx + 5, y); moveto( skv.brx, y); lineto( skv.brx - 5, y); } } /*NP*/ void trace_temp( short width ) /*************************************************************/ /* TRACE_TEMP */ /* John Hart NSSFC KCMO */ /* */ /* Plots environmental temperature trace on SkewT. */ /*************************************************************/ { short i, j, x, y, xold, yold, ok = 0; setcliprgn(skv.tlx, skv.tly, skv.brx, skv.bry); setlinestyle( 1, width ); for( i=0; i < numlvl; i++) { if( sndg[i][3] > -200) { xold = x; yold = y; x = temp_to_pix( sndg[i][3], sndg[i][1] ); y = pres_to_pix( sndg[i][1] ); if( ok == 0) { moveto( x, y); ok = 1; } else { moveto( xold, yold); lineto( x, y); } } } } /*NP*/ void trace_temp2( short width ) /*************************************************************/ /* TRACE_TEMP2 */ /* John Hart NSSFC KCMO */ /* */ /* Plots environmental temperature trace on SkewT. */ /*************************************************************/ { short i, j, x, y, xold, yold, ok = 0, numlvl2; numlvl2 = sndg2[0][0]; setcliprgn(skv.tlx, skv.tly, skv.brx, skv.bry); setlinestyle( 1, width ); for( i=0; i < numlvl2; i++) { if( sndg2[i][3] > -200) { xold = x; yold = y; x = temp_to_pix( sndg2[i][3], sndg2[i][1] ); y = pres_to_pix( sndg2[i][1] ); if( ok == 0) { moveto( x, y); ok = 1; } else { moveto( xold, yold); lineto( x, y); } } } } /*NP*/ void trace_vtmp( short width ) /*************************************************************/ /* TRACE_VTMP */ /* John Hart NSSFC KCMO */ /* */ /* Plots virtual temperature trace on SkewT. */ /*************************************************************/ { short i, j, x, y, xold, yold, ok = 0; setlinestyle( 3, width ); for( i = 0; i < numlvl; i++) { if( qc(sndg[i][3]) && qc(sndg[i][4])) { xold = x; yold = y; x = temp_to_pix( i_vtmp(sndg[i][1]), sndg[i][1] ); y = pres_to_pix( sndg[i][1] ); if( ok == 0) { moveto( x, y); ok = 1; } else { moveto( xold, yold); lineto( x, y); } } } } /*NP*/ void trace_dwpt( short width ) /*************************************************************/ /* TRACE_DWPT */ /* John Hart NSSFC KCMO */ /* */ /* Plots environmental Dew Point trace on SkewT. */ /*************************************************************/ { short i, j, x, y, xold, yold, ok = 0; setcliprgn(skv.tlx, skv.tly, skv.brx, skv.bry); setlinestyle( 1, width ); for( i=0; i < numlvl; i++) { if( sndg[i][4] > -200) { xold = x; yold = y; x = temp_to_pix( sndg[i][4], sndg[i][1] ); y = pres_to_pix( sndg[i][1] ); if( ok == 0) { moveto( x, y); ok = 1; } else { moveto( xold, yold); lineto( x, y); } } } } /*NP*/ void trace_dwpt2( short width ) /*************************************************************/ /* TRACE_DWPT2 */ /* John Hart NSSFC KCMO */ /* */ /* Plots environmental Dew Point trace on SkewT. */ /*************************************************************/ { short i, j, x, y, xold, yold, ok = 0, numlvl2; numlvl2 = sndg2[0][0]; setcliprgn(skv.tlx, skv.tly, skv.brx, skv.bry); setlinestyle( 1, width ); for( i=0; i < numlvl2; i++) { if( sndg2[i][4] > -200) { xold = x; yold = y; x = temp_to_pix( sndg2[i][4], sndg2[i][1] ); y = pres_to_pix( sndg2[i][1] ); if( ok == 0) { moveto( x, y); ok = 1; } else { moveto( xold, yold); lineto( x, y); } } } } /*NP*/ void trace_wetbulb( short width ) /*************************************************************/ /* TRACE_WETBULB */ /* John Hart NSSFC KCMO */ /* */ /* Plots environmental Wetbulb trace on SkewT. */ /*************************************************************/ { short i, j, x, y, xold, yold, ok = 0; float t1; setlinestyle( 1, width ); for( i=0; i < numlvl; i++) { if(sndg[i][4] > -200) { xold = x; yold = y; t1 = wetbulb( sndg[i][1], sndg[i][3], sndg[i][4] ); x = temp_to_pix( t1, sndg[i][1] ); y = pres_to_pix( sndg[i][1] ); if( ok == 0) { moveto( x, y); ok = 1; } else { moveto( xold, yold); lineto( x, y); } } } } /*NP*/ short pres_to_pix( float pres ) /*************************************************************/ /* PRES_TO_PIX */ /* John Hart NSSFC KCMO */ /* */ /* Converts given pressure (mb) to an Y coordinate on */ /* Skewt graphic. */ /*************************************************************/ { double scl1, scl2; scl1 = log(1050.) - log(100.); scl2 = log(1050.) - log(pres); return (short)(skv.bry - (scl2 / scl1) * (skv.bry - skv.tly)); } /*NP*/ float pix_to_pres( short pix ) /*************************************************************/ /* PIX_TO_PRES */ /* John Hart NSSFC KCMO */ /* */ /* Converts given Y coordinate on Skewt graphic to */ /* pressure(mb). */ /*************************************************************/ { double scl1, scl2, scl3; scl1 = log(1050.) - log(100.); scl2 = skv.bry - (double)pix; scl3 = skv.bry - skv.tly + 1; return (float)(1050 / exp((scl2 / scl3) * scl1)); } /*NP*/ short temp_to_pix( float temp, float pres ) /*************************************************************/ /* TEMP_TO_PIX */ /* John Hart NSSFC KCMO */ /* */ /* Converts given temperature (c) to an X coordinate on */ /* Thermodynamic diagram. */ /* */ /* Depending on (skv.type), relationship is for (1) Pseudo- */ /* Adiabatic or (2) Skew-T/Log P diagram. */ /* */ /* Skew: 90c spread across the bottom of chart. */ /* 120c spread up-and-down the chart. */ /* Temp at BR of chart = 50c */ /*************************************************************/ { float scl1, scl2; if( skv.type == 1 ) { scl1 = (float)skv.brtemp - ((((float)skv.bry - (float)pres_to_pix( pres )) / ((float)skv.bry - (float)skv.tly)) * (float)skv.vspread); } else { scl1 = skv.brtemp; } scl2 = skv.brx - (((scl1 - temp) / skv.hspread) * (skv.brx - skv.tlx)); return (short)scl2; } /*NP*/ float pix_to_temp( short x, short y ) /*************************************************************/ /* PIX_TO_TEMP */ /* John Hart NSSFC KCMO */ /* */ /* Converts given X/Y coordinates to temperature(c) on */ /* Thermodynamic diagram. */ /*************************************************************/ { float scl1, scl2, scl3; scl1 = 1 - (((float)x - (float)skv.tlx) / ((float)skv.brx - (float)skv.tlx)); scl2 = (float)skv.brtemp - (scl1 * skv.hspread); scl1 = 1 - (((float)y - (float)skv.tly) / ((float)skv.bry - (float)skv.tly)); scl3 = scl2 - (scl1 * (float)skv.vspread); return scl3; } /*NP*/ void trace_parcel(float pres, float temp, float dwpt) /*************************************************************/ /* TRACE_PARCEL */ /* John Hart NSSFC KCMO */ /* */ /* Plots parcel(pres, temp, dwpt) trajectory on SkewT */ /* graphic. */ /* */ /* pres - Pressure of initial parcel(mb) */ /* temp - Temperature of initial parcel (c) */ /* dwpt - Dew Point of initial parcel (c) */ /*************************************************************/ { float i, p2, t2, t3; short x, y; if(!qc(pres) || !qc(temp) || !qc(dwpt) ) return; setcolor(31); setlinestyle( 4, 1 ); /* Doing Both non-virtual & virtual temp trace based on global switch settings*/ if (g_Parcel) { x = temp_to_pix( temp, pres ); y = pres_to_pix( pres ); moveto( x, y ); drylift(pres, temp, dwpt, &p2, &t2); x = temp_to_pix( t2, p2 ); y = pres_to_pix( p2 ); lineto( x, y ); for(i = p2 - 50; i >= 100; i = i - 50) { t3 = wetlift(p2, t2, i); x = temp_to_pix( t3, i ); y = pres_to_pix( i ); lineto( x, y ); } t3 = wetlift(p2, t2, 100); x = temp_to_pix( t3 , 100 ); y = pres_to_pix( 100 ); lineto( x, y ); } if (g_TvParcelCor) { x = temp_to_pix( virtemp(pres, temp, dwpt), pres ); y = pres_to_pix( pres ); moveto( x, y ); drylift(pres, temp, dwpt, &p2, &t2); x = temp_to_pix( virtemp(p2, t2, t2), p2 ); y = pres_to_pix( p2 ); lineto( x, y ); for(i = p2 - 50; i >= 100; i = i - 50) { t3 = wetlift(p2, t2, i); x = temp_to_pix( virtemp(i, t3, t3), i ); y = pres_to_pix( i ); lineto( x, y ); } t3 = wetlift(p2, t2, 100); x = temp_to_pix( virtemp(100, t3, t3), 100 ); y = pres_to_pix( 100 ); lineto( x, y ); } } /*NP*/ void wind_barb( float wdir, float wspd, short x, short y, short siz) /*************************************************************/ /* WIND_BARB */ /* John Hart NSSFC KCMO */ /* */ /* Plots wind barb at location (x,y) for given wind. */ /*************************************************************/ { short x1, y1, x2, y2, x3, y3, sped, flag, maxsiz=3; float dx, dy, spcx, spcy, wid, hgt; dx = ucomp(wdir, 10) * siz / 1.5; dy = vcomp(wdir, 10) * siz / 1.5; x1 = x; y1 = y; x2 = x1 + (short)dx; y2 = y1 - (short)dy; /* ----- Draw backbone of wind barb, along with origin dot ----- */ if(siz > maxsiz) { setlinestyle(1, 2); } else { setlinestyle( 1, 1 ); } rectangle( 0, x1-1, y1-1, x1+1, y1+1); moveto(x1, y1); lineto(x2, y2); sped = (short)wspd; x1 = x2; y1 = y2; wid = 5; /* Number of flags that will fit */ spcx = dx / wid; spcy = dy / wid; x1 = x1 + (short)spcx; y1 = y1 - (short)spcy; /* ----- Draw wind flags (increments of 50kt) ----- */ flag = 0; while (sped > 47) { flag = 1; x1 = x1 - (short)spcx; y1 = y1 + (short)spcy; hgt = .5F; /* Heigth of flags */ x2 = x1 + (short)(dy * hgt); y2 = y1 + (short)(dx * hgt); x3 = x1 - (short)spcx; y3 = y1 + (short)spcy; moveto( x1, y1); lineto( x2, y2); lineto( x3, y3); x2 = (x1 + x2 + x3) / 3; y2 = (y1 + y2 + y3) / 3; sped -= 50; x1 = x3; y1 = y3; } /* ----- Draw wind barbs (increments of 5kt) ----- */ while (sped > 7 ) { hgt = .5F; /* Heigth of flags */ x2 = x1 + (short)(dy * hgt); y2 = y1 + (short)(dx * hgt); x3 = x1 - (short)spcx; y3 = y1 + (short)spcy; moveto( x3, y3); lineto( x2, y2); sped -= 10; x1 = x3; y1 = y3; } /* ----- Draw short barb ----- */ if(sped > 3 ) { hgt = .5F; /* Heigth of flags */ x2 = x1 + (short)(dy * hgt); y2 = y1 + (short)(dx * hgt); x3 = x1 - (short)spcx; y3 = y1 + (short)spcy; dx = (x3 - x2) / 2; dy = (y3 - y2) / 2; x2 = x3 - (short)dx; y2 = y3 - (short)dy; moveto( x3, y3); lineto( x2, y2); } } /*NP*/ void plot_barbs( void ) /*************************************************************/ /* PLOT_BARBS */ /* John Hart NSSFC KCMO */ /* */ /* Plots wind barbs along side of thermo diagram. */ /*************************************************************/ { short i, x, y; float lastpres; setcliprgn(1, 1, xwdth, xhght); lastpres = 1100; for( i = 0; i < numlvl; i++) { if( qc( sndg[i][5] ) ) { y = pres_to_pix( sndg[i][1] ); x = skv.brx - 40; if((sndg[i][2]-i_hght(lastpres)) > 400) { wind_barb( sndg[i][5], sndg[i][6], x, y, 4); lastpres = sndg[i][1]; } } } } /*NP*/ void vvel_profile( void ) /*************************************************************/ /* VVEL_PROFILE */ /* John Hart NSSFC KCMO */ /* */ /* Plots vertical velocity profile */ /*************************************************************/ { short i, x1, x2, y, vvel, avail, leng; float lastpres; avail=0; setcliprgn(1, 1, xwdth, xhght); lastpres = 1100; for( i = 0; i < numlvl; i++) { if(qc(sndg[i][0]) && (sndg[i][0] < 1)) { avail++; y = pres_to_pix( sndg[i][1] ); x1 = skv.tlx + 40; if (g_pfs_model_sel_sw) leng = sndg[i][0] * 10; else leng = (sndg[i][0] * 1000); /* Convert to Mbs/sec */ x2 = x1 - (leng * 2); /* Determine screen scale */ setcolor(25); if(sndg[i][0] < 0) setcolor(12); moveto(x1, y); lineto(x2, y); } } /* ----- Draw Scales ----- */ if(avail > 5) { setcolor(7); x1 = skv.tlx + 40; moveto( x1, skv.tly+40 ); lineto( x1, skv.bry-10 ); setlinestyle( 3, 1 ); x1 = skv.tlx + 20; moveto( x1, skv.tly+40 ); lineto( x1, skv.bry-10 ); x1 = skv.tlx + 60; moveto( x1, skv.tly+40 ); lineto( x1, skv.bry-10 ); set_font(2); outgtext( "OMEGA", skv.tlx+18, skv.tlx); outgtext( "+10", skv.tlx+3, skv.tlx+15); outgtext( "-10", skv.tlx+43, skv.tlx+15); } } float F1(float x) { if (x >= -10) return 1.0; else return (-.1*(x+70)+7); } float F2(float x) { if (x>=0) return 2.0; else if (x>=-10 && x<0) return (-.025*(x+10)+2.5); else return(-.125*(x+70)+10.0); } float F3(float x) { if (x>=0) return 3.0; else if (x>=-10 && x<0) return(-0.1*(x+10)+4.0); else return(-0.15*(x+50)+10.0); } int getCloudAmount(float temp,float dd) { if (dd