diff -uNr GMT4.2.1/src/GMT.1 GMT4.2.1_barb/src/GMT.1 --- GMT4.2.1/src/GMT.1 2007-10-11 05:03:16.000000000 +0900 +++ GMT4.2.1_barb/src/GMT.1 2007-12-11 17:15:13.000000000 +0900 @@ -53,6 +53,8 @@ .br \fBgrd2xyz\fP Conversion from 2-D gridded file to table data .br +\fBgrdbarb\fP Plot wind barbs from grdfiles +.br \fBgrdblend\fP Blend several partially over-lapping grid files onto one grid .br \fBgrdclip\fP Limit the z-range in gridded data diff -uNr GMT4.2.1/src/GMT.in GMT4.2.1_barb/src/GMT.in --- GMT4.2.1/src/GMT.in 2007-10-06 02:32:56.000000000 +0900 +++ GMT4.2.1_barb/src/GMT.in 2007-12-11 20:36:48.000000000 +0900 @@ -76,6 +76,7 @@ gmtselect Extract data subsets based on spatial criteria grd2cpt Make a color palette table from a grid file grd2xyz Conversion from 2-D gridded file to table data + grdbarb Plot wind barbs from grdfiles grdblend Blend several partially over-lapping grid files onto one grid grdclip Limit the z-range in gridded data grdcontour Contouring of 2-D gridded data diff -uNr GMT4.2.1/src/gmt_init.c GMT4.2.1_barb/src/gmt_init.c --- GMT4.2.1/src/gmt_init.c 2007-10-08 07:41:05.000000000 +0900 +++ GMT4.2.1_barb/src/gmt_init.c 2007-12-11 20:36:48.000000000 +0900 @@ -4974,6 +4974,7 @@ char symbol_type, txt_a[GMT_LONG_TEXT], txt_b[GMT_LONG_TEXT], txt_c[GMT_LONG_TEXT], text_cp[GMT_LONG_TEXT], *c; static char *allowed_symbols[2] = {"-aAbBCcDdeEfGgHhIijJNnpqrSsTtVvwWxy", "-aAbCcDdeEfGgHhIijJNnoOpqrSsTtuUVvwWxy"}; static char *bar_symbols[2] = {"bB", "-bBoOuU"}; + static char *barb_symbols[2] = {"wW", "wW"}; p->n_required = p->convert_angles = 0; p->user_unit = p->shrink = p->read_vector = p->base_set = FALSE; @@ -5044,6 +5045,12 @@ if (p->size_y == 0.0) p->size_y = p->given_size_y; p->equal_area = FALSE; } + else if (strchr (barb_symbols[mode], (int) text[0]) && (text[1] == 'b' || text[1] == 'B')) { /* Symbol, but no size given (size assumed given on command line) */ + n = sscanf (text, "%c", &symbol_type); + if (p->size_x == 0.0) p->size_x = p->given_size_x; + if (p->size_y == 0.0) p->size_y = p->given_size_y; + p->equal_area = FALSE; + } else if (strchr (bar_symbols[mode], (int) text[0])) { /* Bar, column, cube with size */ /* Bar: -Sb|B[c|i|m|p|u][b] */ @@ -5392,8 +5399,23 @@ case 'W': p->convert_angles = 1; case 'w': - p->symbol = GMT_SYMBOL_PIE; - p->n_required = 2; + switch (text[1]) { + case 'B': /* wind barb */ + case 'b': + p->symbol = GMT_SYMBOL_BARB; + if (text[2]) { + sscanf (&text[2], "%[^/]/%[^/]/%lf/%lf", txt_a, txt_b, &p->b_angle, &p->b_scale); + p->b_width = GMT_convert_units (txt_a, GMT_INCH); + p->b_length = GMT_convert_units (txt_b, GMT_INCH); + } + p->read_barb = TRUE; + p->n_required = 2; + check = FALSE; + break; + default: /* wedge */ + p->symbol = GMT_SYMBOL_PIE; + p->n_required = 2; + } break; case 'r': p->symbol = GMT_SYMBOL_RECT; diff -uNr GMT4.2.1/src/gmt_plot.c GMT4.2.1_barb/src/gmt_plot.c --- GMT4.2.1/src/gmt_plot.c 2007-10-02 11:27:51.000000000 +0900 +++ GMT4.2.1_barb/src/gmt_plot.c 2007-12-11 20:36:48.000000000 +0900 @@ -2662,6 +2662,99 @@ ps_textbox (x, y, size, label, angle, just, outline, dx, dy, rgb); } +void GMT_draw_barb (double x0, double y0, double z0, double theta, double spd, double barbwidth, double barblength, double barbangle, double barbscale, struct GMT_PEN *pen, struct GMT_FILL *fill, BOOLEAN outline) +{ + double w1, dx, dy, y; + double s, c; + int i, ispd, n, n_pennant, n_feather; + struct GMT_CUSTOM_SYMBOL symbol; + struct GMT_CUSTOM_SYMBOL_ITEM bs[256]; + + if (spd == 0.) return; + + /* make struct of custom symbol for barbs */ + strcpy (symbol.name, "barb"); + symbol.first = bs; + + /* spine of barb */ + ispd = (int) (spd / barbscale * 2. + 0.0001); + n_pennant = ispd / 10; + n_feather = (ispd % 10) / 2; + if (ispd % 2) n_feather ++; + w1 = 1./6.; + y = w1 * (n_pennant + n_feather + 1); + if (y < 1.) y = 1.; + + bs[0].x = 0.; + bs[0].y = 0.; + bs[0].action = GMT_ACTION_MOVE; + bs[0].next = bs+1; + + bs[1].x = 0.; + bs[1].y = y; + bs[1].action = GMT_ACTION_DRAW; + bs[1].next = bs+2; + + /* pennants and feathers */ + n = 2; + if (ispd == 1) y -= w1; /* space for 5kt barb */ + + sincos (barbangle * D2R, &s, &c); + dx = s * barbwidth / barblength; + dy = -c * barbwidth / barblength; + + while (ispd > 0) { + bs[n].x = 0.; + bs[n].y = y; + bs[n].action = GMT_ACTION_MOVE; + bs[n].next = bs+n+1; + n ++; + + /* pennants */ + if (ispd >= 10) { + bs[n].x = dx; + bs[n].y = y - w1 + dy; + bs[n].action = GMT_ACTION_DRAW; + bs[n].next = bs+n+1; + n ++; + + y -= w1; + bs[n].x = 0; + bs[n].y = y; + + ispd -= 10; + if (ispd < 10) y -= w1; /* space between pennant and feather */ + } else if (ispd >= 2) { + bs[n].x = dx; + bs[n].y = y + dy; + ispd -= 2; + y -= w1; + } else { /* 5kt feather */ + bs[n].x = dx/2.; + bs[n].y = y + dy/2.; + ispd --; + } + bs[n].action = GMT_ACTION_DRAW; + bs[n].next = bs+n+1; + n ++; + } + + /* rotate */ + sincos (theta * D2R, &s, &c); + + for(i = 0; i < n; i ++) { + y = c * bs[i].x - s * bs[i].y; + bs[i].x = -s * bs[i].x - c * bs[i].y; + bs[i].y = y; + + bs[i].fill = NULL; + bs[i].pen = NULL; + } + bs[n-1].next = NULL; + + GMT_draw_custom_symbol (x0, y0, z0, barblength, &symbol, pen, fill, outline); +} + void GMT_draw_map_scale (struct GMT_MAP_SCALE *ms) { int i, j, jj, k, *rgb, n_a_ticks[9], n_f_ticks[9], unit; diff -uNr GMT4.2.1/src/gmt_plot.h GMT4.2.1_barb/src/gmt_plot.h --- GMT4.2.1/src/gmt_plot.h 2007-05-26 04:39:14.000000000 +0900 +++ GMT4.2.1_barb/src/gmt_plot.h 2007-12-11 20:36:48.000000000 +0900 @@ -51,6 +51,7 @@ #define GMT_SYMBOL_OCTAGON 24 #define GMT_SYMBOL_CUSTOM 25 #define GMT_SYMBOL_ROTATERECT 26 +#define GMT_SYMBOL_BARB 27 #define GMT_SYMBOL_FRONT -100 #define GMT_SYMBOL_QUOTED_LINE -200 @@ -104,12 +105,17 @@ int convert_angles; /* If 2, convert azimuth to angle on map, 1 special case for -JX, 0 plain case */ BOOLEAN read_vector; /* if TRUE must read vector attributes */ + BOOLEAN read_barb; /* if TRUE must read wind barb attributes */ BOOLEAN shrink; /* If TRUE, shrink vector attributes for small lengths */ double v_norm; /* shrink when lengths are smaller than this */ double v_shrink; /* Required scale factor */ double v_width; /* Width of vector stem in inches */ double h_length; /* Length of vector head in inches */ double h_width; /* Width of vector head in inches */ + double b_width; /* Width of wind barb in inches */ + double b_length; /* Length of wind barb in inches */ + double b_angle; /* Angle of wind barb in degree */ + double b_scale; /* Scale of each wind barbs */ int v_just; /* How to justify vector: head point given (3), head (2), center(1), tail (0 - Default) */ BOOLEAN v_double_heads; /* If TRUE, Add 8 (|= 8) to outline to specify double-headed vector (FALSE is single-headed) */ @@ -164,4 +170,5 @@ EXTERN_MSC void GMT_pie (double x, double y, double z, double size[], struct GMT_FILL *fill, BOOLEAN outline); EXTERN_MSC void GMT_rotrect (double x, double y, double z, double size[], struct GMT_FILL *fill, BOOLEAN outline); EXTERN_MSC void GMT_vector (double x0, double y0, double x1, double y1, double z0, double tailwidth, double headlength, double headwidth, double shape, struct GMT_FILL *fill, BOOLEAN outline); +EXTERN_MSC void GMT_draw_barb (double x0, double y0, double z0, double theta, double spd, double barbwidth, double barblength, double barbangle, double barbscale, struct GMT_PEN *pen, struct GMT_FILL *fill, BOOLEAN outline); #endif /* _GMT_PLOT_H */ diff -uNr GMT4.2.1/src/grdbarb.1 GMT4.2.1_barb/src/grdbarb.1 --- GMT4.2.1/src/grdbarb.1 1970-01-01 09:00:00.000000000 +0900 +++ GMT4.2.1_barb/src/grdbarb.1 2007-12-11 18:46:20.000000000 +0900 @@ -0,0 +1,239 @@ +.TH GRDBARB l "11 Dec 2007" "GMT4.2.1" "Generic Mapping Tools" +.SH NAME +grdbarb \- Plot wind barbs from grid files +.SH SYNOPSIS +\fBgrdbarb\fP \fIcompx.grd\fP \fIcompy.grd\fP \fB\-J\fP\fIparameters\fP [ \fB\-A\fP ] +[ \fB\-B\fP\fItickinfo\fP ] [ \fB\-C\fP\fIcptfile\fP ] [ \fB\-E\fP ] +[ \fB\-G\fP\fIfill\fP] [ \fB\-I\fP\fIx_inc\fP[\fBm|c\fP][/\fIy_inc\fP[\fBm|c\fP]] ] [ \fB\-K\fP ] [ \fB\-N\fP ] [ \fB\-O\fP ] [ \fB\-P\fP ] +[ \fB\-Q\fP\fIparameters\fP ] [ \fB\-R\fP\fIwest/east/south/north\fP[\fBr\fP] ] [ \fB\-S\fP[\fBl\fP]\fIscale\fP ] +[ \fB\-T\fP ] [ \fB\-U\fP[\fI/dx/dy/\fP][\fIlabel\fP] ] [ \fB\-V\fP ] [ \fB\-W\fP\fIcontourpen\fP ] [ \fB\-X\fP\fIx-shift\fP ] +[ \fB\-Y\fP\fIy-shift\fP ] [ \fB\-Z\fP ] [ \fB\-c\fP\fIcopies\fP ] +.SH DESCRIPTION +\fBgrdbarb\fP reads two 2-D gridded files which represents the x- and y-components of a vector field and +produces a wind field plot by +drawing barbs with orientation and length according to the information in the files. Alternatively, +polar coordinate components may be used (r, theta). +\fBgrdbarb\fP is basically a short-hand for using 2 calls to \fBgrd2xyz\fP and pasting the output through +\fBpsxy \-SU\fP. +.TP +\fIcompx.grd\fP +Contains the x-component of the vector field. +.TP +\fIcompy.grd\fP +Contains the y-component of the vector field. +.TP +.B \-J +Selects the map projection. Scale is UNIT/degree, 1:xxxxx, or width in UNIT (upper case modifier). +UNIT is cm, inch, or m, depending on the MEASURE_UNIT setting in \.gmtdefaults4, but this can be +overridden on the command line by appending \fBc\fP, \fBi\fP, or \fBm\fP to the scale/width value. +For map height, max dimension, or min dimension, append \fBh\fP, \fB+\fP, or \fB-\fP to the width, +respectively. +.br +.sp +\fBCYLINDRICAL PROJECTIONS:\fP +.br +.sp +\fB\-Jc\fP\fIlon0/lat0/scale\fP (Cassini) +.br +\fB\-Jj\fP\fIlon0/scale\fP (Miller) +.br +\fB\-Jm\fP\fIscale\fP (Mercator - Greenwich and Equator as origin) +.br +\fB\-Jm\fP\fIlon0/lat0/scale\fP (Mercator - Give meridian and standard parallel) +.br +\fB\-Joa\fP\fIlon0/lat0/azimuth/scale\fP (Oblique Mercator - point and azimuth) +.br +\fB\-Job\fP\fIlon0/lat0/lon1/lat1/scale\fP (Oblique Mercator - two points) +.br +\fB\-Joc\fP\fIlon0/lat0/lonp/latp/scale\fP (Oblique Mercator - point and pole) +.br +\fB\-Jq\fP\fIlon0/scale\fP (Equidistant Cylindrical Projection (Plate Carree)) +.br +\fB\-Jt\fP\fIlon0/scale\fP (TM - Transverse Mercator, with Equator as y = 0) +.br +\fB\-Jt\fP\fIlon0/lat0/scale\fP (TM - Transverse Mercator, set origin) +.br +\fB\-Ju\fP\fIzone/scale\fP (UTM - Universal Transverse Mercator) +.br +\fB\-Jy\fP\fIlon0/lats/scale\fP (Basic Cylindrical Projection) +.br +.sp +\fBAZIMUTHAL PROJECTIONS:\fP +.br +.sp +\fB\-Ja\fP\fIlon0/lat0/scale\fP (Lambert). +.br +\fB\-Je\fP\fIlon0/lat0/scale\fP (Equidistant). +.br +\fB\-Jf\fP\fIlon0/lat0/horizon/scale\fP (Gnomonic). +.br +\fB\-Jg\fP\fIlon0/lat0/scale\fP (Orthographic). +.br +\fB\-Jg\fP\fIlon0/lat0/altitude/azimuth/tilt/twist/Width/Height/scale\fP (General Perspective). +.br +\fB\-Js\fP\fIlon0/lat0/\fP[\fIslat/\fP]\fIscale\fP (General Stereographic) +.br +.sp +\fBCONIC PROJECTIONS:\fP +.br +.sp +\fB\-Jb\fP\fIlon0/lat0/lat1/lat2/scale\fP (Albers) +.br +\fB\-Jd\fP\fIlon0/lat0/lat1/lat2/scale\fP (Equidistant) +.br +\fB\-Jl\fP\fIlon0/lat0/lat1/lat2/scale\fP (Lambert) +.br +.sp +\fBMISCELLANEOUS PROJECTIONS:\fP +.br +.sp +\fB\-Jh\fP\fIlon0/scale\fP (Hammer) +.br +\fB\-Ji\fP\fIlon0/scale\fP (Sinusoidal) +.br +\fB\-Jk\fP[\fBf|s\fP]\fIlon0/scale\fP (Eckert IV (f) and VI (s)) +.br +\fB\-Jn\fP\fIlon0/scale\fP (Robinson) +.br +\fB\-Jr\fP\fIlon0/scale\fP (Winkel Tripel) +.br +\fB\-Jv\fP\fIlon0/scale\fP (Van der Grinten) +.br +\fB\-Jw\fP\fIlon0/scale\fP (Mollweide) +.br +.sp +\fBNON-GEOGRAPHICAL PROJECTIONS:\fP +.br +.sp +\fB\-Jp\fP[\fBa\fP]\fIscale\fP[\fI/origin\fP] (polar (theta,r) coordinates, optional \fBa\fP for azimuths and offset theta [0]) +.br +\fB\-Jx\fP\fIx-scale\fP[\fBl|p\fP\fIpow\fP][\fI/y-scale\fP[\fBl|p\fP\fIpow\fP]][\fBd\fP] (Linear, log, and power scaling) +.br +More details can be found in the \fBpsbasemap\fP man pages. +.br +.SH OPTIONS +No space between the option flag and the associated arguments. +.TP +.B \-A +Means grid files have polar (r, theta) components instead of Cartesian (x, y). +.TP +.B \-B +Sets map boundary annotation and tickmark intervals; see the +\fBpsbasemap\fP man page for all the details. +.TP +.B \-C +Use \fIcptfile\fP to assign colors based on vector length. +.TP +.B \-E +Center wind barbs on grid nodes [Default draws from grid node]. +.TP +.B \-G +Sets color or shade for barb interiors [Default is no fill]. +(See SPECIFYING FILL below). +.TP +.B \-I +Only plot barbs at nodes every \fIx_inc, y_inc\fP apart (must be multiples of +original grid spacing). Append \fBm\fP for minutes or \fBc\fP for seconds. [Default plots every node]. +.TP +.B \-K +More \fIPostScript\fP code will be appended later [Default terminates the plot system]. +.TP +.B \-N +Do NOT clip barbs at map boundaries [Default will clip]. +.TP +.B \-O +Selects Overlay plot mode [Default initializes a new plot system]. +.TP +.B \-P +Selects Portrait plotting mode [\fBGMT\fP Default is Landscape, see \fBgmtdefaults\fP to change this]. +.TP +.B \-Q +Select barb plot. Optionally, specify \fIparameters\fP which +are \fIbarbwidth/barblength/barbangle/barbscale\fP [Default is 0.025\fBc\fP/0.051\fBc\fP/120/5 (or 0.1\fBi\fP/0.2\fBi\fP/120/5)]. +.TP +.B \-R +\fIxmin, xmax, ymin,\fP and \fIymax\fP specify the Region of interest. For geographic +regions, these limits correspond to \fIwest, east, south,\fP and \fInorth\fP and you may specify them +in decimal degrees or in [+-]dd:mm[:ss.xxx][W|E|S|N] format. Append \fBr\fP if lower left and upper right +map coordinates are given instead of wesn. The two shorthands \fB\-Rg \-Rd\fP stand for global domain +(0/360 or -180/+180 in longitude respectively, with -90/+90 in latitude). +For calendar time coordinates you may either give relative +time (relative to the selected TIME_EPOCH and in the selected TIME_UNIT; append \fBt\fP to \fB\-JX|x\fP), +or absolute time of the form [\fIdate\fP]\fBT[\fP\fIclock\fP] (append \fBT\fP to \fB\-JX|x\fP). At least one of \fIdate\fP and \fIclock\fP +must be present; the \fBT\fP is always required. The \fIdate\fP string must be of the form [-]yyyy[-mm[-dd]] +(Gregorian calendar) or yyyy[-Www[-d]] (ISO week calendar), while the \fIclock\fP string must be of +the form hh:mm:ss[.xxx]. The use of delimiters and their type and positions must be as indicated +(however, input/output and plotting formats are flexible). +Specify a subset of the grid. +.TP +.B \-T +Means azimuth should be converted to angles based on the selected map projection. +.TP +.B \-U +Draw Unix System time stamp on plot. User may specify where the lower left corner +of the stamp should fall on the page relative to lower left corner of plot. Optionally, +append a label, or \fBc\fP (which will plot the command string.). The \fBGMT\fP parameters +UNIX_TIME and UNIX_TIME_POS can affect the appearance; see the \fBgmtdefaults\fP man +page for details. +.TP +.B \-V +Selects verbose mode, which will send progress reports to stderr [Default runs "silently"]. +.TP +.B \-W +Set pen attributes used for vector outlines [Default: width = 1, color = 0/0/0, texture = solid]. (See SPECIFYING PENS below). +.TP +.B \-X \-Y +Shift origin of plot by (\fIx-shift,y-shift\fP). +Prepend \fBa\fP for absolute coordinates; +the default (\fBr\fP) will reset plot origin. +Give \fBc\fP to center plot using current page size. +.TP +.B \-Z +Means the angles provided are azimuths rather than direction (requires \fB\-A\fP). +.TP +.B \-c +Specifies the number of plot copies. [Default is 1]. +.SS SPECIFYING PENS +.TP +\fIpen\fP +The attributes of lines and symbol outlines as defined by \fIpen\fP is a comma delimetered list of +\fIwidth\fP, \fIcolor\fP and \fItexture\fP, each of which is optional. +\fIwidth\fP can be indicated as a measure (points, centimeters, inches) or as \fBfaint\fP, \fBthin\fP[\fBner\fP|\fBnest\fP], +\fBthick\fP[\fBer\fP|\fBest\fP], \fBfat\fP[\fBter\fP|\fBtest\fP], or \fBobese\fP. +\fIcolor\fP specifies a grey shade or color (see SPECIFYING COLOR below). +\fItexture\fP is a combination of dashes `-' and dots `.'. +.SS SPECIFYING FILL +.TP +\fIfill\fP +The attribute \fIfill\fP specifies the solid shade or solid \fIcolor\fP +(see SPECIFYING COLOR below) or the pattern used for filling polygons. +Patterns are specified as \fBp\fP\fIdpi/pattern\fP, where \fIpattern\fP gives +the number of the built-in pattern (1-90) \fIor\fP the name of a Sun 1-, 8-, +or 24-bit raster file. The \fIdpi\fP sets the resolution of the image. For +1-bit rasters: use \fBP\fP\fIdpi/pattern\fP for inverse video, or append +\fB:F\fP\fIcolor\fP[\fBB\fP[\fIcolor\fP]] to specify fore- and background +colors (use \fIcolor\fP = - for transparency). +See \fBGMT\fP Cookbook & Technical Reference Appendix E for information +on individual patterns. +.SS SPECIFYING COLOR +.TP +\fIcolor\fP +The \fIcolor\fP of lines, areas and patterns can be specified by a valid color name +(from the system's X11/rgb.txt file),\"' +by a grey shade (in the range 0\-255) or by a numerical color code (r/g/b, each in range 0\-255; h-s-v, ranges +0\-360, 0\-1, 0\-1; or c/m/y/k, each in range 0\-100%). + +.SH EXAMPLES +To draw the vector field given by the files r.grd and theta.grd on a linear plot +with scale 5 cm per data unit, +using vector rather than stick plot, and scale vector magnitudes so that 10 units +equal 1 inch, run +.br +.sp +\fBgrdvector\fP r.grd theta.grd \fB\-Jx\fP5\fBc\fP \fB\-A \-Q\fP \fB\-S\fP10\fBi\fP > gradient.ps +.br +.sp +.SH "SEE ALSO" +.IR gmt (l), +.IR grdcontour (l), +.IR psxy (l) diff -uNr GMT4.2.1/src/grdbarb.c GMT4.2.1_barb/src/grdbarb.c --- GMT4.2.1/src/grdbarb.c 1970-01-01 09:00:00.000000000 +0900 +++ GMT4.2.1_barb/src/grdbarb.c 2007-12-11 20:36:48.000000000 +0900 @@ -0,0 +1,412 @@ +/*-------------------------------------------------------------------- + * $Id: grdvector.c,v 1.41 2007/03/24 01:42:07 pwessel Exp $ + * + * Copyright (c) 1991-2007 by P. Wessel and W. H. F. Smith + * See COPYING file for copying and redistribution conditions. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Contact info: gmt.soest.hawaii.edu + *--------------------------------------------------------------------*/ +/* + + grdvector reads 2 grdfiles that contains the 2 components of a vector + field (cartesian or polar) and plots vectors at the grid positions. + This is basically a short-hand for using grd2xyz | psxy -SV and is + more convenient for such plots on a grid. + + Author: Paul Wessel + Date: 12-JUN-1995 + Revised: 15-FEB-2000 + Version: 4 + + grdbarb ( based source code is grdvector.c ) reads 2 grd files that + contains the 2 components of a vector field ( cartesian or polar ) + and plots wind barbs at the grid positions. This is basically a + short-hand for using grd2xyz | psxy -SU and is more convenient for + such plots on a grid. + + Author: KATO Masay + Date: 21-MAY-2006 + Version: 0.6 ( for GMT4.1.2 ) + + */ + + +#include "gmt.h" +#include "pslib.h" + +struct GRDBARB_CTRL { + struct A { /* -A */ + BOOLEAN active; + } A; + struct C { /* -C */ + BOOLEAN active; + char *file; + } C; + struct E { /* -E */ + BOOLEAN active; + } E; + struct G { /* -G */ + BOOLEAN active; + struct GMT_FILL fill; + } G; + struct I { /* -Idx[/dy] */ + BOOLEAN active; + double xinc, yinc; + } I; + struct N { /* -N */ + BOOLEAN active; + } N; + struct Q { /* -Q */ + BOOLEAN active; + double width, length, angle, scale; + } Q; + struct T { /* -T */ + BOOLEAN active; + } T; + struct W { /* -W */ + BOOLEAN active; + struct GMT_PEN pen; + } W; + struct Z { /* -Z */ + BOOLEAN active; + } Z; +}; + +int main (int argc, char **argv) +{ + int i, j, n = 0, nm, nx, ny, ij, i0, j0, di, dj; + + BOOLEAN shrink_properties = FALSE, error = FALSE; + + char *file[2], txt_a[GMT_LONG_TEXT], txt_b[GMT_LONG_TEXT], txt_c[GMT_LONG_TEXT]; + + float *r, *theta; + + double v_w, h_l, h_w, v_shrink = 1.0, tmp, x, y, plot_x, plot_y, x_off, y_off; + double west, east, south, north, x2, y2; + double data_west, data_east, data_south, data_north, value, c, s; + + struct GRD_HEADER h[2]; + struct GRDBARB_CTRL *Ctrl; + + void *New_Grdbarb_Ctrl (), Free_Grdbarb_Ctrl (struct GRDBARB_CTRL *C); + + argc = GMT_begin (argc, argv); + + Ctrl = (struct GRDBARB_CTRL *)New_Grdbarb_Ctrl (); /* Allocate and initialize a new control structure */ + + west = east = south = north = 0.0; + di = dj = 1; + i0 = j0 = 0; + + for (i = 1; i < argc; i++) { + if (argv[i][0] == '-') { + switch (argv[i][1]) { + /* Common parameters */ + + case 'B': + case 'J': + case 'K': + case 'O': + case 'P': + case 'R': + case 'U': + case 'V': + case 'X': + case 'x': + case 'Y': + case 'y': + case 'c': + case '\0': + error += GMT_parse_common_options (argv[i], &west, &east, &south, &north); + break; + + /* Supplemental parameters */ + + case 'A': + Ctrl->A.active = TRUE; + break; + case 'C': /* Vary symbol color with z */ + Ctrl->C.active = TRUE; + Ctrl->C.file = strdup (&argv[i][2]); + break; + case 'E': + Ctrl->E.active = TRUE; + break; + case 'G': /* Set Gray shade for polygon */ + Ctrl->G.active = TRUE; + if (GMT_getfill (&argv[i][2], &Ctrl->G.fill)) { + GMT_fill_syntax ('G', " "); + error++; + } + break; + case 'I': /* Only use gridnodes Ctrl->I.xinc,Ctrl->I.yinc apart */ + Ctrl->I.active = TRUE; + if (GMT_getinc (&argv[i][2], &Ctrl->I.xinc, &Ctrl->I.yinc)) { + GMT_inc_syntax ('I', 1); + error = TRUE; + } + break; + case 'N': /* Do not clip at border */ + Ctrl->N.active = TRUE; + break; + case 'Q': + Ctrl->Q.active = TRUE; + if (argv[i][2]) { + if (sscanf (&argv[i][2], "%[^/]/%[^/]/%lf/%lf", txt_a, txt_b, &Ctrl->Q.angle, &Ctrl->Q.scale) != 4) { + fprintf (stderr, "%s: GMT SYNTAX ERROR -Q option: Could not decode barbwidth/barblength/barbangle/barbscale\n", GMT_program); + error++; + } + else { + Ctrl->Q.width = GMT_convert_units (txt_a, GMT_INCH); + Ctrl->Q.length = GMT_convert_units (txt_b, GMT_INCH); + } + } + break; + case 'T': + Ctrl->T.active = TRUE; + break; + case 'W': /* Set line attributes */ + Ctrl->W.active = TRUE; + if (argv[i][2] && GMT_getpen (&argv[i][2], &Ctrl->W.pen)) { + GMT_pen_syntax ('W', " "); + error++; + } + break; + case 'Z': + Ctrl->Z.active = TRUE; + break; + default: + error = TRUE; + GMT_default_error (argv[i][1]); + break; + } + } + else if (n < 2) + file[n++] = argv[i]; + else + n++; + } + + if (argc == 1 || GMT_give_synopsis_and_exit) { + fprintf (stderr, "grdbarb %s - Plot wind barb fields from grdfiles\n\n", GMT_VERSION); + fprintf (stderr, "usage: grdbarb compx.grd compy.grd %s %s [-A]\n", GMT_J_OPT, GMT_Rgeo_OPT); + fprintf (stderr, "\t[%s] [-C] [-E] [-G] [-I] [-K] [-N] [-O] [-P] [-Q]\n", GMT_B_OPT); + fprintf (stderr, "\t[-T] [%s] [-V] [-W] [%s] [%s] [-Z] [%s]\n\n", GMT_U_OPT, GMT_X_OPT, GMT_Y_OPT, GMT_c_OPT); + + if (GMT_give_synopsis_and_exit) exit (EXIT_FAILURE); + + fprintf (stderr, "\tcompx & compy are grdfiles with the 2 wind components.\n"); + GMT_explain_option ('j'); + fprintf (stderr, "\n\tOPTIONS:\n"); + fprintf (stderr, "\t-A means grdfiles have polar (r, theta) components [Default is Cartesian]\n"); + GMT_explain_option ('b'); + fprintf (stderr, "\t-C Use cpt-file to assign colors based on wind speed\n"); + fprintf (stderr, "\t-E cEnter wind barbs on grid nodes [Default draws from grid node]\n"); + fprintf (stderr, "\t-G Specify color. fill can be either (each 0-255) for color or (0-255) for gray [0].\n"); + fprintf (stderr, "\t Default is no fill (outlines only)\n"); + fprintf (stderr, "\t-I plots only those nodes that are apart [Default is all nodes]\n"); + GMT_explain_option ('K'); + fprintf (stderr, "\t-N Do Not clip wind barbs that exceed the map boundaries [Default will clip]\n"); + GMT_explain_option ('O'); + GMT_explain_option ('P'); + fprintf (stderr, "\t-Q Specify wind barb parameters\n"); + fprintf (stderr, "\t are barbwidth/barblength/barbangle/barbscale [Default is 0.1i/0.2i/120/5]\n"); + GMT_explain_option ('R'); + fprintf (stderr, "\t-T means azimuth should be converted to angles based on map projection\n"); + GMT_explain_option ('U'); + GMT_explain_option ('V'); + fprintf (stderr, "\t-W sets pen attributes [width = %gp, color = (%d/%d/%d), texture = solid line].\n", + Ctrl->W.pen.width, Ctrl->W.pen.rgb[0], Ctrl->W.pen.rgb[1], Ctrl->W.pen.rgb[2]); + GMT_explain_option ('X'); + fprintf (stderr, "\t-Z means the angles provided are azimuths rather than direction\n"); + GMT_explain_option ('c'); + GMT_explain_option ('.'); + exit (EXIT_FAILURE); + } + + if (Ctrl->I.active && (Ctrl->I.xinc <= 0.0 || Ctrl->I.yinc <= 0.0)) { + fprintf (stderr, "%s: GMT SYNTAX ERROR -I option: Must specify positive increments\n", GMT_program); + error++; + } + if (Ctrl->Z.active && !Ctrl->A.active) { + fprintf (stderr, "%s: GMT SYNTAX ERROR -Z option: Azimuths not valid input for Cartesian data\n", GMT_program); + error++; + } + if (Ctrl->C.active && !Ctrl->C.file) { + fprintf (stderr, "%s: GMT SYNTAX ERROR -C option: Must specify a color palette table\n", GMT_program); + error++; + } + if (!(Ctrl->G.active || Ctrl->W.active || Ctrl->C.active)) { + fprintf (stderr, "%s: GMT SYNTAX ERROR: Must specify at least one of -G, -W, -C\n", GMT_program); + error++; + } + if (n != 2) { + fprintf (stderr, "%s: GMT SYNTAX ERROR: Must specify two input grdfiles\n", GMT_program); + error++; + } + + if (error) exit (EXIT_FAILURE); + + if (Ctrl->C.active) GMT_read_cpt (Ctrl->C.file); + + if (!(strcmp (file[0], "=") || strcmp (file[1], "="))) { + fprintf (stderr, "%s: Piping of grdfiles not supported!\n", GMT_program); + exit (EXIT_FAILURE); + } + + GMT_err_fail (GMT_read_grd_info (file[0], &h[0]), file[0]); + GMT_err_fail (GMT_read_grd_info (file[1], &h[1]), file[1]); + + if (!(h[0].nx == h[1].nx && h[0].ny == h[1].ny && h[0].x_min == h[1].x_min && h[0].y_min == h[1].y_min + && h[0].x_inc == h[1].x_inc && h[0].y_inc == h[1].y_inc)) { + fprintf (stderr, "%s: files %s and %s does not match!\n", GMT_program, file[0], file[1]); + exit (EXIT_FAILURE); + } + + /* Determine what wesn to pass to map_setup */ + + if (!project_info.region_supplied) { + west = h[0].x_min; + east = h[0].x_max; + south = h[0].y_min; + north = h[0].y_max; + } + + GMT_err_fail (GMT_map_setup (west, east, south, north), ""); + + /* Determine the wesn to be used to read the grdfile */ + + if (GMT_grd_setregion (&h[0], &data_west, &data_east, &data_south, &data_north)) { /* No grid to plot; just do empty map and exit */ + GMT_plotinit (argc, argv); + GMT_map_basemap (); + GMT_plotend (); + GMT_end (argc, argv); + } + + /* Read data */ + + nx = GMT_get_n (data_west, data_east, h[0].x_inc, h[0].node_offset); + ny = GMT_get_n (data_south, data_north, h[0].y_inc, h[0].node_offset); + nm = nx * ny; + r = (float *) GMT_memory (VNULL, (size_t)nm, sizeof (float), GMT_program); + theta = (float *) GMT_memory (VNULL, (size_t)nm, sizeof (float), GMT_program); + GMT_err_fail (GMT_read_grd (file[0], &h[0], r, data_west, data_east, data_south, data_north, GMT_pad, FALSE), file[0]); + GMT_err_fail (GMT_read_grd (file[1], &h[1], theta, data_west, data_east, data_south, data_north, GMT_pad, FALSE), file[1]); + + GMT_plotinit (argc, argv); + + GMT_setpen (&Ctrl->W.pen); + + if (!Ctrl->N.active) GMT_map_clip_on (GMT_no_rgb, 3); + + if (Ctrl->I.xinc != 0.0 && Ctrl->I.yinc != 0.0) { + struct GRD_HEADER tmp_h; + tmp_h = h[0]; + tmp_h.x_inc = Ctrl->I.xinc; + tmp_h.y_inc = Ctrl->I.yinc; + GMT_RI_prepare (&tmp_h); /* Convert to make sure we have correct increments */ + Ctrl->I.xinc = tmp_h.x_inc; + Ctrl->I.yinc = tmp_h.y_inc; + dj = irint (Ctrl->I.yinc / h[0].y_inc); + di = irint (Ctrl->I.xinc / h[0].x_inc); + tmp = ceil (h[0].y_max / Ctrl->I.yinc) * Ctrl->I.yinc; + if (tmp > h[0].y_max) tmp -= Ctrl->I.yinc; + j0 = irint ((h[0].y_max - tmp) / h[0].y_inc); + tmp = floor (h[0].x_min / Ctrl->I.xinc) * Ctrl->I.xinc; + if (tmp < h[0].x_min) tmp += Ctrl->I.xinc; + i0 = irint ((tmp - h[0].x_min) / h[0].x_inc); + } + + for (j = j0; j < h[1].ny; j += dj) { + y = GMT_j_to_y (j, h[0].y_min, h[0].y_max, h[0].y_inc, h[0].xy_off, h[0].ny); + for (i = i0; i < h[1].nx; i += di) { + + ij = j * h[0].nx + i; + if (GMT_is_fnan (r[ij]) || GMT_is_fnan (theta[ij])) continue; /* Cannot plot NaN-vectors */ + + value = r[ij]; + + if (!Ctrl->A.active) { + value = hypot (theta[ij], r[ij]); + if (value == 0.0) continue; + theta[ij] = (float)(R2D * atan2 (theta[ij], r[ij])); + r[ij] = (float)value; + } + else if (r[ij] < 0.0) { + r[ij] = -r[ij]; + theta[ij] += 180.0; + } + else if (r[ij] == 0.0) continue; + + if (Ctrl->C.active) GMT_get_rgb_from_z (value, Ctrl->G.fill.rgb); + + x = GMT_i_to_x (i, h[0].x_min, h[0].x_max, h[0].x_inc, h[0].xy_off, h[0].nx); + GMT_geo_to_xy (x, y, &plot_x, &plot_y); + + if (Ctrl->T.active) { + if (!Ctrl->Z.active) theta[ij] = (float)90.0 - theta[ij]; + GMT_azim_to_angle (x, y, 0.1, (double)theta[ij], &tmp); + theta[ij] = (float)tmp; + } + + if (Ctrl->E.active) { + sincos (theta[ij] * D2R, &s, &c); + plot_x += 0.5 * Ctrl->Q.length * c; + plot_y += 0.5 * Ctrl->Q.length * s; + } + + if (!Ctrl->Q.active) { + if (Ctrl->C.active) ps_setpaint (Ctrl->G.fill.rgb); + /* ps_segment (plot_x, plot_y, x2, y2); */ + continue; + } + + GMT_draw_barb (plot_x, plot_y, 0., theta[ij], r[ij], Ctrl->Q.width, Ctrl->Q.length, copysign(Ctrl->Q.angle, y), Ctrl->Q.scale, &Ctrl->W.pen, &Ctrl->G.fill, Ctrl->W.active); + } + } + + if (!Ctrl->N.active) GMT_map_clip_off (); + + GMT_map_basemap (); + + GMT_plotend (); + + GMT_free ((void *)r); + GMT_free ((void *)theta); + + Free_Grdbarb_Ctrl (Ctrl); /* Deallocate control structure */ + + GMT_end (argc, argv); + + exit (EXIT_SUCCESS); +} + +void *New_Grdbarb_Ctrl () { /* Allocate and initialize a new control structure */ + struct GRDBARB_CTRL *C; + + C = (struct GRDBARB_CTRL *) GMT_memory (VNULL, 1, sizeof (struct GRDBARB_CTRL), "New_Grdbarb_Ctrl"); + + /* Initialize values whose defaults are not 0/FALSE/NULL */ + GMT_init_fill (&C->G.fill, -1, -1, -1); + GMT_init_pen (&C->W.pen, GMT_PENWIDTH); + C->Q.width = 0.1; + C->Q.length = 0.2; + C->Q.angle = 120.; + C->Q.scale = 5.; + return ((void *)C); +} + +void Free_Grdbarb_Ctrl (struct GRDBARB_CTRL *C) { /* Deallocate control structure */ + if (C->C.file) GMT_free ((void *)C->C.file); + GMT_free ((void *)C); +} diff -uNr GMT4.2.1/src/makefile GMT4.2.1_barb/src/makefile --- GMT4.2.1/src/makefile 2007-10-11 04:28:23.000000000 +0900 +++ GMT4.2.1_barb/src/makefile 2007-12-11 20:36:48.000000000 +0900 @@ -64,7 +64,7 @@ PROGSPS_O = gmt2rgb.o grdcontour.o grdimage.o grdvector.o grdview.o psbasemap.o psclip.o \ pscoast.o pshistogram.o psimage.o pslegend.o psmask.o psrose.o psscale.o pstext.o \ - pscontour.o pswiggle.o psxy.o psxyz.o + pscontour.o pswiggle.o psxy.o psxyz.o grdbarb.o ALLPROGS = GMT $(PROGS) $(PROGSPS) @@ -78,7 +78,7 @@ all: init $(ALLPROGS) init: gmtmacros gmt_notposix.h GMT - + gmtmacros: @if [ ! -s makegmt.macros ]; then \ echo "src/makegmt.macros is empty - you must rerun configure in the main GMT directory"; \ @@ -257,6 +257,7 @@ pswiggle$(EXE): pswiggle.o psxy$(EXE): psxy.o psxyz$(EXE): psxyz.o +grdbarb$(EXE): grdbarb.o sample1d$(EXE): sample1d.o spectrum1d$(EXE): spectrum1d.o splitxyz$(EXE): splitxyz.o diff -uNr GMT4.2.1/src/psxy.1 GMT4.2.1_barb/src/psxy.1 --- GMT4.2.1/src/psxy.1 2007-10-11 05:03:18.000000000 +0900 +++ GMT4.2.1_barb/src/psxy.1 2007-12-11 17:24:17.000000000 +0900 @@ -462,6 +462,12 @@ Same as \fB\-Sw\fP, except azimuths (in degrees east of north) should be given instead of the two directions. The azimuths will be mapped into angles based on the chosen map projection (\fB\-Sw\fP leaves the directions unchanged.) .TP +.B \-Swb +wind barb. Direction (in degrees counter-clockwise from horizontal) and length must be found in columns 3 and 4. \fIsize\fP, +if present, will be interpreted as barbwidth/barblength/barbangle/barbscale [Default is 0.025\fBc\fP/0.051\fBc\fP/120/5 (or 0.1\fBi\fP/0.2\fBi\fP/120/5)]. +.B \-SWB +Same as \fB\-Swb\fP, except azimuth (in degrees east of north) should be given instead of direction. The azimuth will be mapped into an angle based on the chosen map projection (\fB\-Swb\fP leaves the directions unchanged.) +.TP .B \-Sx cross. \fIsize\fP is diameter of circumscribing circle. .TP diff -uNr GMT4.2.1/src/psxy.c GMT4.2.1_barb/src/psxy.c --- GMT4.2.1/src/psxy.c 2007-10-01 05:49:04.000000000 +0900 +++ GMT4.2.1_barb/src/psxy.c 2007-12-11 20:36:48.000000000 +0900 @@ -26,6 +26,9 @@ * Date: 15-SEP-2001 * Version: 4 * + * Date: 13-MAR-2005 + * Modified: KATO Masaya + * */ #include "gmt.h" @@ -115,14 +118,22 @@ memset ((void *)&S, 0, sizeof (struct GMT_SYMBOL)); GMT_contlabel_init (&S.G, 0); + S.read_barb = FALSE; S.v_width = 0.03; S.h_length = 0.12; S.h_width = 0.1; S.font_no = gmtdefs.annot_font[0]; + S.b_width = 0.1; + S.b_length = 0.2; + S.b_angle = 120.; + S.b_scale = 5.; + if ((S.u = gmtdefs.measure_unit) == GMT_CM) { S.v_width = 0.075 / 2.54; S.h_length = 0.3 / 2.54; S.h_width = 0.25 / 2.54; Ctrl->E.size = 0.25 / 2.54; + S.b_width = 0.25 / 2.54; + S.b_length = 0.50 / 2.54; } /* Check and interpret the command line arguments */ @@ -299,6 +310,7 @@ fprintf (stderr, "\t -(xdash), st(a)r, (b|B)ar, (c)ircle, (d)iamond, (e)llipse, (f)ront, octa(g)on, (h)exagon, (i)nvtriangle,\n"); fprintf (stderr, "\t (j)rotated rectangle, (k)ustom, (l)etter, pe(n)tagon, (p)oint, (q)uoted line, (r)ect, (s)quare,\n"); fprintf (stderr, "\t (t)riangle, (v)ector, (w)edge, (x)cross, (y)dash\n"); + fprintf (stderr, "\t (wb) wind barb\n"); fprintf (stderr, "\t If no size is specified, psxy expects the 3rd column to have sizes.\n"); fprintf (stderr, "\t If no symbol is specified, psxy expects the last column to have symbol code.\n"); fprintf (stderr, "\t [Note: if -C is selected then 3rd means 4th column, etc.]\n"); @@ -342,6 +354,10 @@ fprintf (stderr, "\t Upper case H, B, T, S will give double-headed vector [Default is t]\n"); fprintf (stderr, "\t Wedges: the start and stop directions of pie wedge must be in input columns 3, 4.\n"); fprintf (stderr, "\t If -SW rather than -Sw is selected, psxy will expect two azimuths instead.\n"); + fprintf (stderr, "\t Wind barbs: the direction and length must be in input columns 3 and 4.\n"); + fprintf (stderr, "\t Furthermore, means barbwidth/barblength/barbangle/barbscale [Default is %g/%g/%g/%g]\n", S.b_width, S.b_length, S.b_angle, S.b_scale); + fprintf (stderr, "\t If -SWB rather than -Swb is selected, psxy will expect azimuth and length\n"); + fprintf (stderr, "\t and convert azimuths based on the chosen map projection\n"); GMT_explain_option ('U'); GMT_explain_option ('V'); GMT_pen_syntax ('W', "sets pen attributes:"); @@ -364,8 +380,8 @@ error++; } if (S.symbol > 0 && Ctrl->C.active) get_rgb = TRUE; /* Need to read z-vales from input data file */ - if (Ctrl->E.active && (S.read_vector || S.symbol == GMT_SYMBOL_ELLIPSE || S.symbol == GMT_SYMBOL_FRONT || S.symbol == GMT_SYMBOL_QUOTED_LINE || S.symbol == GMT_SYMBOL_ROTATERECT)) { - fprintf (stderr, "%s: GMT SYNTAX ERROR -E option: Incompatible with -Se, -Sf, -Sj, -Sq, -Sv\n", GMT_program); + if (Ctrl->E.active && (S.read_vector || S.read_barb || S.symbol == GMT_SYMBOL_ELLIPSE || S.symbol == GMT_SYMBOL_FRONT || S.symbol == GMT_SYMBOL_QUOTED_LINE || S.symbol == GMT_SYMBOL_ROTATERECT)) { + fprintf (stderr, "%s: GMT SYNTAX ERROR -E option: Incompatible with -Se, -Sf, -Sj, -Sq, -Sv, -Swb\n", GMT_program); error++; } if (Ctrl->C.active && S.symbol == 0 && !GMT_io.multi_segments[GMT_IN]) { @@ -655,6 +671,10 @@ x_len = in[two+S.read_size]; y_len = in[three+S.read_size]; } + else if (S.read_barb){ + direction = in[two]; + length = in[three]; + } /* Skip zero-size symbols */ @@ -667,6 +687,10 @@ if (gmtdefs.verbose) fprintf (stderr, "%s: Warning: Vector length <= 0.0 near line %d (skipped)\n", GMT_program, n_total_read); continue; } + if (S.read_barb && length <= 0.0) { + if (gmtdefs.verbose) fprintf (stderr, "%s: Warning: Vector length <= 0.0 near line %d (skipped)\n", GMT_program, n_total_read); + continue; + } if (S.symbol == GMT_SYMBOL_ELLIPSE && (major <= 0.0 || minor <= 0.0)) { if (gmtdefs.verbose) fprintf (stderr, "%s: Warning: Ellipse axes <= 0.0 near line %d (skipped)\n", GMT_program, n_total_read); continue; @@ -905,6 +929,15 @@ dim[0] = x_len; dim[1] = y_len; GMT_rect (plot_x - 0.5*x_len, plot_y - 0.5*y_len, 0.0, dim, ¤t_fill, outline_active); break; + case GMT_SYMBOL_BARB: + if (S.convert_angles == 2) { + GMT_azim_to_angle (in[0], in[1], 0.1, direction, &tmp); + direction = tmp; + } + else if (S.convert_angles == 1) /* Cartesian azimuth */ + direction = 90.0 - direction; + GMT_draw_barb (plot_x, plot_y, 0., direction, length, S.b_width, S.b_length, copysign(S.b_angle, in[1]), S.b_scale, &Ctrl->W.pen, &Ctrl->G.fill, Ctrl->W.active); + break; case GMT_SYMBOL_CUSTOM: GMT_draw_custom_symbol (plot_x, plot_y, 0.0, S.size_x, S.custom, ¤t_pen, ¤t_fill, outline_active); break; diff -uNr GMT4.2.1/src/psxyz.1 GMT4.2.1_barb/src/psxyz.1 --- GMT4.2.1/src/psxyz.1 2007-10-11 05:03:18.000000000 +0900 +++ GMT4.2.1_barb/src/psxyz.1 2007-12-11 17:23:28.000000000 +0900 @@ -455,6 +455,12 @@ Same as \fB\-Sw\fP, except azimuths (in degrees east of north) should be given instead of the two directions. The azimuths will be mapped into angles based on the chosen map projection (\fB\-Sw\fP leaves the directions unchanged.) .TP +.B \-Swb +wind barb. Direction (in degrees counter-clockwise from horizontal) and length must be found in columns 3 and 4. \fIsize\fP, +if present, will be interpreted as barbwidth/barblength/barbangle/barbscale [Default is 0.025\fBc\fP/0.051\fBc\fP/120/5 (or 0.1\fBi\fP/0.2\fBi\fP/120/5)]. +.B \-SWB +Same as \fB\-Swb\fP, except azimuth (in degrees east of north) should be given instead of direction. The azimuth will be mapped into an angle based on the chosen map projection (\fB\-Swb\fP leaves the directions unchanged.) +.TP .B \-Sx (\fBx\fP)cross. \fIsize\fP is diameter of circumscribing circle. .br diff -uNr GMT4.2.1/src/psxyz.c GMT4.2.1_barb/src/psxyz.c --- GMT4.2.1/src/psxyz.c 2007-10-01 05:49:05.000000000 +0900 +++ GMT4.2.1_barb/src/psxyz.c 2007-12-11 20:36:48.000000000 +0900 @@ -139,12 +139,19 @@ S.h_length = 0.12; S.h_width = 0.1; S.base = GMT_d_NaN; + + S.b_width = 0.1; + S.b_length = 0.2; + S.b_angle = 120.; + S.b_scale = 5.; lux[0] = lux[1] = lux[2] = 0.0; /* Default is no shading */ if ((S.u = gmtdefs.measure_unit) == GMT_CM) { S.v_width = 0.075 / 2.54; S.h_length = 0.3 / 2.54; S.h_width = 0.25 / 2.54; + S.b_width = 0.25 / 2.54; + S.b_length = 0.50 / 2.54; } /* Check and interpret the command line arguments */ @@ -266,6 +273,7 @@ fprintf (stderr, "\t -(xdash), st(a)r, (b|B)ar, (c)ircle, (d)iamond, (e)llipse, (f)ront, octa(g)on, (h)exagon\n"); fprintf (stderr, "\t (i)nvtriangle, (j)rotated rectangle, (k)ustom, (%c)etter, pe(n)tagon, c(o)lumn, (p)oint, (q)uoted line,\n", 'l'); fprintf (stderr, "\t (r)ect, (s)quare, (t)riangle, c(u)be, (v)ector, (w)edge, (x)cross, (y)dash, (z)dash\n"); + fprintf (stderr, "\t (wb) wind barb\n"); fprintf (stderr, "\t If no size is specified, psxyz expects the 4th column to have sizes.\n"); fprintf (stderr, "\t If no symbol is specified, psxyz expects the last column to have symbol code.\n"); fprintf (stderr, "\t [Note: if -C is selected then 4th means 5th column, etc.]\n"); @@ -311,6 +319,10 @@ GMT_explain_option ('U'); fprintf (stderr, "\t Wedges: the start and stop directions of pie wedge must be in input columns 4 and 5.\n"); fprintf (stderr, "\t If -SW rather than -Sw is selected, psxy will expect two azimuths instead.\n"); + fprintf (stderr, "\t Wind barbs: the direction and length must be in input columns 3 and 4.\n"); + fprintf (stderr, "\t Furthermore, means barbwidth/barblength/barbangle/barbscale [Default is %g/%g/%g/%g]\n", S.b_width, S.b_length, S.b_angle, S.b_scale); + fprintf (stderr, "\t If -SWB rather than -Swb is selected, psxyz will expect azimuth and length\n"); + fprintf (stderr, "\t and convert azimuths based on the chosen map projection\n"); GMT_explain_option ('V'); GMT_pen_syntax ('W', "sets pen attributes:"); fprintf (stderr, "\t Implicitly draws symbol outline with this pen.\n"); @@ -530,6 +542,11 @@ data1[n].flag = S.convert_angles; /* Azim vs Dir. */ if (data1[n].y_size < S.v_norm) data1[n].flag |= 8; /* Flag to shrink vector attributes */ } + else if (S.read_barb){ + data1[n].x_size = (float)in[three]; /* direction */ + data1[n].y_size = (float)in[four]; /* length */ + data1[n].flag = S.convert_angles; /* Azim vs Dir. */ + } else if (S.symbol == GMT_SYMBOL_ELLIPSE) { data1[n].x_size = (float)in[three]; /* direction */ data1[n].y_size = (float)in[four]; /* major */ @@ -587,7 +604,7 @@ if (gmtdefs.verbose) fprintf (stderr, "%s: Warning: Symbol size <= 0.0 near line %d (skipped)\n", GMT_program, n_total_read); continue; } - if (S.read_vector && S.v_just < 3 && data1[n].y_size <= 0.0) { + if ( ( S.read_vector || S.read_barb ) && S.v_just < 3 && data1[n].y_size <= 0.0) { if (gmtdefs.verbose) fprintf (stderr, "%s: Warning: vector length <= 0.0 near line %d (skipped)\n", GMT_program, n_total_read); continue; } @@ -864,6 +881,16 @@ GMT_vector (data1[i].x, data1[i].y, x2, y2, data1[i].z, S.v_width, S.h_length, S.h_width, gmtdefs.vector_shape, &data1[i].f, this_outline); } break; + case GMT_SYMBOL_BARB: + if (data1[i].flag & 2) { + GMT_azim_to_angle (data1[i].lon, data1[i].lat, 0.1, data1[i].x_size, &tmp); + data1[i].x_size = (float)tmp; + } + else if (data1[i].flag & 1) { + data1[i].x_size = (float)(90.0 - data1[i].x_size); + } + GMT_draw_barb (data1[i].x, data1[i].y, data1[i].z, data1[i].x_size, data1[i].y_size, S.b_width, S.b_length, copysign(S.b_angle, data1[i].lat), S.b_scale, &Ctrl->W.pen, &Ctrl->G.fill, Ctrl->W.active); + break; case GMT_SYMBOL_PIE: if (S.convert_angles == 2) { GMT_azim_to_angle (data1[i].lon, data1[i].lat, 0.1, (double)(R2D*data1[i].y_size), &tmp);