home *** CD-ROM | disk | FTP | other *** search
- /*--------------------------------------------------------------------
- * The GMT-system: @(#)grdmask.c 2.21 4/28/95
- *
- * Copyright (c) 1991-1995 by P. Wessel and W. H. F. Smith
- * See README file for copying and redistribution conditions.
- *--------------------------------------------------------------------*/
- /*
- * grdmask defines a grid based on region and xinc/yinc values,
- * reads xy polygon files, and sets the grid nodes inside, on the
- * boundary, and outside of the polygons to the user-defined values
- * <in>, <on>, and <out>. These may be any number, including NaN.
- *
- * Author: Walter. H. F. Smith
- * Date: 23-May-1991-1995
- * Version: 2.0
- */
-
- #include "gmt.h"
-
- float *data;
-
- main (argc, argv)
- int argc;
- char **argv;
- {
-
- int i, j, ij, nm, n_path, ix, iy, side, fno, n_files = 0, n_alloc = GMT_CHUNK, n_args;
- int one_or_zero, dummy[4];
-
- BOOLEAN error = FALSE, done, nofile = TRUE, multi_segments = FALSE, pixel = FALSE;
-
- double *x, *y, xx, yy, xmin, xmax, ymin, ymax, xy[2], out_edge_in[3];
- double xinc2, yinc2;
-
- char *maskfile = CNULL, line[512], *ptr, *more, EOL_flag = '>';
-
- FILE *fp;
-
- struct GRD_HEADER header;
-
- argc = gmt_begin (argc, argv);
-
- grd_init (&header, argc, argv, FALSE);
-
- out_edge_in[2] = 1.0; /* Default inside value */
- out_edge_in[0] = out_edge_in[1] = 0.0; /* Default outside and edge value */
- dummy[0] = dummy[1] = dummy[2] = dummy[3] = 0;
-
- /* Check command line arguments */
-
- for (i = 1; i < argc; i++) {
- if (argv[i][0] == '-') {
- switch (argv[i][1]) {
-
- /* Common parameters */
-
- case 'R':
- case 'V':
- case ':':
- case '\0':
- error += get_common_args (argv[i], &header.x_min, &header.x_max, &header.y_min, &header.y_max);
- break;
-
- /* Supplemental parameters */
-
- case 'N':
- strcpy (line, &argv[i][2]);
- ptr = strtok (line, "/");
- for (j = 0; j < 3; j++) {
- out_edge_in[j] = (ptr[0] == 'N' || ptr[0] == 'n') ? gmt_NaN : atof (ptr);
- ptr = strtok (CNULL, "/");
- }
- break;
- case 'F':
- pixel = TRUE;
- break;
- case 'G':
- maskfile = &argv[i][2];
- break;
- case 'I':
- gmt_getinc (&argv[i][2], &header.x_inc, &header.y_inc);
- break;
- case 'M':
- multi_segments = TRUE;
- if (argv[i][2]) EOL_flag = argv[i][2];
- break;
- default:
- error = TRUE;
- gmt_default_error (argv[i][1]);
- break;
- }
- }
- else
- n_files++;
- }
-
- if (argc == 1 || gmt_quick) {
- fprintf (stderr, "grdmask %s - Create mask grdfile from polygons\n\n", GMT_VERSION);
- fprintf (stderr, "usage: grdmask [<pathfiles>] -G<mask_grd_file> -I<xinc[m|c]>[/<yinc>[m|c]]\n");
- fprintf (stderr, "\t-R<west/east/south/north> [-F] [-N<out>/<edge>/<in>] [-M[<flag>]] [-V] [-:]\n\n");
-
- if (gmt_quick) exit (-1);
-
- fprintf (stderr, "\tpathfiles is one or more polygon files\n");
- fprintf (stderr, "\t-G Specify file name for output mask grd file.\n");
- fprintf (stderr, "\t-I sets Increment of the grid; enter xinc, optionally xinc/yinc.\n");
- fprintf (stderr, "\t Default is yinc = xinc. Append an m [or c] to indicate minutes [or seconds].\n");
- explain_option ('R');
- fprintf (stderr, "\n\tOPTIONS:\n");
- fprintf (stderr, "\t-F Force pixel registration for output grid [Default is gridline orientation]\n");
- fprintf (stderr, "\t-M Input files each consist of multiple segments separated by one record\n");
- fprintf (stderr, "\t whose first character is <flag> [>].\n");
- fprintf (stderr, "\t-N sets values to use if point is outside, on the path, or inside.\n");
- fprintf (stderr, "\t NaN is a valid entry. Default values are 0/0/1.\n");
- explain_option ('V');
- explain_option (':');
- exit(-1);
- }
-
- if (!project_info.region_supplied) {
- fprintf (stderr, "%s: GMT SYNTAX ERROR: Must specify -R option\n", gmt_program);
- error++;
- }
- if (header.x_inc <= 0.0 || header.y_inc <= 0.0) {
- fprintf (stderr, "%s: GMT SYNTAX ERROR -I option. Must specify positive increment(s)\n", gmt_program);
- error = TRUE;
- }
- if (!maskfile) {
- fprintf (stderr, "%s: GMT SYNTAX ERROR -G: Must specify output file\n", gmt_program);
- error = TRUE;
- }
-
- if (error) exit (-1);
-
- one_or_zero = (pixel) ? 0 : 1;
- header.nx = rint((header.x_max - header.x_min) / header.x_inc) + one_or_zero;
- header.ny = rint((header.y_max - header.y_min) / header.y_inc) + one_or_zero;
- header.node_offset = pixel;
- xinc2 = 0.5 * header.x_inc;
- yinc2 = 0.5 * header.y_inc;
- nm = header.nx * header.ny;
- data = (float *) memory (CNULL, nm, sizeof(float), "grdmask");
- x = (double *) memory (CNULL, n_alloc, sizeof(double), "grdmask");
- y = (double *) memory (CNULL, n_alloc, sizeof(double), "grdmask");
-
- if (gmtdefs.verbose) {
- fprintf (stderr, "grdmask: Nodes completely outside the polygons will be set to ");
- (bad_float (out_edge_in[0])) ? fprintf (stderr, "NaN\n") : fprintf (stderr, "%lg\n", out_edge_in[0]);
- fprintf (stderr, "grdmask: Nodes completely inside the polygons will be set to ");
- (bad_float (out_edge_in[2])) ? fprintf (stderr, "NaN\n") : fprintf (stderr, "%lg\n", out_edge_in[2]);
- fprintf (stderr, "grdmask: Nodes on the polygons boundary will be set to ");
- (bad_float (out_edge_in[1])) ? fprintf (stderr, "NaN\n") : fprintf (stderr, "%lg\n", out_edge_in[1]);
- }
-
- /* Initialize all nodes to the 'outside' value */
-
- for (ij = 0; ij < nm; ij++) data[ij] = out_edge_in[0];
-
- ix = (gmtdefs.xy_toggle) ? 1 : 0; iy = 1 - ix; /* Set up which columns have x and y */
-
- if (n_files > 0)
- nofile = FALSE;
- else
- n_files = 1;
- n_args = (argc > 1) ? argc : 2;
-
- done = FALSE;
-
- for (fno = 1; !done && fno < n_args; fno++) { /* Loop over all input files */
- if (!nofile && argv[fno][0] == '-') continue;
- if (nofile) {
- fp = stdin;
- done = TRUE;
- }
- else if ((fp = fopen (argv[fno], "r")) == NULL) {
- fprintf (stderr, "grdmask: Cannot open file %s\n", argv[fno]);
- continue;
- }
-
- if (!nofile && gmtdefs.verbose) fprintf (stderr, "grdmask: Working on file %s\n", argv[fno]);
-
- if (gmtdefs.io_header) for (i = 0; i < gmtdefs.n_header_recs; i++) fgets (line, 512, fp);
-
- more = fgets (line, 512, fp);
- while (more) {
- n_path = 0;
- xmin = ymin = 1.0e+100;
- xmax = ymax = -1.0e+100;
-
- while ((more && !multi_segments) || (more && multi_segments && line[0] != EOL_flag)) {
-
- sscanf(line, "%lf %lf", &xy[ix], &xy[iy]);
- x[n_path] = xy[0];
- y[n_path] = xy[1];
-
- if (x[n_path] > xmax) xmax = x[n_path];
- if (x[n_path] < xmin) xmin = x[n_path];
- if (y[n_path] > ymax) ymax = y[n_path];
- if (y[n_path] < ymin) ymin = y[n_path];
- n_path++;
-
- if (n_path == (n_alloc-1)) { /* n_alloc-1 since we may need 1 more to close polygon */
- n_alloc += GMT_CHUNK;
- x = (double *) memory ((char *)x, n_alloc, sizeof(double), "grdmask");
- y = (double *) memory ((char *)y, n_alloc, sizeof(double), "grdmask");
- }
- more = fgets (line, 512, fp);
- }
-
- if (x[n_path-1] != x[0] || y[n_path-1] != y[0]) {
- x[n_path] = x[0];
- y[n_path] = y[0];
- n_path++;
- }
-
- for (j = 0; j < header.ny; j++) {
-
- yy = header.y_max - j * header.y_inc;
- if (pixel) yy -= yinc2;
- if (yy < ymin || yy > ymax) continue; /* Point outside, no need to assign value */
-
- for (i = 0; i < header.nx; i++) {
- xx = header.x_min + i * header.x_inc;
- if (pixel) xx += xinc2;
- if (xx < xmin || xx > xmax) continue; /* Point outside, no need to assign value */
-
- if ((side = non_zero_winding(xx, yy, x, y, n_path)) == 0) continue; /* Outside */
-
- /* Here, point is inside or on edge, we must assign value */
-
- data[j*header.nx+i] = out_edge_in[side];
- }
- #ifdef DEBUG
- fprintf (stderr, "j = %d\r", j);
- #endif
- }
- if (more) more = fgets (line, 512, fp);
- }
-
- if (fp != stdin) fclose (fp);
- }
-
- if (write_grd (maskfile, &header, data, 0.0, 0.0, 0.0, 0.0, dummy, FALSE)) {
- fprintf (stderr, "grdmask: Error writing file %s\n", maskfile);
- exit (-1);
- }
-
- free ((char *)data);
- free ((char *)x);
- free ((char *)y);
-
- gmt_end (argc, argv);
- }
-