awips2/ncep/gov.noaa.nws.ncep.ui.nsharp/nsharp_c/ps_driv.c
root 9f19e3f712 Initial revision of AWIPS2 11.9.0-7p5
Former-commit-id: 64fa9254b946eae7e61bbc3f513b7c3696c4f54f
2012-01-06 08:55:05 -06:00

2276 lines
67 KiB
C

/***************************************************************/
/* NSHARP */
/* Postscript driver routine */
/* Adapted from hpgl.c driver */
/* */
/* Unidata/UCAR Steve Chiswell 3/99 */
/* */
/* -------------------------------------------------- */
/** Public routines in this module: */
/* print_sounding_ps */
/* */
/** Private routines in this module: */
/* ps_centertext */
/* ps_circle */
/* ps_cliprgn */
/* ps_close */
/* ps_disp_param */
/* ps_draw_hodo */
/* ps_draw_skewt */
/* ps_dry_adiabat */
/* ps_fill_cape */
/* ps_fill_capex (to be removed) */
/* ps_hodo_circs */
/* ps_hodo_to_pix */
/* ps_isobar */
/* ps_isotherm */
/* ps_label_hodo */
/* ps_lineto */
/* ps_lvldata */
/* ps_moveto */
/* ps_open_printer */
/* ps_page */
/* ps_plot_barbs */
/* ps_plot_elevs */
/* ps_plot_uvvs */
/* ps_pres_to_pix */
/* ps_rectangle */
/* ps_select_pen */
/* ps_setup */
/* ps_sharp_label */
/* ps_temp_to_pix */
/* ps_text */
/* ps_trace_dwpt */
/* ps_trace_hodo */
/* ps_trace_parcel */
/* ps_trace_parcelX (to be removed) */
/* ps_trace_temp */
/* ps_trace_vtmp */
/* ps_trace_wetbulb */
/* ps_triangle */
/* ps_wind_barb */
/* ps_write_parcel */
/* ps_write_storm */
/* ps_write_thermo */
/* ps_write_winds */
/* */
/***************************************************************/
#include "gui.h"
#include "sharp95.h"
/*
* Private function prototypes
*/
void ps_centertext (FILE * fp, char *st, short x, short y, short font,
short tf);
void ps_circle (FILE * fp, short x, short y, short radius);
void ps_cliprgn (FILE * fp, short x1, short y1, short x2, short y2);
void ps_close (FILE * fp);
void ps_disp_param (FILE * fp, char *st, short x, short y, short font,
short tf);
void ps_draw_hodo (FILE * fp);
void ps_draw_skewt (FILE * fp);
void ps_dry_adiabat (FILE * fp, float thta);
void ps_fill_cape (FILE * fp, short pct);
void ps_fill_capex (FILE * fp, short pct);
void ps_hodo_circs (FILE * fp);
void ps_hodo_to_pix (float dir, float mag, short *x, short *y);
void ps_isobar (FILE * fp, float pres, short flag);
void ps_isotherm (FILE * fp, float temp);
void ps_label_hodo (FILE * fp);
void ps_lineto (FILE * fp, short x, short y);
void ps_lvldata (FILE * fp, float pres, char *nam, short x, short y);
void ps_moveto (FILE * fp, short x, short y);
FILE *ps_open_printer (void);
void ps_page (FILE * fp);
void ps_plot_barbs (FILE * fp);
void ps_plot_elevs (FILE * fp);
void ps_plot_uvvs ( FILE *fp );
short ps_pres_to_pix (float pres);
void ps_rectangle (FILE * fp, short x1, short y1, short x3, short y3,
short fill, short pct);
void ps_select_pen (FILE * fp, short onoff, float width, short type);
void ps_setup (FILE * fp);
void ps_sharp_label (FILE * fp, short x1, short y1);
short ps_temp_to_pix (float temp, float pres);
void ps_text (FILE * fp, char *textstr, short x, short y,
short pts, short bold);
void ps_trace_dwpt (FILE * fp);
void ps_trace_hodo (FILE * fp);
void ps_trace_parcel (FILE * fp, float pres, float temp, float dwpt);
void ps_trace_parcelx (FILE * fp, float pres, float temp, float dwpt);
void ps_trace_temp (FILE * fp);
void ps_trace_vtmp (FILE * fp);
void ps_trace_wetbulb (FILE * fp);
void ps_triangle (FILE * fp, short x1, short y1, short x2, short y2,
short x3, short y3, short fill);
void ps_wind_barb (FILE * fp, float wdir, float wspd, short x, short y,
short siz);
void ps_write_parcel ( FILE *fp);
void ps_write_storm ( FILE *fp);
void ps_write_thermo ( FILE *fp);
void ps_write_winds ( FILE *fp);
void _sounding_plot (FILE * fp);
extern int nnpage;
static int text_justify = 0;
static int Pfont;
static int linewrap;
int pscolor;
struct _skewt hsk = { 500, 850, 5636, 5986, 100, 70, 60, 1 };
struct _hodog hho = { 3500, 850, 5636, 2950, -25, -25, 120, 20 };
/*===================================================================*/
void
print_sounding_ps (int COLRMODE)
/*************************************************************/
/* PRINT_SOUNDING_PS */
/* */
/* Prints skewt/hodograph to Postscript. */
/*************************************************************/
{
int i = 1;
FILE *fp;
struct sndg_struct *save_sndgp;
pscolor = COLRMODE;
fp = ps_open_printer ();
if (fp == NULL)
{
printf ("failed to open postscript file\n");
return;
}
ps_setup (fp);
if (NxmPrt_isPgFlgSet ())
{
save_sndgp = sndgp;
while ((i < MAX_PIXMAP) && (sndgs[i] != NULL) && (sndgs[i]->numlev > 0))
{
if (i > 1)
ps_page (fp);
sndgp = sndgs[i];
_sounding_plot (fp);
i++;
}
sndgp = save_sndgp;
}
else
{
_sounding_plot (fp);
}
ps_close (fp);
return;
}
/*=========================================================================*/
FILE *
ps_open_printer (void)
/************************************************************************
* ps_open_printer *
* *
* Opens stream for output to printer. Returns FILE handle. *
* *
* fin - Name of file to open *
** *
* T. Piper/SAIC 01/04 changed mktemp to mkstemp *
* S. Chiswell/UCAR 04/04 added fdopen for mkstemp descriptor *
***********************************************************************/
{
char *tempnam;
FILE *f1 = NULL;
int fdes;
tempnam = (char *) malloc (20);
tempnam[0] = '\0';
sprintf (tempnam, "/tmp/.nsharp_XXXXXX");
fdes = mkstemp (tempnam);
strcpy (config.filename, tempnam);
free (tempnam);
f1 = fdopen (fdes, "w");
return f1;
}
/*=========================================================================*/
void
ps_setup (FILE * fp)
/*************************************************************/
/* ps_setup */
/* */
/* fp - File handle */
/** *
* Log: *
* T. Piper/SAIC 03/05 Updated for Adobe 3.0 *
***********************************************************************/
{
int iret, type=0;
dttms_t dattim;
/*-----------------------------------------------------------------*/
/* Write prolog commands to file. */
fprintf (fp, "%%!PS-Adobe-3.0\n");
fprintf (fp, "%%%%For: %s\n", getenv("USER"));
fprintf (fp, "%%%%Creator: NSHARP\n");
fprintf (fp, "%%%%Title: NSHARP Graphic\n");
css_gtim ( &type, dattim, &iret);
fprintf (fp, "%%%%CreationDate: %s\n", dattim);
fprintf (fp, "%%%%EndComments\n");
fprintf (fp, "%%%%BeginProlog\n");
fprintf (fp, "%%%%Pages : (atend)\n");
fprintf (fp, "/M {moveto} def\n");
fprintf (fp, "/L {lineto} def\n");
fprintf (fp, "/N {newpath} def\n");
fprintf (fp, "/LW {setlinewidth} def\n");
fprintf (fp, "/AF {arc fill} def\n");
fprintf (fp, "/MS {makefont setfont} def\n");
fprintf (fp, "/FF {findfont} def\n");
fprintf (fp, "/CF {currentfont} def\n");
fprintf (fp, "/FL {closepath fill} def\n");
fprintf (fp, "/RGB {setrgbcolor} def\n");
fprintf (fp, "%%%%EndProlog\n");
fprintf (fp, "%%%%BeginSetup\n");
fprintf (fp, "<</PageSize[612 792]>>setpagedevice\n");
fprintf (fp, "%%%%EndSetup\n");
fprintf (fp, " 20 50 translate .075 .075 scale\n");
fprintf (fp, " 1 setlinecap 1 setlinejoin newpath\n");
fprintf (fp, "%%%%Page: 1 ?\n");
nnpage = 1;
Pfont = 0;
linewrap = 0;
}
void
ps_select_pen (FILE * fp, short onoff, float width, short type)
/*************************************************************/
/* ps_select_pen */
/* */
/* Selects the appropriate graphics pen in HP-GL/2 mode. */
/* */
/* fp - File handle */
/* onoff - Selects pin color (1=black, 0=white) */
/* width - Width in pels */
/* type - Line style (0-8), 9=Solid */
/* */
/*************************************************************/
{
float red, green, blue;
int irwdth, rgbcolor;
if (pscolor != 1)
rgbcolor = 1;
else
rgbcolor = (int) onoff;
switch (rgbcolor)
{
case 0:
red = 1;
green = 1;
blue = 1;
break;
case 1:
red = 0;
green = 0;
blue = 0;
break;
case 2:
red = .7;
green = 0;
blue = 0;
break;
case 3:
red = 0;
green = .7;
blue = 0;
break;
case 4:
red = 0;
green = 0;
blue = .7;
break;
case 5:
red = .7;
green = .7;
blue = 0;
break;
case 6:
red = 0;
green = .7;
blue = .7;
break;
default:
red = 0;
green = 0;
blue = 0;
}
switch ((int) type)
{
case 2:
fprintf (fp, "[40] 0 setdash\n");
break;
case 10:
fprintf (fp, "[40 40 5 50] 0 setdash\n");
break;
case 11:
fprintf (fp, "[20] 0 setdash\n");
break;
case 9:
fprintf (fp, "[] 0 setdash\n");
break;
default:
printf ("Unknown line type, defaulting to solid %d\n", type);
fprintf (fp, "[] 0 setdash\n");
}
irwdth = (int) (width * 60);
/*printf("look width %d color %f %f %f\n",irwdth,red,green,blue); */
if (irwdth < 1)
irwdth = 1;
fprintf (fp, "%5.3f %5.3f %5.3f %s\n", red, green, blue, " RGB ");
fprintf (fp, "%4d LW\n", irwdth);
}
void
ps_moveto (FILE * fp, short x, short y)
/*************************************************************/
/* ps_moveto */
/* */
/* Moves cursor to given coordinates, newpath */
/*************************************************************/
{
y = (1016 * 11) - 1050 - y;
fprintf (fp, "N %6d %6d M ", x, y);
}
void
ps_lineto (FILE * fp, short x, short y)
/*************************************************************/
/* ps_lineto */
/* */
/* lineto from current cursor location to (x,y) */
/*************************************************************/
{
y = (1016 * 11) - 1050 - y;
fprintf (fp, "%5d %5d L ", x, y);
linewrap++;
if (linewrap >= 4)
{
fprintf (fp, "\n");
linewrap = 0;
}
}
void
ps_rectangle (FILE * fp, short x1, short y1, short x3, short y3,
short fill, short pct)
/*************************************************************/
/* ps_rectangle */
/* */
/* Draws a rectangle bounded by (x1,y1) and (x2,y2). */
/* */
/* fill - Fill Indicator (1=YES) */
/* pct - Percent coverage of fill (0-100%) */
/*************************************************************/
{
short x2, y2, x4, y4;
float grayf;
x2 = x3;
y2 = y1;
x4 = x1;
y4 = y3;
if (fill == 1)
{
grayf = ((float) (100. - pct)) / 100.;
fprintf (fp, "%5.3f %5.3f %5.3f RGB\n", grayf, grayf, grayf);
}
ps_moveto (fp, x1, y1);
ps_lineto (fp, x2, y2);
ps_lineto (fp, x3, y3);
ps_lineto (fp, x4, y4);
ps_lineto (fp, x1, y1);
if (fill != 1)
fprintf (fp, "stroke\n");
else
fprintf (fp, "FL\n");
}
void
ps_cliprgn (FILE * fp, short x1, short y1, short x2, short y2)
/*************************************************************/
/* ps_cliprgn */
/* */
/* Defines drawing area with points (x1,y1) and (x2,y2). */
/*************************************************************/
{
y1 = (1016 * 11) - 1050 - y1;
y2 = (1016 * 11) - 1050 - y2;
fprintf (fp, "initclip\n");
fprintf (fp,
"N %d %d M %d %d lineto %d %d lineto %d %d lineto %d %d lineto closepath clip N\n",
x1, y1, x1, y2, x2, y2, x2, y1, x1, y1);
}
void
ps_close (FILE * fp)
/*************************************************************/
/* PS_CLOSE */
/* */
/*************************************************************/
{
fprintf (fp, " gsave showpage grestore\n");
fprintf (fp, " -576 -126 translate -90 rotate 60.6796 60.6796 scale\n");
fprintf (fp, "%%%%Trailer:\n");
fprintf (fp, "%%%%Pages: %5d\n", nnpage);
fclose (fp);
}
void
ps_page (FILE * fp)
/*************************************************************/
/* PS_PAGE */
/* */
/*************************************************************/
{
fprintf (fp, " gsave showpage grestore\n");
nnpage++;
fprintf (fp, "%%%%Page:%5d ?\n", nnpage);
}
void
ps_draw_skewt (FILE * fp)
/*************************************************************/
/* ps_draw_skewt */
/* */
/* Draws a standard Skew-T/LogP diagram using postscript. */
/*************************************************************/
{
short i;
float thta;
float lvl[] = { 1050, 1000, 850, 700, 500, 300, 200, 100 };
char st[128];
/* ----- Write Title Line at top of chart ----- */
sprintf (st, "%s (%s)", sndgp->title, raob_type);
ps_text (fp, st, hsk.tlx, hsk.tly - 65, 12, 3);
/* ----- Begin with outer boundary and frame ----- */
ps_select_pen (fp, 1, .75F, 9);
ps_rectangle (fp, hsk.tlx, hsk.tly, hsk.brx, hsk.bry, 0, 0);
ps_cliprgn (fp, hsk.brx, hsk.tly, hsk.tlx, hsk.bry);
ps_fill_cape (fp, 20);
/* ----- Draw Horizontal Pressure Lines ----- */
ps_select_pen (fp, 1, 0, 9);
for (i = 1; i <= 7; i++)
{
ps_isobar (fp, lvl[i], 0);
}
for (i = 150; i < 1050; i += 50)
{
ps_isobar (fp, (float) i, 1);
}
/* ----- Draw Skewed Temperature Lines ----- */
ps_select_pen (fp, 1, 0, 2);
for (i = -160; i <= 50; i += 10)
{
ps_isotherm (fp, (float) i);
}
/* ----- Draw Dry Adiabats ----- */
ps_select_pen (fp, 1, 0, 9);
for (thta = -70; thta <= 350; thta += 20)
{
ps_dry_adiabat (fp, thta);
};
/* ----- Plot Environmental Temperature Data ----- */
ps_select_pen (fp, 2, .75F, 9);
ps_trace_temp (fp);
/* ----- Plot Environmental Dew Point Data ----- */
ps_select_pen (fp, 3, .75F, 9);
ps_trace_dwpt (fp);
/* ----- Plot Environmental Virtual Temperature Data ----- */
ps_select_pen (fp, 5, .25F, 11);
ps_trace_vtmp (fp);
/* ----- Plot Environmental Wet Bulb Temperature Data ----- */
ps_select_pen (fp, 6, .25F, 11);
ps_trace_wetbulb (fp);
/* ----- Plot Environmental Wind Barbs ----- */
ps_select_pen (fp, 1, .25F, 9);
ps_plot_barbs (fp);
/* ----- Plot Elevation legend ----- */
ps_select_pen (fp, 1, .25F, 9);
ps_plot_elevs (fp);
/* ----- Trace Lifted Parcel ----- */
ps_select_pen (fp, 4, .35F, 10);
ps_trace_parcel (fp, sndgp->lplvals.pres, sndgp->lplvals.temp,
sndgp->lplvals.dwpt);
}
/*============================================================================*/
void
ps_isobar (FILE * fp, float pres, short flag)
/*************************************************************/
/* ps_isobar */
/* */
/* 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];
y = ps_pres_to_pix (pres);
if (flag == 0)
{
ps_cliprgn (fp, 20000, 0, 0, 20000);
itoa ((short) pres, st, 10);
ps_text (fp, st, hsk.tlx - 355, y + 60, 10, 0);
ps_cliprgn (fp, hsk.brx, hsk.tly, hsk.tlx, hsk.bry);
ps_moveto (fp, hsk.tlx, y);
ps_lineto (fp, hsk.brx, y);
fprintf (fp, " stroke\n");
}
else
{
ps_moveto (fp, hsk.tlx, y);
ps_lineto (fp, hsk.tlx + 100, y);
fprintf (fp, " stroke\n");
ps_moveto (fp, hsk.brx, y);
ps_lineto (fp, hsk.brx - 100, y);
fprintf (fp, " stroke\n");
}
}
void
ps_isotherm (FILE * fp, float temp)
/*************************************************************/
/* ps_isotherm */
/* */
/* Draws temperature lines (temp, c) on SkewT graphic. */
/*************************************************************/
{
short x1, y1, x2, y2;
char st[10];
if ((temp >= -30) && (temp <= 50))
{
x1 = ps_temp_to_pix (temp, 1050);
y1 = hsk.bry;
ps_cliprgn (fp, 20000, 0, 0, 20000);
itoa ((short) temp, st, 10);
ps_text (fp, st, x1, y1 + 160, 10, 0);
ps_cliprgn (fp, hsk.brx, hsk.tly, hsk.tlx, hsk.bry);
}
x1 = ps_temp_to_pix (temp, 1050);
y1 = hsk.bry;
ps_moveto (fp, x1, y1);
x2 = ps_temp_to_pix (temp, 100);
y2 = hsk.tly;
ps_lineto (fp, x2, y2);
fprintf (fp, " stroke\n");
}
/*======================================================================*/
short
ps_pres_to_pix (float pres)
/*************************************************************/
/* ps_pres_to_pix */
/* */
/* 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) (hsk.bry - (scl2 / scl1) * (hsk.bry - hsk.tly));
}
/*======================================================================*/
short
ps_temp_to_pix (float temp, float pres)
/*************************************************************/
/* ps_temp_to_pix */
/* */
/* Converts given temperature (c) to an X coordinate on */
/* Thermodynamic diagram. */
/* */
/* Depending on (hsk.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;
short tmpshrt;
/*----------------------------------------------------------------------*/
if (hsk.type == 1)
{
tmpshrt = ps_pres_to_pix (pres);
scl1 = (float) hsk.brtemp - ((((float)hsk.bry -
(float)tmpshrt) /
((float)hsk.bry -
(float)hsk.tly)) * (float)hsk.vspread);
}
else
{
scl1 = hsk.brtemp;
}
scl2 = hsk.brx - (((scl1 - temp) / hsk.hspread) * (hsk.brx - hsk.tlx));
return (short) scl2;
}
/*======================================================================*/
void
ps_dry_adiabat (FILE * fp, float thta)
/*************************************************************/
/* PS_DRY_ADIABAT */
/* */
/* Draws dry adiabat of theta (thta, c) on SkewT graphic. */
/*************************************************************/
{
float pres, temp;
short x, y;
int ok = 0;
fprintf (fp, "%% Dry Adiabat %5.1f\n", thta);
for (pres = 1050; pres >= 100; pres = pres - 50)
{
temp = ((thta + 273.15) / pow (1000.0 / pres, ROCP)) - 273.15;
x = ps_temp_to_pix (temp, pres);
y = ps_pres_to_pix (pres);
if (G_DIFF(pres, 1050.0F))
{
ps_moveto (fp, x, y);
}
else
{
ps_lineto (fp, x, y);
ok++;
}
}
if (ok > 0)
fprintf (fp, " stroke\n");
}
/*======================================================================*/
void
ps_trace_temp (FILE * fp)
/*************************************************************/
/* ps_trace_temp */
/* */
/* Plots environmental temperature trace on SkewT. */
/*************************************************************/
{
short i, x, y, ok = 0;
for (i = 0; i < sndgp->numlev; i++)
{
if (sndgp->sndg[i].temp > -200)
{
x = ps_temp_to_pix (sndgp->sndg[i].temp, sndgp->sndg[i].pres);
y = ps_pres_to_pix (sndgp->sndg[i].pres);
if (ok == 0)
{
ps_moveto (fp, x, y);
ok = 1;
}
else
{
ps_lineto (fp, x, y);
ok++;
}
}
}
if (ok > 1)
fprintf (fp, " stroke\n");
}
/*======================================================================*/
void
ps_trace_vtmp (FILE * fp)
/*************************************************************/
/* ps_trace_vtmp */
/* */
/* Plots environmental virtual temp trace on SkewT. */
/*************************************************************/
{
short i, x, y, ok = 0;
for (i = 0; i < sndgp->numlev; i++)
{
if (sndgp->sndg[i].temp > -200)
{
x =
ps_temp_to_pix (i_vtmp (sndgp->sndg[i].pres),
sndgp->sndg[i].pres);
y = ps_pres_to_pix (sndgp->sndg[i].pres);
if (ok == 0)
{
ps_moveto (fp, x, y);
ok = 1;
}
else
{
ps_lineto (fp, x, y);
ok++;
}
}
}
if (ok > 1)
fprintf (fp, " stroke\n");
}
/*====================================================================*/
void
ps_trace_dwpt (FILE * fp)
/*************************************************************/
/* ps_trace_dwpt */
/* */
/* Plots environmental Dew Point trace on SkewT. */
/*************************************************************/
{
short i, x, y, ok = 0;
for (i = 0; i < sndgp->numlev; i++)
{
if (sndgp->sndg[i].dwpt > -200)
{
x = ps_temp_to_pix (sndgp->sndg[i].dwpt, sndgp->sndg[i].pres);
y = ps_pres_to_pix (sndgp->sndg[i].pres);
if (ok == 0)
{
ps_moveto (fp, x, y);
ok = 1;
}
else
{
ps_lineto (fp, x, y);
ok++;
}
}
}
if (ok > 1)
fprintf (fp, " stroke\n");
}
/*=========================================================================*/
void
ps_trace_wetbulb (FILE * fp)
/*************************************************************/
/* ps_trace_wetbulb */
/* */
/* Plots environmental Wet Bulb trace on SkewT. */
/*************************************************************/
{
short i, x, y, ok = 0;
float t1;
for (i = 0; i < sndgp->numlev; i++)
{
if (sndgp->sndg[i].dwpt > -200)
{
t1 =
wetbulb (sndgp->sndg[i].pres, sndgp->sndg[i].temp,
sndgp->sndg[i].dwpt);
x = ps_temp_to_pix (t1, sndgp->sndg[i].pres);
y = ps_pres_to_pix (sndgp->sndg[i].pres);
if (ok == 0)
{
ps_moveto (fp, x, y);
ok = 1;
}
else
{
ps_lineto (fp, x, y);
ok++;
}
}
}
if (ok > 1)
fprintf (fp, " stroke\n");
}
/*=======================================================================*/
void
ps_text (FILE * fp, char *textstr, short x, short y, short pts, short bold)
/*************************************************************/
/* PS_TEXT */
/* */
/* Writes given string at location (x,y). */
/* pts - Number of points for given font */
/* bold - Typeface indicator (0=NORM, 3=BOLD) */
/*************************************************************/
{
int iftyp1, iftyp2;
int font = 11;
float size = 1.0F;
static char *pfonts[12] = {
"Courier", "Helvetica", "Times-Roman",
"Courier-Oblique", "Helvetica-Oblique",
"Times-Italic", "Courier-Bold",
"Helvetica-Bold", "Times-Bold",
"Courier-BoldOblique",
"Helvetica-BoldOblique",
"Times-BoldItalic"
};
static float Psize = 0.5F;
iftyp1 = font / 10;
iftyp2 = font % 10;
if ((iftyp1 < 0) || (iftyp1 > 3))
iftyp1 = 0;
if ((iftyp2 < 1) || (iftyp2 > 3))
iftyp2 = 1;
font = iftyp1 * 3 + iftyp2;
if ((Pfont != font) || (!G_DIFF(Psize, size)) )
{
fprintf (fp, "/%s FF\n", pfonts[font - 1]);
fprintf (fp, "[%10.3f 0 0%10.3f 0 0] MS\n", size * 110, size * 110);
Pfont = font;
Psize = size;
}
ps_moveto (fp, x, y);
/* Write out the Text. */
switch (text_justify)
{
case 1: /* right justified */
fprintf (fp, "(%s) dup stringwidth pop neg 0 rmoveto show\n", textstr);
break;
case 2: /* cenetered text */
fprintf (fp, "(%s) dup stringwidth pop neg 2 div 0 rmoveto show\n",
textstr);
break;
default:
fprintf (fp, "(%s) show\n", textstr);
}
}
/*======================================================================*/
void
ps_wind_barb (FILE * fp, float wdir, float wspd, short x, short y, short siz)
/*************************************************************/
/* ps_wind_barb */
/* */
/* Plots wind barb at location (x,y) for given wind. */
/*************************************************************/
{
short x1, y1, x2, y2, x3, y3, sped;
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 ----- */
ps_moveto (fp, x1, y1);
ps_lineto (fp, x2, y2);
fprintf (fp, " stroke\n");
sped = (short) wspd;
x1 = x2;
y1 = y2;
wid = 6; /* Width of flags */
spcx = dx / wid;
spcy = dy / wid;
x1 = x1 + (short) spcx;
y1 = y1 - (short) spcy;
/* ----- Draw wind flags (increments of 50kt) ----- */
while (sped > 47)
{
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;
ps_triangle (fp, x1, y1, x2, y2, x3, y3, 1);
/*ps_moveto( fp, x1, y1);
ps_lineto( fp, x2, y2);
ps_lineto( fp, x3, y3); */
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;
ps_moveto (fp, x3, y3);
ps_lineto (fp, x2, y2);
fprintf (fp, " stroke\n");
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;
ps_moveto (fp, x3, y3);
ps_lineto (fp, x2, y2);
fprintf (fp, " stroke\n");
sped -= 10;
x1 = x3;
y1 = y3;
}
}
/*======================================================================*/
void
ps_plot_barbs (FILE * fp)
/*************************************************************/
/* ps_plot_barbs */
/* */
/* Plots wind barbs along side of thermo diagram. */
/*************************************************************/
{
short i, x, y;
float lastpres;
ps_cliprgn (fp, 20000, 0, 0, 20000);
/* ----- Draw vertical line ----- */
ps_moveto (fp, hsk.brx + 500, hsk.tly);
ps_lineto (fp, hsk.brx + 500, hsk.bry);
fprintf (fp, " stroke\n");
lastpres = 1100;
for (i = 0; i < sndgp->numlev; i++)
{
if (qc (sndgp->sndg[i].drct) && sndgp->sndg[i].pres >= 100)
{
y = ps_pres_to_pix (sndgp->sndg[i].pres);
x = hsk.brx + 500;
if ((sndgp->sndg[i].hght - i_hght (lastpres)) > 400)
{
ps_wind_barb (fp, sndgp->sndg[i].drct, sndgp->sndg[i].sped, x,
y, 45);
lastpres = sndgp->sndg[i].pres;
}
}
}
}
/*======================================================================*/
void
ps_trace_parcel (FILE * fp, float pres, float temp, float dwpt)
/*************************************************************/
/* ps_trace_parcel */
/* */
/* 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 (dwpt)) || (!qc (temp)) || (!qc (pres)))
return;
x = ps_temp_to_pix (virtemp (pres, temp, dwpt), pres);
y = ps_pres_to_pix (pres);
ps_moveto (fp, x, y);
drylift (pres, temp, dwpt, &p2, &t2);
x = ps_temp_to_pix (virtemp (p2, t2, t2), p2);
y = ps_pres_to_pix (p2);
ps_lineto (fp, x, y);
for (i = p2 - 50; i >= 100; i = i - 50)
{
t3 = wetlift (p2, t2, i);
x = ps_temp_to_pix (virtemp (i, t3, t3), i);
y = ps_pres_to_pix (i);
ps_lineto (fp, x, y);
}
t3 = wetlift (p2, t2, 100);
x = ps_temp_to_pix (virtemp (100, t3, t3), 100);
y = ps_pres_to_pix (100);
ps_lineto (fp, x, y);
fprintf (fp, " stroke\n");
}
/*======================================================================*/
void
ps_trace_parcelx (FILE * fp, float pres, float temp, float dwpt)
/*************************************************************/
/* ps_trace_parcelX */
/* */
/* 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;
x = ps_temp_to_pix (temp, pres);
y = ps_pres_to_pix (pres);
ps_moveto (fp, x, y);
drylift (pres, temp, dwpt, &p2, &t2);
x = ps_temp_to_pix (t2, p2);
y = ps_pres_to_pix (p2);
ps_lineto (fp, x, y);
for (i = p2 - 50; i >= 100; i = i - 50)
{
t3 = wetlift (p2, t2, i);
x = ps_temp_to_pix (t3, i);
y = ps_pres_to_pix (i);
ps_lineto (fp, x, y);
}
t3 = wetlift (p2, t2, 100);
x = ps_temp_to_pix (t3, 100);
y = ps_pres_to_pix (100);
ps_lineto (fp, x, y);
}
/*======================================================================*/
void
ps_triangle (FILE * fp, short x1, short y1, short x2, short y2,
short x3, short y3, short fill)
/*************************************************************/
/* ps_triangle */
/* */
/* Draws triangle of (x,y) coordinates. */
/* */
/* fill - Fill indicator (1=YES) */
/*************************************************************/
{
ps_moveto (fp, x1, y1);
ps_lineto (fp, x2, y2);
ps_lineto (fp, x3, y3);
fprintf (fp, " FL\n");
}
/*======================================================================*/
void
ps_draw_hodo (FILE * fp)
/*************************************************************/
/* ps_draw_hodo */
/* */
/* Draws a standard Hodograph diagram on a HP Laserjet */
/* printer. All graphic calls are HP-GL/2 dependent. */
/*************************************************************/
{
short x1, y1, i;
char st[10];
/* ----- Transparency mode off ----- */
ps_cliprgn (fp, hho.tlx, hho.tly, hho.brx, hho.bry);
ps_rectangle (fp, hho.tlx, hho.tly, hho.brx, hho.bry, 1, 0);
ps_select_pen (fp, 1, .75F, 9);
ps_rectangle (fp, hho.tlx, hho.tly, hho.brx, hho.bry, 0, 0);
/* ----- Plot crosshairs ----- */
ps_select_pen (fp, 1, .1F, 9);
ps_hodo_to_pix (180, 60, &x1, &y1);
ps_moveto (fp, x1, hho.tly);
ps_lineto (fp, x1, hho.bry);
fprintf (fp, " stroke\n");
ps_hodo_to_pix (270, 60, &x1, &y1);
ps_moveto (fp, hho.tlx, y1);
ps_lineto (fp, hho.brx, y1);
fprintf (fp, " stroke\n");
/* ----- Plot X-Coord hash marks ----- */
for (i = hho.scale; i <= hho.hodomag; i = i + hho.scale)
{
ps_hodo_to_pix (180, (float) i, &x1, &y1);
ps_moveto (fp, x1 - 30, y1);
ps_lineto (fp, x1 + 30, y1);
fprintf (fp, " stroke\n");
itoa (i, st, 10);
ps_text (fp, st, x1 + 50, y1 + 30, 6, 0);
ps_hodo_to_pix (360, (float) i, &x1, &y1);
ps_moveto (fp, x1 - 30, y1);
ps_lineto (fp, x1 + 30, y1);
fprintf (fp, " stroke\n");
itoa (i, st, 10);
ps_text (fp, st, x1 + 50, y1 + 30, 6, 0);
}
/* ----- Plot Y-Coord hash marks ----- */
for (i = hho.scale; i <= hho.hodomag; i = i + hho.scale)
{
ps_hodo_to_pix (90, (float) i, &x1, &y1);
ps_moveto (fp, x1, y1 - 30);
ps_lineto (fp, x1, y1 + 30);
fprintf (fp, " stroke\n");
itoa (i, st, 10);
ps_text (fp, st, x1 - 50, y1 + 80, 6, 0);
ps_hodo_to_pix (270, (float) i, &x1, &y1);
ps_moveto (fp, x1, y1 - 30);
ps_lineto (fp, x1, y1 + 30);
fprintf (fp, " stroke\n");
itoa (i, st, 10);
ps_text (fp, st, x1 - 50, y1 + 80, 6, 0);
}
ps_select_pen (fp, 1, .1F, 9);
ps_hodo_circs (fp);
/* ----- Plot Hodograph (Shear Vectors) ----- */
ps_select_pen (fp, 1, .15F, 9);
ps_trace_hodo (fp);
ps_select_pen (fp, 1, .15F, 9);
ps_label_hodo (fp);
}
/*======================================================================*/
void
ps_hodo_to_pix (float dir, float mag, short *x, short *y)
/*************************************************************/
/* ps_hodo_to_pix */
/* */
/* Calculates the printer location (x,y) in pels of the */
/* wind vector (dir,mag). */
/*************************************************************/
{
float midx, midy;
float scle;
scle = (hho.brx - hho.tlx) / hho.hodomag;
midx = hho.tlx + ((hho.brx - hho.tlx) / 2) + (hho.xshift * scle);
midy = hho.tly + ((hho.bry - hho.tly) / 2) - (hho.yshift * scle);
*x = (short) (midx - (ucomp (dir, mag) * scle));
*y = (short) (midy + (vcomp (dir, mag) * scle));
}
/*======================================================================*/
void
ps_trace_hodo (FILE * fp)
/*************************************************************/
/* ps_trace_hodo */
/* */
/* Plots environmental wind shear vectors on Hodograph. */
/*************************************************************/
{
short i, x, y, ok = 0;
for (i = 0; i < sndgp->numlev; i++)
{
if (qc (sndgp->sndg[i].drct) && qc (sndgp->sndg[i].sped))
{
ps_hodo_to_pix (sndgp->sndg[i].drct, sndgp->sndg[i].sped, &x, &y);
if (ok == 0)
{
ps_moveto (fp, x, y);
ok = 1;
}
else
{
ps_lineto (fp, x, y);
ok++;
}
}
}
if (ok > 1)
fprintf (fp, " stroke\n");
}
/*======================================================================*/
void
ps_label_hodo (FILE * fp)
/*************************************************************/
/* ps_label_hodo */
/* */
/* places labels on hodograph at predetermined levels. */
/*************************************************************/
{
float wdi, wsp;
short i, x, y;
short lvl[] = { 1000, 2000, 3000, 5000, 10000, 15000 };
char st[10];
for (i = 0; i <= 5; i++)
{
wdi = i_wdir (i_pres (msl (lvl[i])));
wsp = i_wspd (i_pres (msl (lvl[i])));
ps_hodo_to_pix (wdi, wsp, &x, &y);
sprintf (st, "%d", lvl[i] / 1000);
ps_text (fp, st, x - 60, y - 60, 8, 3);
}
/* ----- Display Storm Motion at Upper Left Corner ----- */
if (qc (sndgp->st_dir) && qc (sndgp->st_spd))
{
sprintf (st, "%d / %d kt", (short) sndgp->st_dir,
(short) sndgp->st_spd);
}
else
{
sprintf (st, "M / M");
}
ps_text (fp, st, hho.tlx + 50, hho.tly + 150, 9, 0);
}
/*======================================================================*/
void
ps_plot_elevs (FILE * fp)
/*************************************************************/
/* ps_plot_elevs */
/* */
/* Plots elevations (m, ft) MSL on right side of SkewT. */
/*************************************************************/
{
short y;
float hgt, tmpflt;
char st[80];
ps_cliprgn (fp, 20000, 0, 0, 20000);
/* ----- Draw base legend ----- */
ps_moveto (fp, hsk.brx + 1200, hsk.tly);
ps_lineto (fp, hsk.brx + 1200, hsk.bry);
fprintf (fp, " stroke\n");
ps_moveto (fp, hsk.brx + 900, hsk.tly);
ps_lineto (fp, hsk.brx + 1500, hsk.tly);
fprintf (fp, " stroke\n");
ps_text (fp, "MSL", hsk.brx + 1125, hsk.tly - 95, 7, 3);
ps_text (fp, "kft km", hsk.brx + 1000, hsk.tly - 15, 7, 3);
/* ----- Find SFC level and plot ----- */
y = ps_pres_to_pix (sndgp->sndg[sfc ()].pres);
ps_moveto (fp, hsk.brx + 1150, y);
ps_lineto (fp, hsk.brx + 1250, y);
fprintf (fp, " stroke\n");
sprintf (st, "%d m", (short)sndgp->sndg[sfc ()].hght);
ps_text (fp, st, hsk.brx + 1300, y + 30, 7, 0);
tmpflt = mtof(sndgp->sndg[sfc ()].hght);
sprintf (st, "%d ft", (short)tmpflt );
ps_disp_param (fp, st, hsk.brx + 800, y + 30, 7, 0);
/*ps_text( fp, st, hsk.brx + 800, y + 30, 7, 0); */
/* ----- Plot every 1km ----- */
for (hgt = 1000; hgt < sndgp->sndg[sndgp->numlev - 1].hght; hgt += 1000)
{
if (i_pres (hgt) > 100)
{
y = ps_pres_to_pix (i_pres (hgt));
ps_moveto (fp, hsk.brx + 1200, y);
ps_lineto (fp, hsk.brx + 1250, y);
fprintf (fp, " stroke\n");
sprintf (st, "%d", (short) (hgt / 1000));
ps_text (fp, st, hsk.brx + 1300, y + 30, 7, 0);
}
}
/* ----- Plot every 5kft ----- */
tmpflt = mtof(sndgp->sndg[sndgp->numlev - 1].hght);
for (hgt = 5000; hgt < tmpflt; hgt += 5000)
{
if (i_pres (ftom (hgt)) > 100)
{
y = ps_pres_to_pix (i_pres (ftom (hgt)));
ps_moveto (fp, hsk.brx + 1150, y);
ps_lineto (fp, hsk.brx + 1200, y);
fprintf (fp, " stroke\n");
sprintf (st, "%d", (short) (hgt / 1000));
ps_text (fp, st, hsk.brx + 1000, y + 30, 7, 0);
}
}
}
/*======================================================================*/
void
ps_hodo_circs (FILE * fp)
/*************************************************************/
/* ps_hodo_circs */
/* */
/* Draws speed rings on hodograph as scale increments. */
/*************************************************************/
{
short x1, y1, x2, y2, i;
ps_hodo_to_pix (180, 0, &x1, &y1);
for (i = hho.scale; i <= hho.hodomag; i = i + hho.scale)
{
ps_hodo_to_pix (180, (float) i, &x2, &y2);
ps_circle (fp, x1, y1, abs (y2 - y1));
}
}
/*======================================================================*/
void
ps_circle (FILE * fp, short x, short y, short radius)
/*************************************************************/
/* ps_circle */
/* */
/* Draws a circle at (x,y) of radius (radius). */
/*************************************************************/
{
fprintf (fp, "N %d %d M %d %d %d 0 360 arc\n", x, y, x, y, radius);
}
/*======================================================================*/
void
ps_write_parcel (FILE * fp)
/*************************************************************/
/* ps_write_parcel */
/* */
/* Writes parcel data to printer. */
/*************************************************************/
{
char st[80];
short x1, y1;
float sfctemp, sfcdwpt, sfcpres, p;
struct _parcel pcl;
sfctemp = sndgp->lplvals.temp;
sfcdwpt = sndgp->lplvals.dwpt;
sfcpres = sndgp->lplvals.pres;
x1 = 100;
y1 = hsk.bry + 500;
ps_cliprgn (fp, 20000, 0, 0, 20000);
ps_centertext (fp, "THERMODYNAMIC PARAMETERS", x1 + 1500, y1, 12, 3);
ps_select_pen (fp, 1, .4F, 9);
ps_rectangle (fp, x1 - 50, y1 + 20, x1 + 3000, 9800, 0, 0);
/* ----- Selected parcel type ----- */
y1 += 200;
sprintf (st, "%s", sndgp->lplvals.desc);
ps_text (fp, st, x1, y1, 9, 0);
/* ----- Lifted Parcel Information ----- */
y1 += 200;
sprintf (st, "LPL: %4.0fmb %4.0fC/%4.0fC %4.0fF/%4.0fF",
sndgp->lplvals.pres,
sndgp->lplvals.temp, sndgp->lplvals.dwpt,
ctof (sndgp->lplvals.temp), ctof (sndgp->lplvals.dwpt));
ps_text (fp, st, x1, y1, 9, 0);
/* ----- Calculate Parcel Data ----- */
parcel (-1, -1, sfcpres, sfctemp, sfcdwpt, &pcl);
/* ----- CAPE/LI ----- */
y1 += 200;
ps_text (fp, "CAPE:", x1, y1, 9, 0);
strcpy (st, qc2 (pcl.bplus, " J/kg", 0));
ps_disp_param (fp, st, x1 + 1200, y1, 9, 0);
ps_text (fp, "LI:", x1 + 1500, y1, 9, 0);
strcpy (st, qc2 (pcl.li5, " C @ 500mb", 0));
ps_disp_param (fp, st, x1 + 2900, y1, 9, 0);
/* ----- BFZL/LImin ----- */
y1 += 150;
ps_text (fp, "BFZL:", x1, y1, 9, 0);
strcpy (st, qc2 (pcl.bfzl, " J/kg", 0));
ps_disp_param (fp, st, x1 + 1200, y1, 9, 0);
ps_text (fp, "LImin:", x1 + 1500, y1, 9, 0);
if (qc (pcl.limax))
{
strcpy (st, qc2 (pcl.limax, " C @ ", 0));
strcat (st, qc2 (pcl.limaxpres, "mb", 0));
}
else
{
strcpy (st, "M");
}
ps_disp_param (fp, st, x1 + 2900, y1, 9, 0);
/* ----- CINH/CAP ----- */
y1 += 150;
ps_text (fp, "CINH:", x1, y1, 9, 0);
strcpy (st, qc2 (pcl.bminus, " J/kg", 0));
ps_disp_param (fp, st, x1 + 1200, y1, 9, 0);
ps_text (fp, "CAP:", x1 + 1500, y1, 9, 0);
if (qc (pcl.cap))
{
strcpy (st, qc2 (pcl.cap, " C @ ", 0));
strcat (st, qc2 (pcl.cappres, "mb", 0));
}
else
{
strcpy (st, "M");
}
ps_disp_param (fp, st, x1 + 2900, y1, 9, 0);
/* ----- Header for LEVEL data ----- */
y1 += 200;
ps_disp_param (fp, "LEVEL", x1 + 400, y1, 9, 0);
ps_disp_param (fp, "PRES", x1 + 1100, y1, 9, 0);
ps_disp_param (fp, "HGT(AGL)", x1 + 2100, y1, 9, 0);
ps_disp_param (fp, "TEMP", x1 + 2900, y1, 9, 0);
y1 += 20;
ps_select_pen (fp, 1, .1F, 9);
ps_moveto (fp, x1, y1);
ps_lineto (fp, x1 + 2950, y1);
fprintf (fp, " stroke\n");
/* ----- LCL ----- */
y1 += 150;
p = pcl.lclpres;
ps_lvldata (fp, p, "LCL", x1, y1);
/* ----- LFC ----- */
y1 += 150;
p = pcl.lfcpres;
ps_lvldata (fp, p, "LFC", x1, y1);
strcpy (st, qc2 (i_temp (p), " C", 0));
ps_disp_param (fp, st, x1 + 2900, y1, 9, 0);
/* ----- EL ----- */
y1 += 150;
p = pcl.elpres;
ps_lvldata (fp, p, "EL", x1, y1);
strcpy (st, qc2 (i_temp (p), " C", 0));
ps_disp_param (fp, st, x1 + 2900, y1, 9, 0);
/* ----- MPL ----- */
y1 += 150;
p = pcl.mplpres;
ps_lvldata (fp, p, "MPL", x1, y1);
y1 += 50;
ps_select_pen (fp, 1, .4F, 9);
ps_moveto (fp, x1 - 50, y1);
ps_lineto (fp, x1 + 3000, y1);
fprintf (fp, " stroke\n");
}
/*=======================================================================*/
void
ps_write_thermo (FILE * fp)
/*************************************************************/
/* ps_write_thermo */
/* */
/* Writes thermo data to printer. */
/*************************************************************/
{
char st[80];
short x1, y1;
float ix1, ix2, ix3;
/*-----------------------------------------------------------------------*/
x1 = 100;
y1 = 8406;
/* ----- PW and Mean RH ----- */
ps_text (fp, "Precip Water:", x1, y1, 9, 0);
strcpy (st, qc2 (precip_water (&ix1, -1, -1), " in", 2));
ps_disp_param (fp, st, x1 + 1400, y1, 9, 0);
ps_text (fp, "Mean RH:", x1 + 1600, y1, 9, 0);
strcpy (st, qc2 (mean_relhum (&ix1, -1, -1), " %", 0));
ps_disp_param (fp, st, x1 + 2900, y1, 9, 0);
/* ----- Mean MR and Mean LRH ----- */
y1 += 150;
ps_text (fp, "Mean Q:", x1, y1, 9, 0);
strcpy (st, qc2 (mean_mixratio (&ix1, -1, -1), " g/kg", 1));
ps_disp_param (fp, st, x1 + 1400, y1, 9, 0);
ps_text (fp, "Mean LRH:", x1 + 1600, y1, 9, 0);
strcpy (st,
qc2 (mean_relhum (&ix1, -1, sndgp->sndg[sfc ()].pres - 150), " %",
0));
ps_disp_param (fp, st, x1 + 2900, y1, 9, 0);
/* ----- Top of Moist Layer ----- */
y1 += 150;
ps_text (fp, "Top of Moist Layer:", x1, y1, 9, 0);
strcpy (st, qc2 (top_moistlyr (&ix1), " mb", 0));
strcat (st, " / ");
strcat (st, qc2 (mtof(agl (i_hght (ix1))), " ft", 0));
ps_text (fp, st, x1 + 1600, y1, 9, 0);
y1 += 50;
ps_select_pen (fp, 1, .4F, 9);
ps_moveto (fp, x1 - 50, y1);
ps_lineto (fp, x1 + 3000, y1);
fprintf (fp, " stroke\n");
/* ----- 700-500mb Lapse Rates ----- */
y1 += 150;
ps_text (fp, "700-500mb Lapse Rate:", x1, y1, 9, 0);
strcpy (st, qc2 (delta_t (&ix1), " C", 0));
strcat (st, " / ");
strcat (st, qc2 (lapse_rate (&ix1, 700, 500), " C/km", 1));
ps_text (fp, st, x1 + 1600, y1, 9, 0);
/* ----- 850-500mb Lapse Rates ----- */
y1 += 150;
ps_text (fp, "850-500mb Lapse Rate:", x1, y1, 9, 0);
strcpy (st, qc2 (vert_tot (&ix1), " C", 0));
strcat (st, " / ");
strcat (st, qc2 (lapse_rate (&ix1, 850, 500), " C/km", 1));
ps_text (fp, st, x1 + 1600, y1, 9, 0);
y1 += 50;
ps_moveto (fp, x1 - 50, y1);
ps_lineto (fp, x1 + 3000, y1);
fprintf (fp, " stroke\n");
/* ----- Total-Totals and K-Index ----- */
y1 += 150;
ps_text (fp, "Total Totals:", x1, y1, 9, 0);
strcpy (st, qc2 (t_totals (&ix1, &ix2, &ix3), "", 0));
ps_disp_param (fp, st, x1 + 1400, y1, 9, 0);
ps_text (fp, "K-Index:", x1 + 1600, y1, 9, 0);
strcpy (st, qc2 (k_index (&ix1), "", 0));
ps_disp_param (fp, st, x1 + 2900, y1, 9, 0);
/* -----SWEAT and Max Temp ----- */
y1 += 150;
ps_text (fp, "SWEAT Index:", x1, y1, 9, 0);
strcpy (st, qc2 (sweat_index (&ix1), "", 0));
ps_disp_param (fp, st, x1 + 1400, y1, 9, 0);
ps_text (fp, "Max Temp:", x1 + 1600, y1, 9, 0);
strcpy (st, qc2 (ctof (max_temp (&ix1, -1)), " F", 0));
ps_disp_param (fp, st, x1 + 2900, y1, 9, 0);
/* ----- ThetaE Diff and Convective Temp ----- */
y1 += 150;
ps_text (fp, "ThetaE Diff:", x1, y1, 9, 0);
ix2 = ThetaE_diff (&ix1);
strcpy (st, qc2 (ix2, " C", 0));
ps_disp_param (fp, st, x1 + 1400, y1, 9, 0);
ix2 = cnvtv_temp (&ix1, -50);
ps_text (fp, "*Conv Temp:", x1 + 1600, y1, 9, 0);
strcpy (st, qc2 (ctof (ix2), " F", 0));
ps_disp_param (fp, st, x1 + 2900, y1, 9, 0);
/* ----- FZL and WBZ ----- */
y1 += 150;
ps_text (fp, "FRZ Level:", x1, y1, 9, 0);
strcpy (st, qc2 (mtof(agl (i_hght (temp_lvl (0, &ix1)))), " ft", 0));
ps_disp_param (fp, st, x1 + 1400, y1, 9, 0);
ps_text (fp, "WBZ Level:", x1 + 1600, y1, 9, 0);
strcpy (st, qc2 (mtof(agl (i_hght (wb_lvl (0, &ix1)))), " ft", 0));
ps_disp_param (fp, st, x1 + 2900, y1, 9, 0);
}
/*====================================================================*/
void
ps_disp_param (FILE * fp, char *st, short x, short y, short font, short tf)
/*************************************************************/
/* ps_disp_param */
/* */
/* Right justifies value at location x,y. */
/*************************************************************/
{
text_justify = 1;
fprintf (fp, "%% need to right justify %d\n", text_justify);
ps_text (fp, st, x, y, font, tf);
text_justify = 0;
}
/*======================================================================*/
void
ps_fill_cape (FILE * fp, short pct)
/*************************************************************/
/* ps_fill_cape */
/* */
/* Fills the positive area with grey area. */
/*************************************************************/
{
short x, y, i, j, xs, ys;
float t1, p1, t2, p2, sfcpres, sfctemp, sfcdwpt, pres;
float grayf;
struct _parcel pcl;
sfcpres = sndgp->lplvals.pres;
sfctemp = sndgp->lplvals.temp;
sfcdwpt = sndgp->lplvals.dwpt;
/* ----- Calculate Parcel Data ----- */
parcel (-1, -1, sfcpres, sfctemp, sfcdwpt, &pcl);
if (pcl.bplus <= 0)
{
return;
}
/* ----- Account for partial soundings ----- */
if (!qc (pcl.elpres))
{
pcl.elpres = sndgp->sndg[sndgp->numlev - 1].pres;
}
/* ----- Start at LFC ----- */
fprintf (fp, "\n%% Plot cape\nN ");
p1 = pcl.lfcpres;
t1 = i_vtmp (pcl.lfcpres);
x = ps_temp_to_pix (t1, p1);
y = ps_pres_to_pix (p1);
ps_moveto (fp, x, y);
xs = x;
ys = y;
/* ----- Trace up temperature line ----- */
i = 0;
while (sndgp->sndg[i].pres > pcl.lfcpres)
{
i++;
}
for (j = i; sndgp->sndg[j].pres > pcl.elpres; j++)
{
if (qc (sndgp->sndg[j].temp))
{
p1 = sndgp->sndg[j].pres;
t1 = i_vtmp (p1);
x = ps_temp_to_pix (t1, p1);
y = ps_pres_to_pix (p1);
ps_lineto (fp, x, y);
}
}
grayf = ((float) (100. - pct)) / 100.;
fprintf (fp, "%5.3f %5.3f %5.3f RGB\n", grayf, grayf, grayf);
/* ----- Now, starting at EL, go back down Thw to LFC ----- */
drylift (sfcpres, sfctemp, sfcdwpt, &p2, &t2);
for (pres = pcl.elpres; pres < pcl.lfcpres; pres += 50)
{
t1 = wetlift (p2, t2, pres);
x = ps_temp_to_pix (virtemp (pres, t1, t1), pres);
y = ps_pres_to_pix (pres);
ps_lineto (fp, x, y);
}
/* ----- Finish Polygon by returning to LFC ----- */
ps_lineto (fp, xs, ys);
fprintf (fp, "FL\n");
}
/*======================================================================*/
void
ps_fill_capex (FILE * fp, short pct)
/*************************************************************/
/* ps_fill_capeX */
/* */
/* Fills the positive area with grey area. */
/*************************************************************/
{
short x, y, i, j, xs, ys;
float t1, p1, t2, p2, sfcpres, sfctemp, sfcdwpt, pres;
struct _parcel pcl;
sfcpres = sndgp->lplvals.pres;
sfctemp = sndgp->lplvals.temp;
sfcdwpt = sndgp->lplvals.dwpt;
/* ----- Calculate Parcel Data ----- */
parcelx (-1, -1, sfcpres, sfctemp, sfcdwpt, &pcl);
if (pcl.bplus <= 0)
{
return;
}
/* ----- Set Polygon Mode ----- */
fputs ("PM0;", fp);
/* ----- Start at LFC ----- */
p1 = pcl.lfcpres;
t1 = i_temp (pcl.lfcpres);
x = ps_temp_to_pix (t1, p1);
y = ps_pres_to_pix (p1);
ps_moveto (fp, x, y);
xs = x;
ys = y;
/* ----- Trace up temperature line ----- */
i = 0;
while (sndgp->sndg[i].pres > pcl.lfcpres)
{
i++;
}
for (j = i; sndgp->sndg[j].pres > pcl.elpres; j++)
{
if (qc (sndgp->sndg[j].temp))
{
p1 = sndgp->sndg[j].pres;
t1 = i_temp (p1);
x = ps_temp_to_pix (t1, p1);
y = ps_pres_to_pix (p1);
ps_lineto (fp, x, y);
}
}
/* ----- Now, starting at EL, go back down Thw to LFC ----- */
drylift (sfcpres, sfctemp, sfcdwpt, &p2, &t2);
for (pres = pcl.elpres; pres < pcl.lfcpres; pres += 50)
{
t1 = wetlift (p2, t2, pres);
x = ps_temp_to_pix (t1, pres);
y = ps_pres_to_pix (pres);
ps_lineto (fp, x, y);
}
/* ----- Finish Polygon by returning to LFC ----- */
ps_lineto (fp, xs, ys);
/* ----- End Polygon Mode ----- */
fputs ("PM2;", fp);
/* ----- Transparency mode on ----- */
fputs ("TR1;", fp);
/* ----- Set Fill Density and Finish Fill ----- */
fprintf (fp, "FT10,%d;", pct);
fputs ("FP;", fp);
}
/*======================================================================*/
void
ps_centertext (FILE * fp, char *st, short x, short y, short font, short tf)
/*************************************************************/
/* ps_centertext */
/* */
/* Writes given string at location (x,y). */
/* pts - Number of points for given font */
/* bold - Typeface indicator (0=NORM, 3=BOLD) */
/*************************************************************/
{
fprintf (fp, "%% need to center text\n");
text_justify = 2;
ps_text (fp, st, x, y, font, tf);
text_justify = 0;
}
/*======================================================================*/
void
ps_lvldata (FILE * fp, float pres, char *nam, short x, short y)
/*************************************************************/
/* ps_lvldata */
/* */
/* Write level data to printer (used in parcel area). */
/*************************************************************/
{
char st[80];
if (qc (pres))
{
ps_disp_param (fp, nam, x + 400, y, 9, 0);
strcpy (st, qc2 (pres, "mb", 0));
ps_disp_param (fp, st, x + 1100, y, 9, 0);
strcpy (st, qc2 (mtof(agl (i_hght (pres))), "ft", 0));
ps_disp_param (fp, st, x + 2100, y, 9, 0);
}
else
{
ps_disp_param (fp, nam, x + 400, y, 9, 0);
ps_disp_param (fp, "M", x + 1100, y, 9, 0);
ps_disp_param (fp, "M", x + 2100, y, 9, 0);
}
}
/*======================================================================*/
void
ps_sharp_label (FILE * fp, short x1, short y1)
/*************************************************************/
/* ps_sharp_label */
/* */
/* Writes SHARP label on page at specified (x,y) */
/*************************************************************/
{
char st[80];
strcpy (st, "Output produced by Unidata postscript driver:");
ps_text (fp, st, x1 + 25, y1 + 80, 5, 3);
ps_moveto (fp, x1 + 25, y1 + 80);
fprintf (fp, " (%s)\n", st);
fprintf (fp, "true charpath pathbbox 40 add /uy exch def pop pop pop\n");
strcpy (st, "NSHARP (SkewT-Hodograph Analysis and Research Program)");
ps_text (fp, st, x1 + 25, y1 + 160, 5, 3);
ps_moveto (fp, x1 + 25, y1 + 160);
fprintf (fp, " (%s)\n", st);
fprintf (fp,
"true charpath pathbbox pop 60 add /ux exch def 60 sub /ly exch def 60 sub /lx exch def\n");
fprintf (fp, "N lx ly M ux ly L ux uy L lx uy L lx ly L stroke\n");
/*strcpy( st, " ");
ps_text( fp, st, x1 + 25, y1 + 240, 5, 3);
ps_select_pen( fp, 1, .3F, 9 );
ps_rectangle( fp, x1, y1, x1 + 2195, y1 + 280, 0, 0 ); */
}
/*====================================================================*/
void
ps_write_winds (FILE * fp)
/*************************************************************/
/* ps_write_winds */
/* */
/* Writes wind data to printer. */
/*************************************************************/
{
char st[80];
short x1, y1;
float ix1, ix2, ix3, ix4, tmpflt;
struct _parcel pcl;
/*-------------------------------------------------------------------*/
x1 = 3500;
y1 = hsk.bry + 500;
ps_cliprgn (fp, 20000, 0, 0, 20000);
ps_centertext (fp, "KINEMATIC PARAMETERS", x1 + 1500, y1, 12, 3);
ps_select_pen (fp, 1, .4F, 9);
ps_rectangle (fp, x1 - 50, y1 + 20, x1 + 3000, 7700, 0, 0);
/* ----- 0-6km Mean Wind ----- */
y1 += 200;
ps_text (fp, "Sfc - 6 km Mean Wind:", x1, y1, 9, 0);
mean_wind (-1, i_pres (agl (6000)), &ix1, &ix2, &ix3, &ix4);
if (qc (ix3) && qc (ix4))
{
tmpflt = kt_to_mps(ix4);
sprintf (st, "%d / %d kt (%d m/s)", (short)ix3, (short)ix4,
(short)tmpflt);
}
else
{
sprintf (st, "M / M");
}
ps_disp_param (fp, st, x1 + 2900, y1, 9, 0);
/* ----- LFC-EL Mean Wind ----- */
y1 += 150;
ps_text (fp, "LFC - EL Mean Wind:", x1, y1, 9, 0);
mean_wind (-1, -1, &ix1, &ix2, &ix3, &ix4);
if (qc (ix3) && qc (ix4))
{
tmpflt = kt_to_mps(ix4);
sprintf (st, "%d / %d kt (%d m/s)", (short) ix3, (short) ix4,
(short)tmpflt);
}
else
{
sprintf (st, "M / M");
}
ps_disp_param (fp, st, x1 + 2900, y1, 9, 0);
/* ----- 850-300 Mean Wind ----- */
y1 += 150;
ps_text (fp, "850 - 300 Mean Wind:", x1, y1, 9, 0);
mean_wind (850, 300, &ix1, &ix2, &ix3, &ix4);
if (qc (ix3) && qc (ix4))
{
tmpflt = kt_to_mps(ix4);
sprintf (st, "%d / %d kt (%d m/s)", (short) ix3, (short) ix4,
(short)tmpflt);
}
else
{
sprintf (st, "M / M");
}
ps_disp_param (fp, st, x1 + 2900, y1, 9, 0);
y1 += 200;
ps_moveto (fp, x1, y1);
ps_lineto (fp, x1 + 3000, y1);
/* ----- Sfc-2km Shear ----- */
y1 += 150;
wind_shear (-1, i_pres (msl (2000)), &ix1, &ix2, &ix3, &ix4);
ps_text (fp, "Sfc - 2km Shear:", x1, y1, 9, 0);
if (qc (ix3) && qc (ix4))
{
sprintf (st, "%d kt", (short)ix4);
ps_disp_param (fp, st, x1 + 1700, y1, 9, 0);
tmpflt = kt_to_mps(ix4);
sprintf (st, "(%d m/s)", (short)tmpflt);
ps_disp_param (fp, st, x1 + 2500, y1, 9, 0);
}
else
{
strcpy (st, "M");
ps_disp_param (fp, st, x1 + 1700, y1, 9, 0);
}
/* ----- Sfc-6km Shear ----- */
y1 += 150;
wind_shear (-1, i_pres (msl (6000)), &ix1, &ix2, &ix3, &ix4);
ps_text (fp, "Sfc - 6km Shear:", x1, y1, 9, 0);
if (qc (ix3) && qc (ix4))
{
sprintf (st, "%d kt", (short)ix4);
ps_disp_param (fp, st, x1 + 1700, y1, 9, 0);
tmpflt = kt_to_mps(ix4);
sprintf (st, "(%d m/s)", (short)tmpflt);
ps_disp_param (fp, st, x1 + 2500, y1, 9, 0);
}
else
{
strcpy (st, "M");
ps_disp_param (fp, st, x1 + 1700, y1, 9, 0);
}
/* ----- BRN Shear ----- */
y1 += 150;
pcl.bplus = 1;
pcl.lplpres = sndgp->lplvals.pres;
ix2 = bulk_rich (pcl, &ix1);
ps_text (fp, "*BRN Shear:", x1, y1, 9, 0);
if (qc (ix3) && qc (ix4))
{
sprintf (st, "%d m2/s2", (short) ix1);
ps_disp_param (fp, st, x1 + 2500, y1, 9, 0);
}
else
{
strcpy (st, "M");
ps_disp_param (fp, st, x1 + 2100, y1, 9, 0);
}
}
/*======================================================================*/
void
ps_write_storm (FILE * fp)
/*************************************************************/
/* ps_write_storm */
/* */
/* Writes storm data to printer. */
/*************************************************************/
{
char st[80], st1[80];
short x1, y1;
float sfctemp, sfcdwpt, sfcpres, hel3;
float ix1, ix2, ix3, ix4;
struct _parcel pcl;
sfctemp = sndgp->lplvals.temp;
sfcdwpt = sndgp->lplvals.dwpt;
sfcpres = sndgp->lplvals.pres;
parcel (-1, -1, sfcpres, sfctemp, sfcdwpt, &pcl);
x1 = 3500;
y1 = 8000;
ps_cliprgn (fp, 20000, 0, 0, 20000);
ps_centertext (fp, "STORM STRUCTURE PARAMETERS", x1 + 1500, y1, 12, 3);
ps_select_pen (fp, 1, .4F, 9);
ps_rectangle (fp, x1 - 50, y1 + 20, x1 + 3000, 9200, 0, 0);
/* ----- Sfc-3km SREH ----- */
y1 += 200;
ix1 = helicity (0, 3000, sndgp->st_dir, sndgp->st_spd, &ix2, &ix3);
hel3 = ix1;
ps_text (fp, "Sfc - 3km SREH:", x1, y1, 9, 0);
if (qc (ix1))
{
sprintf (st, "%.0f m2/s2", ix1);
ps_disp_param (fp, st, x1 + 1700, y1, 9, 0);
}
else
{
strcpy (st, "M");
ps_disp_param (fp, st, x1 + 1700, y1, 9, 0);
}
/* ----- Effective SREH ----- */
y1 += 150;
ix1 = helicity (-1, -1, sndgp->st_dir, sndgp->st_spd, &ix2, &ix3);
ps_text (fp, "Effective SREH:", x1, y1, 9, 0);
if (qc (ix1))
{
sprintf (st, "%.0f m2/s2", ix1);
sprintf (st1, "from %.0f m.", agl (i_hght (esfc (50))));
ps_disp_param (fp, st, x1 + 1700, y1, 9, 0);
ps_disp_param (fp, st1, x1 + 2600, y1, 9, 0);
}
else
{
strcpy (st, "M");
ps_disp_param (fp, st, x1 + 1700, y1, 9, 0);
}
y1 += 200;
ps_moveto (fp, x1, y1);
ps_lineto (fp, x1 + 3000, y1);
/* ----- 0-2 km Storm Relative Winds ----- */
y1 += 150;
ps_text (fp, "0-2 km SRW:", x1, y1, 9, 0);
sr_wind (-1, i_pres (msl (2000)), sndgp->st_dir, sndgp->st_spd, &ix1, &ix2,
&ix3, &ix4);
if (qc (ix4))
{
sprintf (st, "%.0f kt", ix4);
ps_disp_param (fp, st, x1 + 1300, y1, 9, 0);
}
else
{
ps_disp_param (fp, "M", x1 + 1300, y1, 9, 0);
}
/* ----- EHI ----- */
ps_text (fp, "EHI:", x1 + 1700, y1, 9, 0);
ix1 = ehi (pcl.bplus, hel3);
if (qc (ix1))
{
sprintf (st, "%.1f", ix1);
ps_disp_param (fp, st, x1 + 2900, y1, 9, 0);
}
else
{
ps_disp_param (fp, "M", x1 + 2900, y1, 9, 0);
}
/* ----- 4-6 km Storm Relative Winds ----- */
y1 += 150;
ps_text (fp, "4-6 km SRW:", x1, y1, 9, 0);
sr_wind (i_pres (msl (4000)), i_pres (msl (6000)), sndgp->st_dir,
sndgp->st_spd, &ix1, &ix2, &ix3, &ix4);
if (qc (ix4))
{
sprintf (st, "%.0f kt", ix4);
ps_disp_param (fp, st, x1 + 1300, y1, 9, 0);
}
else
{
ps_disp_param (fp, "M", x1 + 1300, y1, 9, 0);
}
/* ----- BRN ----- */
ps_text (fp, "BRN:", x1 + 1700, y1, 9, 0);
ix1 = bulk_rich (pcl, &ix2);
if (qc (ix1))
{
sprintf (st, "%.0f", ix1);
ps_disp_param (fp, st, x1 + 2900, y1, 9, 0);
}
else
{
ps_disp_param (fp, "M", x1 + 2900, y1, 9, 0);
}
/* ----- 6-10 km Storm Relative Winds ----- */
y1 += 150;
ps_text (fp, "6-10 km SRW:", x1, y1, 9, 0);
sr_wind (i_pres (msl (6000)), i_pres (msl (10000)), sndgp->st_dir,
sndgp->st_spd, &ix1, &ix2, &ix3, &ix4);
if (qc (ix4))
{
sprintf (st, "%.0f kt", ix4);
ps_disp_param (fp, st, x1 + 1300, y1, 9, 0);
}
else
{
ps_disp_param (fp, "M", x1 + 1300, y1, 9, 0);
}
}
/*======================================================================*/
void
ps_plot_uvvs (FILE * fp)
/*************************************************************/
/* ps_plot_uvvs */
/* */
/* Plots VVs (Mbps) on right side of SkewT. */
/*************************************************************/
{
short i, x, y, x1, avail;
float leng, scal;
scal = 1000;
ps_cliprgn (fp, 20000, 0, 0, 20000);
ps_select_pen (fp, 1, .25F, 9);
x1 = hsk.brx + 1900;
/* ----- Plot every level ----- */
avail = 0;
for (i = 0; i < sndgp->numlev; i++)
{
if (qc (sndgp->sndg[i].omega) && (sndgp->sndg[i].omega < 1))
{
avail++;
y = ps_pres_to_pix (sndgp->sndg[i].pres);
leng = (sndgp->sndg[i].omega * scal); /* Convert to Mbs/sec */
ps_select_pen (fp, 1, .05F, 9);
if (abs (leng) > 5)
ps_select_pen (fp, 1, .10F, 9);
if (abs (leng) > 10)
ps_select_pen (fp, 1, .35F, 9);
if (abs (leng) > 15)
ps_select_pen (fp, 1, .50F, 9);
x = x1 - (leng * 15); /* Determine screen scale */
ps_moveto (fp, x1, y);
ps_lineto (fp, x, y);
}
}
if (avail > 5)
{
/* ----- Draw base legend ----- */
ps_select_pen (fp, 1, .20F, 9);
ps_moveto (fp, x1, hsk.tly);
ps_lineto (fp, x1, hsk.bry);
ps_select_pen (fp, 1, .10F, 11);
ps_moveto (fp, x1 + 150, hsk.tly);
ps_lineto (fp, x1 + 150, hsk.bry);
ps_select_pen (fp, 1, .10F, 11);
ps_moveto (fp, x1 - 150, hsk.tly);
ps_lineto (fp, x1 - 150, hsk.bry);
ps_select_pen (fp, 1, .20F, 9);
ps_moveto (fp, x1 - 300, hsk.tly);
ps_lineto (fp, x1 + 300, hsk.tly);
ps_centertext (fp, "VVEL (Mbps)", x1, hsk.tly - 95, 7, 3);
ps_centertext (fp, "Down Up ", x1, hsk.tly - 15, 7, 3);
}
}
/*======================================================================*/
void
_sounding_plot (FILE * fp)
{
ps_draw_skewt (fp);
ps_select_pen (fp, 1, 1, 9);
ps_draw_hodo (fp);
ps_write_parcel (fp);
ps_write_thermo (fp);
ps_write_winds (fp);
ps_write_storm (fp);
ps_plot_uvvs (fp);
ps_sharp_label (fp, 75, 9845);
}