/*-------------------------------------------------------------------- * $Id: grdcontour.c,v 1.3.4.4 2002/02/27 17:58:55 pwessel Exp $ * * Copyright (c) 1991-2002 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 *--------------------------------------------------------------------*/ /* * grdcontour reads a 2-D grd file and contours it. This algoritm handles * cases where the old contourm failed, e.g. when a contour line passes * exactly through a data point. This is achieved by adding a tiny * number to those data points that would have a contour line going * through them. This is cheating, but the human eye cannot tell the * difference, so who cares? * A multitude of options exist and are explained in the usage message. * The 2-D grd file format is outlined in the routines read_grd/write_grd. * * Author: Paul Wessel * Date: 6-JAN-1991 * Version: 2.0 Based on old v1.x by Paul Wessel & Walter Smith * Revised: 21-JUL-1998 for GMT 3.1 * Revised: 03-MAR-1999 for GMT 3.2 * Revised: 25-FEB-2000 for GMT 3.3.4 * Revised: 25-JUN-2000 for GMT 3.3.5 * Version: 3.4 Added Kaj Jancke's modification for transparent label boxes * Version: 3.4.1 * */ #include "gmt.h" #define MIN_LENGTH 0.01 float *grd; int *edge; double *x, *y; /* Arrays holding the contour xy values */ struct LABEL { double x, y; double angle; char label[32]; struct LABEL *next_label, *prev_label; } *anchor, *old_label; struct SAVE { double *x, *y; double cval; int n; struct GMT_PEN pen; BOOLEAN do_it, high; } *save; void dump_contour (double *xx, double *yy, int nn, double cval, int id, BOOLEAN interior, char *file); void draw_contour (double *xx, double *yy, int nn, double cval, char ctype, double cangle, int closed, double gap, int half_width, char *unit, int box, int label_font_size); void sort_and_plot_ticks (struct SAVE *save, int n, struct GRD_HEADER *h, float *grd, double tick_gap, double tick_length, BOOLEAN tick_low, BOOLEAN tick_high, BOOLEAN tick_label, char *labels); void plot_labels (int size, int box, int rgb[]); int int_cont_count = 0, ext_cont_count = 0; main (int argc, char **argv) { int i, j, k, n, nm, c, n_edges, label_font_size = 9, b_rgb[3], n_alloc; int section, n_contours, smooth_factor = 0, side, id, box = 1, bad; int off, nx, ny, half = 5, n_save = 0, got, ncut = 0, rgb[3]; BOOLEAN error = FALSE, first = TRUE, dump = FALSE, anot = FALSE, interior, begin; BOOLEAN fix_angle = FALSE, do_ticks = FALSE, add_unit = FALSE, use_cpt_colors = FALSE, use_cpt_anot = TRUE; BOOLEAN tick_high = FALSE, tick_low = FALSE, cpt_given = FALSE, tick_label = FALSE; char *grdfile = 0, dfile[BUFSIZ], line[BUFSIZ], *cont_type, *cont_do_tick; char *cpt_file, *labels, c_unit[32], txt_a[32], txt_b[32]; double c_int = 0.0, c_low, c_high, take_out, aval, a_int = 0.0, tick_gap = 0.2; double anot_dist = 4.0, west = 0.0, east = 0.0, south = 0.0, north = 0.0, tick_length = 0.04; double *contour, cval, mult = 1.0, shift = 0.0, min, max, small, label_angle = 0.0; double small_x, small_y, data_west, data_east, data_south, data_north, tmp, *cont_angle; FILE *fpc = NULL; struct GRD_HEADER header; struct GMT_PEN pen[2]; argc = GMT_begin (argc, argv); GMT_init_pen (&pen[0], GMT_PENWIDTH); GMT_init_pen (&pen[1], 3.0 * GMT_PENWIDTH); c_low = -DBL_MAX; c_high = DBL_MAX; dfile[0] = c_unit[0] = 0; if (gmtdefs.measure_unit == GMT_CM) { anot_dist = 10.0 / 2.54; tick_gap = 0.5 / 2.54; tick_length = 0.1 / 2.54; } for (i = 0; i < 3; i++) b_rgb[i] = gmtdefs.page_rgb[i]; /* Default box color is page color */ 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_get_common_args (argv[i], &west, &east, &south, &north); break; /* Supplemental parameters */ case 'b': error += GMT_io_selection (&argv[i][2]); break; case 'A': if (argv[i][2] == '-') use_cpt_anot = FALSE; n = sscanf (&argv[i][2], "%lf", &a_int); for (j = 2, bad = 0; argv[i][j] && argv[i][j] != 'f'; j++); if (argv[i][j]) { /* Found font size option */ label_font_size = atoi (&argv[i][j+1]); if (label_font_size <= 0) bad++; } for (j = 2; argv[i][j] && argv[i][j] != 'a'; j++); if (argv[i][j]) { /* Found fixed angle option */ label_angle = atof (&argv[i][j+1]); fix_angle = TRUE; if (label_angle <= -90.0 || label_angle > 180.0) bad++; } for (j = 2; argv[i][j] && argv[i][j] != '/'; j++); if (argv[i][j] && GMT_getrgb (&argv[i][j+1], b_rgb)) bad++; anot = TRUE; if (strchr (argv[i], 'o')) box = 2; if (strchr (argv[i], 't')) box = 0; if (bad) { fprintf (stderr, "%s: GMT SYNTAX ERROR -A option. Correct syntax:\n", GMT_program); fprintf (stderr, "\t-A[-][aint][f][a][/][o]\n"); error += bad; } break; case 'C': if ((fpc = fopen (&argv[i][2], "r")) == NULL) c_int = atof (&argv[i][2]); else { c_int = 1.0; cpt_given = (int) strstr (&argv[i][2], ".cpt"); cpt_file = &argv[i][2]; } break; case 'D': dump = TRUE; strcpy (dfile, &argv[i][2]); break; case 'E': sscanf (&argv[i][2], "%lf/%lf", &z_project.view_azimuth, &z_project.view_elevation); break; case 'G': sscanf (&argv[i][2], "%[^/]/%d", txt_a, &half); anot_dist = GMT_convert_units (txt_a, GMT_INCH); half /= 2; break; case 'L': sscanf (&argv[i][2], "%lf/%lf", &c_low, &c_high); break; case 'M': /* with -D, create one multiple line segments */ GMT_multisegment (&argv[i][2]); GMT_io.multi_segments = 2; break; case 'N': add_unit = TRUE; if (argv[i][2]) strcpy (c_unit, &argv[i][2]); break; case 'S': smooth_factor = atoi (&argv[i][2]); break; case 'Q': ncut = atoi (&argv[i][2]); break; case 'T': do_ticks = TRUE; if (argv[i][2]) { if (argv[i][2] == '+') tick_high = TRUE, j = 1; else if (argv[i][2] == '-') tick_low = TRUE, j = 1; else tick_high = tick_low = TRUE, j = 0; if (argv[i][2+j] != ':') { n = sscanf (&argv[i][2+j], "%[^/]/%s", txt_a, txt_b); if (n == 2) { tick_gap = GMT_convert_units (txt_a, GMT_INCH); tick_length = GMT_convert_units (txt_b, GMT_INCH); } } for (j = 2; argv[i][j] && argv[i][j] != ':'; j++); if (argv[i][j]) { j++; tick_label = TRUE; labels = &argv[i][j]; } if (n == 1 || tick_gap <= 0.0 || tick_length == 0.0) { fprintf (stderr, "%s: GMT SYNTAX ERROR -T option. Correct syntax:\n", GMT_program); fprintf (stderr, "\t-T[+|-][[c|i|m|p]/[c|i|m|p]][:LH], must be > 0\n"); error = TRUE; } } else tick_high = tick_low = TRUE; /* Do default */ break; case 'W': k = 2; if (argv[i][k] == '+') use_cpt_colors = TRUE, k++; j = (argv[i][k] == 'a' || argv[i][k] == 'c') ? k+1 : k; if (j == k) { /* Set both */ if (GMT_getpen (&argv[i][j], &pen[0])) { GMT_pen_syntax ('W'); error++; } else pen[1] = pen[0]; } else { id = (argv[i][k] == 'a') ? 1 : 0; if (GMT_getpen (&argv[i][j], &pen[id])) { GMT_pen_syntax ('W'); error++; } } break; case 'Z': if (argv[i][2] && argv[i][2] != 'p') n = sscanf (&argv[i][2], "%lf/%lf", &mult, &shift); GMT_z_periodic = (argv[i][strlen(argv[i])-1] == 'p'); /* Phase data */ break; default: error++; GMT_default_error (argv[i][1]); break; } } else grdfile = argv[i]; } if (argc == 1 || GMT_quick) { fprintf (stderr,"grdcontour %s - Contouring of 2-D gridded data sets\n\n", GMT_VERSION); fprintf (stderr, "usage: grdcontour -C -J [-A[-][][f][/r/g/b][a][o]]\n"); fprintf (stderr, "\t[-B] [-D] [-Eaz/el] [-G[c|i|m|p]/] [-K] [-L]\n"); fprintf (stderr, "\t[-M[]] [-N[unit]] [-O] [-P] [-Q] [-R] [-S] [-T[+|-][[c|i|m|p]/[c|i|m|p]][:LH]] [-U[