home *** CD-ROM | disk | FTP | other *** search
- /*--------------------------------------------------------------------
- * The GMT-system: @(#)grdvector.c 3.15 23 Jul 1995
- *
- * Copyright (c) 1991-1995 by P. Wessel and W. H. F. Smith
- * See README file for copying and redistribution conditions.
- *--------------------------------------------------------------------*/
- /*
- 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.
-
-
- */
-
-
- #include "gmt.h"
-
- float *r, *theta;
-
- main (argc, argv)
- int argc;
- char **argv; {
-
- int i, j, n = 0, nm, nx, ny, ij, i0, j0, di, dj, dummy[4];
-
- BOOLEAN convert_angles = FALSE, get_rgb = FALSE, cartesian = TRUE, shrink = FALSE, set_fill = FALSE;
- BOOLEAN error = FALSE, center = FALSE, outline = FALSE, azimuth = FALSE, stick_plot = TRUE, inc_set = FALSE;
- BOOLEAN clip = TRUE;
-
- char *file[2], *cpt;
-
- double dx2, dy2, v_width = 0.03, h_length = 0.12, h_width = 0.1;
- double v_w, h_l, h_w, v_shrink, v_norm = 0.0, tmp, x, y, plot_x, plot_y, x_off, y_off;
- double west, east, south, north, off, dir, length, x2, y2, scale = 1.0;
- double data_west, data_east, data_south, data_north, value;
-
- struct GRD_HEADER h[2];
- struct FILL fill;
- struct PEN pen;
-
- gmt_init_pen (&pen, 1);
- gmt_init_fill (&fill, -1, -1, -1);
- west = east = south = north = 0.0;
- dummy[0] = dummy[1] = dummy[2] = dummy[3] = 0;
- di = dj = 1;
- i0 = j0 = 0;
- dx2 = dy2 = 0.0;
-
- argc = gmt_begin (argc, argv);
-
- 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 += get_common_args (argv[i], &west, &east, &south, &north);
- break;
-
- /* Supplemental parameters */
-
- case 'A':
- cartesian = FALSE;
- break;
- case 'C': /* Vary symbol color with z */
- cpt = &argv[i][2];
- get_rgb = TRUE;
- break;
- case 'E':
- center = TRUE;
- break;
- case 'F':
- if (gmt_getrgb (&argv[i][2], &gmtdefs.basemap_frame_rgb[0], &gmtdefs.basemap_frame_rgb[1], &gmtdefs.basemap_frame_rgb[2])) {
- gmt_pen_syntax ('F');
- error++;
- }
- break;
- case 'G': /* Set Gray shade for polygon */
- if (gmt_getfill (&argv[i][2], &fill)) {
- gmt_fill_syntax ('G');
- error++;
- }
- set_fill = TRUE;
- break;
- case 'I': /* Only use gridnodes dx2,dy2 apart */
- gmt_getinc (&argv[i][2], &dx2, &dy2);
- inc_set = TRUE;
- break;
- case 'N': /* Do not clip at border */
- clip = FALSE;
- break;
- case 'Q':
- if (argv[i][2] && argv[i][3] != 'n') {
- if (sscanf (&argv[i][2], "%lf/%lf/%lf", &v_width, &h_length, &h_width) != 3) {
- fprintf (stderr, "%s: GMT SYNTAX ERROR -Q option: Could not decode arrowwidth/headlength/headwidth\n", gmt_program);
- error++;
- }
- }
- for (j = 2; argv[i][j] && argv[i][j] != 'n'; j++);
- if (argv[i][j]) { /* Normalize option used */
- v_norm = atof (&argv[i][j+1]);
- if (v_norm > 0.0) {
- v_shrink = 1.0 / v_norm;
- shrink = TRUE;
- }
- else {
- fprintf (stderr, "%s: GMT SYNTAX ERROR -Qn option: No reference length given\n", gmt_program);
- error++;
- }
- }
- stick_plot = FALSE;
- break;
- case 'S':
- scale = atof (&argv[i][2]);
- break;
- case 'T':
- convert_angles = TRUE;
- break;
- case 'W': /* Set line attributes */
- if (argv[i][2] && gmt_getpen (&argv[i][2], &pen)) {
- gmt_pen_syntax ('W');
- error++;
- }
- outline = TRUE;
- break;
- case 'Z':
- azimuth = 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_quick) {
- fprintf (stderr, "grdvector %s - Plot vector fields from grdfiles\n\n", GMT_VERSION);
- fprintf (stderr, "usage: grdvector compx.grd compy.grd -J<params> -R<west/east/south/north> [-A]\n");
- fprintf (stderr, "\t[-B<tickinfo>] [-C<cpt>] [-E] [-F<r/g/b>] [-G<fill>] [-K] [-O] [-P] [-Q<params>] [-N] [-S<scale>] [-T]\n");
- fprintf (stderr, "\t[-U[<label>]] [-V] [-W<pen>] [-X<x_shift>] [-Y<y_shift>] [-Z] [-c<ncopies>] [-:]\n\n");
-
- if (gmt_quick) exit (-1);
-
- fprintf (stderr, "\tcompx & compy are grdfiles with the 2 vector components.\n");
- explain_option ('j');
- fprintf (stderr, "\n\tOPTIONS:\n");
- fprintf (stderr, "\t-A means grdfiles have polar (r, theta) components [Default is Cartesian]\n");
- explain_option ('b');
- fprintf (stderr, " -C Use cpt-file to assign colors based on vector length\n");
- fprintf (stderr, " -E cEnter vectors on grid nodes [Default draws from grid node]\n");
- fprintf (stderr, " -F Set color used for Frame and anotation [%d/%d/%d]\n",
- gmtdefs.basemap_frame_rgb[0], gmtdefs.basemap_frame_rgb[1], gmtdefs.basemap_frame_rgb[2]);
- fprintf (stderr, " -G Specify color. fill can be either <r/g/b> (each 0-255) for color or (0-255) for gray [0].\n");
- fprintf (stderr, " Default is no fill (vector outlines only)\n");
- explain_option ('K');
- fprintf (stderr, " -N Do Not clip vectors that exceed the map boundaries [Default will clip]\n");
- explain_option ('O');
- explain_option ('P');
- fprintf (stderr, " -Q Select vector plot [Default is stick-plot].\n");
- fprintf (stderr, " Optionally, specify vector parameters\n");
- fprintf (stderr, " <params> are arrowwidth/headlength/headwidth [Default is 0.03/0.12/0.09]\n");
- fprintf (stderr, " Append n<size> which will cause vectors shorter than <size> to be\n");
- fprintf (stderr, " scaled down\n");
- explain_option ('R');
- fprintf (stderr, " -S sets scale for vector length in units per inch [1]\n");
- fprintf (stderr, " -T means aximuth should be convered to angles based on map projection\n");
- explain_option ('U');
- explain_option ('V');
- fprintf (stderr, " -W sets pen attributes [width = %d, color = (%d/%d/%d), texture = solid line].\n",
- pen.width, pen.r, pen.g, pen.b);
- explain_option ('X');
- fprintf (stderr, " -Z means the angles provided are azimuths rahter than direction\n");
- explain_option ('c');
- explain_option ('.');
- exit (-1);
- }
-
- if (inc_set && (dx2 <= 0.0 || dy2 <= 0.0)) {
- fprintf (stderr, "%s: GMT SYNTAX ERROR -I option: Must specify positive increments\n", gmt_program);
- error++;
- }
- if (scale == 0.0) {
- fprintf (stderr, "%s: GMT SYNTAX ERROR -S option: Scale must be nonzero\n", gmt_program);
- error++;
- }
- if (azimuth && cartesian) {
- fprintf (stderr, "%s: GMT SYNTAX ERROR -Z option: Azimuths not valid input for Cartesian data\n", gmt_program);
- error++;
- }
- if (get_rgb && !cpt) {
- fprintf (stderr, "%s: GMT SYNTAX ERROR -C option: Must specify a color palette table\n", gmt_program);
- error++;
- }
- if (!(set_fill || outline)) {
- fprintf (stderr, "%s: GMT SYNTAX ERROR: Must specify at least one of -G, -W\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 (-1);
-
- if (get_rgb) read_cpt (cpt);
-
- if (!(strcmp (file[0], "=") || strcmp (file[1], "="))) {
- fprintf (stderr, "grdvector: Piping of grdfiles not supported!\n");
- exit (-1);
- }
-
- if (read_grd_info (file[0], &h[0])) {
- fprintf (stderr, "grdvector: Error opening file %s\n", file[0]);
- exit (-1);
- }
-
- if (read_grd_info (file[1], &h[1])) {
- fprintf (stderr, "grdvector: Error opening file %s\n", file[1]);
- exit (-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, "grdvector: files %s and %s does not match!\n", file[0], file[1]);
- exit (-1);
- }
- off = (h[0].node_offset) ? 0 : 1;
-
- /* Determine what wesn to pass to map_setup */
-
- if (west == east && south == north) {
- west = h[0].x_min;
- east = h[0].x_max;
- south = h[0].y_min;
- north = h[0].y_max;
- }
-
- map_setup (west, east, south, north);
-
- /* Determine the wesn to be used to read the grdfile */
-
- grd_setregion (&h[0], &data_west, &data_east, &data_south, &data_north);
-
- /* Read data */
-
- nx = rint ( (data_east - data_west) / h[0].x_inc) + off;
- ny = rint ( (data_north - data_south) / h[0].y_inc) + off;
- nm = nx * ny;
- r = (float *) memory (CNULL, nm, sizeof (float), "grdvector");
- theta = (float *) memory (CNULL, nm, sizeof (float), "grdvector");
- if (read_grd (file[0], &h[0], r, data_west, data_east, data_south, data_north, dummy, FALSE)) {
- fprintf (stderr, "grdvector: Error reading file %s\n", file[0]);
- exit (-1);
- }
- if (read_grd (file[1], &h[1], theta, data_west, data_east, data_south, data_north, dummy, FALSE)) {
- fprintf (stderr, "grdvector: Error reading file %s\n", file[1]);
- exit (-1);
- }
- scale = 1.0 / scale;
-
- ps_plotinit (CNULL, gmtdefs.overlay, gmtdefs.page_orientation, gmtdefs.x_origin, gmtdefs.y_origin,
- gmtdefs.global_x_scale, gmtdefs.global_y_scale, gmtdefs.n_copies,
- gmtdefs.dpi, gmtdefs.measure_unit, gmtdefs.paper_width, gmtdefs.page_rgb, gmt_epsinfo (argv[0]));
- echo_command (argc, argv);
- if (gmtdefs.unix_time) timestamp (argc, argv);
-
- ps_setline (pen.width);
- if (pen.texture) ps_setdash (pen.texture, pen.offset);
- ps_setpaint (pen.r, pen.g, pen.b);
-
- if (clip) map_clip_on (-1, -1, -1, 3);
-
- if (dx2 != 0.0 && dy2 != 0.0) {
- dj = rint (dy2 / h[0].y_inc);
- di = rint (dx2 / h[0].x_inc);
- tmp = ceil (h[0].y_max / dy2) * dy2;
- if (tmp > h[0].y_max) tmp -= dy2;
- j0 = rint ((h[0].y_max - tmp) / h[0].y_inc);
- tmp = floor (h[0].x_min / dx2) * dx2;
- if (tmp < h[0].x_min) tmp += dx2;
- i0 = rint ((tmp - h[0].x_min) / h[0].x_inc);
- }
-
- for (j = j0; j < h[1].ny; j += dj) {
- y = h[0].y_max - j *h[0].y_inc;
- for (i = i0; i < h[1].nx; i += di) {
-
- ij = j * h[0].nx + i;
- value = r[ij];
-
- if (cartesian) {
- length = hypot (theta[ij], r[ij]);
- if (length == 0.0) continue;
- dir = R2D * atan2 (theta[ij], r[ij]);
- if (r[ij] < 0) dir += M_PI;
- value = copysign (length, r[ij]);
- r[ij] = length;
- theta[ij] = dir;
- }
- else if (r[ij] < 0.0) {
- r[ij] = -r[ij];
- theta[ij] += M_PI;
- }
- else if (r[ij] == 0.0) continue;
-
- if (get_rgb) get_rgb24 (value, &fill.r, &fill.g, &fill.b);
-
- x = h[0].x_min + i * h[0].x_inc;
- geo_to_xy (x, y, &plot_x, &plot_y);
-
- if (convert_angles) {
- if (!azimuth) theta[ij] = 90.0 - theta[ij];
- azim_2_angle (x, y, 0.1, (double)theta[ij], &tmp);
- theta[ij] = tmp * D2R;
- }
- else
- theta[ij] *= D2R;
-
- r[ij] *= scale;
-
- x2 = plot_x + r[ij] * cos (theta[ij]);
- y2 = plot_y + r[ij] * sin (theta[ij]);
-
- if (center) {
- x_off = 0.5 * (x2 - plot_x);
- y_off = 0.5 * (y2 - plot_y);
- plot_x -= x_off;
- plot_y -= y_off;
- x2 -= x_off;
- y2 -= y_off;
- }
-
- if (stick_plot) {
- if (get_rgb) ps_setpaint (fill.r, fill.g, fill.b);
- ps_plot (plot_x, plot_y, 3);
- ps_plot (x2, y2, 2);
- continue;
- }
-
- if (shrink && r[ij] < v_norm) { /* Scale arrow attributes down with length */
- v_w = v_width * r[ij] * v_shrink;
- h_l = h_length * r[ij] * v_shrink;
- h_w = h_width * r[ij] * v_shrink;
- ps_vector (plot_x, plot_y, x2, y2, v_w, h_l, h_w, gmtdefs.vector_shape, fill.r, fill.g, fill.b, outline);
- }
- else /* Leave as specified */
- ps_vector (plot_x, plot_y, x2, y2, v_width, h_length, h_width, gmtdefs.vector_shape, fill.r, fill.g, fill.b, outline);
- }
- }
-
- if (pen.texture) ps_setdash (CNULL, 0);
-
- if (clip) map_clip_off ();
-
- if (frame_info.plot) {
- ps_setpaint (gmtdefs.basemap_frame_rgb[0], gmtdefs.basemap_frame_rgb[1], gmtdefs.basemap_frame_rgb[2]);
- map_basemap ();
- ps_setpaint (gmtdefs.background_rgb[0], gmtdefs.background_rgb[1], gmtdefs.background_rgb[2]);
- }
- ps_plotend (gmtdefs.last_page);
-
- free ((char *)r);
- free ((char *)theta);
-
- gmt_end (argc, argv);
- }
-