diff -uNr GMT4.1.4/src/GMT.in GMT4.1.4_barb/src/GMT.in --- GMT4.1.4/src/GMT.in 2006-11-03 02:01:48.000000000 +0900 +++ GMT4.1.4_barb/src/GMT.in 2007-05-21 07:19:12.000000000 +0900 @@ -71,6 +71,7 @@ gmtselect Extract data subsets based on spatial criteria grd2cpt Make a color palette table from a grdfile grd2xyz Conversion from 2-D gridded file to table data + grdbarb Plot wind barbs from grdfiles grdblend Blend several partially over-lapping grdfiles onto one grid grdclip Limit the z-range in gridded data grdcontour Contouring of 2-D gridded data diff -uNr GMT4.1.4/src/Makefile GMT4.1.4_barb/src/Makefile --- GMT4.1.4/src/Makefile 2006-11-02 01:41:02.000000000 +0900 +++ GMT4.1.4_barb/src/Makefile 2007-05-21 07:19:12.000000000 +0900 @@ -88,7 +88,7 @@ PROGSPS_C = gmt2rgb.c grdcontour.c grdimage.c grdvector.c grdview.c psbasemap.c psclip.c \ pscoast.c pshistogram.c psimage.c pslegend.c psmask.c psrose.c psscale.c pstext.c pscontour.c \ - pswiggle.c psxy.c psxyz.c + pswiggle.c psxy.c psxyz.c grdbarb.c first: all diff -uNr GMT4.1.4/src/gmt_init.c GMT4.1.4_barb/src/gmt_init.c --- GMT4.1.4/src/gmt_init.c 2006-11-03 04:42:41.000000000 +0900 +++ GMT4.1.4_barb/src/gmt_init.c 2007-05-21 07:19:12.000000000 +0900 @@ -5112,8 +5112,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.1.4/src/gmt_plot.c GMT4.1.4_barb/src/gmt_plot.c --- GMT4.1.4/src/gmt_plot.c 2006-10-31 01:17:36.000000000 +0900 +++ GMT4.1.4_barb/src/gmt_plot.c 2007-05-21 07:19:12.000000000 +0900 @@ -2678,6 +2678,99 @@ ps_vector (x0, y0, x1, y1, tailwidth, headlength, headwidth, gmtdefs.vector_shape, rgb, outline); } +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.1.4/src/gmt_plot.h GMT4.1.4_barb/src/gmt_plot.h --- GMT4.1.4/src/gmt_plot.h 2006-10-31 01:17:36.000000000 +0900 +++ GMT4.1.4_barb/src/gmt_plot.h 2007-05-21 07:19:12.000000000 +0900 @@ -50,6 +50,7 @@ #define GMT_SYMBOL_OCTAGON 23 #define GMT_SYMBOL_CUSTOM 24 #define GMT_SYMBOL_ROTATERECT 25 +#define GMT_SYMBOL_BARB 26 #define GMT_SYMBOL_FRONT -100 #define GMT_SYMBOL_QUOTED_LINE -200 @@ -101,12 +102,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) */ @@ -155,6 +161,7 @@ EXTERN_MSC void GMT_timestamp (double x, double y, char *U_label); EXTERN_MSC void GMT_triangle3D (double x, double y, double z, double size, int rgb[], int outline); EXTERN_MSC void GMT_vector3D (double x0, double y0, double x1, double y1, double z0, double tailwidth, double headlength, double headwidth, double shape, int rgb[], 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); EXTERN_MSC void GMT_vertical_axis (int mode); EXTERN_MSC void GMT_xy_axis (double x0, double y0, double length, double val0, double val1, struct GMT_PLOT_AXIS *A, int below, int annotate); EXTERN_MSC struct EPS *GMT_epsinfo (char *program); diff -uNr GMT4.1.4/src/grdbarb.c GMT4.1.4_barb/src/grdbarb.c --- GMT4.1.4/src/grdbarb.c 1970-01-01 09:00:00.000000000 +0900 +++ GMT4.1.4_barb/src/grdbarb.c 2007-05-21 07:19:12.000000000 +0900 @@ -0,0 +1,427 @@ +/*-------------------------------------------------------------------- + * $Id: grdvector.c,v 1.32 2006/04/13 08:34:41 pwessel Exp $ + * + * Copyright (c) 1991-2006 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); + + GMT_put_history (argc, argv); /* Update .gmtcommands4 */ + + 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); + } + + if (GMT_read_grd_info (file[0], &h[0])) { + fprintf (stderr, "%s: Error opening file %s\n", GMT_program, file[0]); + exit (EXIT_FAILURE); + } + + if (GMT_read_grd_info (file[1], &h[1])) { + fprintf (stderr, "%s: Error opening file %s\n", GMT_program, file[1]); + exit (EXIT_FAILURE); + } + + 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_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); + if (GMT_read_grd (file[0], &h[0], r, data_west, data_east, data_south, data_north, GMT_pad, FALSE)) { + fprintf (stderr, "%s: Error reading file %s\n", GMT_program, file[0]); + exit (EXIT_FAILURE); + } + if (GMT_read_grd (file[1], &h[1], theta, data_west, data_east, data_south, data_north, GMT_pad, FALSE)) { + fprintf (stderr, "%s: Error reading file %s\n", GMT_program, file[1]); + exit (EXIT_FAILURE); + } + + 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_rgb24 (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.1.4/src/psxy.c GMT4.1.4_barb/src/psxy.c --- GMT4.1.4/src/psxy.c 2006-10-31 01:17:38.000000000 +0900 +++ GMT4.1.4_barb/src/psxy.c 2007-05-21 07:19:54.000000000 +0900 @@ -26,6 +26,9 @@ * Date: 15-SEP-2001 * Version: 4 * + * Date: 13-MAR-2005 + * Modified: KATO Masaya + * */ #include "gmt.h" @@ -112,14 +115,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 */ @@ -273,6 +284,7 @@ fprintf (stderr, "\t -(xdash), st(a)r, (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"); @@ -315,6 +327,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"); @@ -336,8 +352,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->G.fill.use_pattern && !(S.symbol == GMT_SYMBOL_LINE || S.symbol == GMT_SYMBOL_CUSTOM)) { /* fill-pattern only for polygons */ @@ -626,6 +642,10 @@ x_len = 0.5 * in[two+S.read_size]; y_len = 0.5 * in[three+S.read_size]; } + else if (S.read_barb){ + direction = in[two]; + length = in[three]; + } /* Skip zero-size symbols */ @@ -638,6 +658,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; @@ -838,6 +862,15 @@ case GMT_SYMBOL_RECT: ps_rect (plot_x - x_len, plot_y - y_len, plot_x + x_len, plot_y + y_len, Ctrl->G.fill.rgb, Ctrl->W.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, &Ctrl->W.pen, &Ctrl->G.fill, Ctrl->W.active); break; diff -uNr GMT4.1.4/src/psxyz.c GMT4.1.4_barb/src/psxyz.c --- GMT4.1.4/src/psxyz.c 2006-10-31 01:17:38.000000000 +0900 +++ GMT4.1.4_barb/src/psxyz.c 2007-05-21 07:22:39.000000000 +0900 @@ -136,12 +136,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 */ @@ -260,6 +267,7 @@ fprintf (stderr, "\t -(xdash), st(a)r, (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"); @@ -304,6 +312,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"); @@ -541,6 +553,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 */ @@ -598,7 +615,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; } @@ -832,6 +849,16 @@ GMT_vector3D (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.rgb, 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);