home *** CD-ROM | disk | FTP | other *** search
- /*--------------------------------------------------------------------
- * The GMT-system: @(#)grdlandmask.c 3.14 07 Aug 1995
- *
- * Copyright (c) 1991-1995 by P. Wessel and W. H. F. Smith
- * See README file for copying and redistribution conditions.
- *--------------------------------------------------------------------*/
- /*
- * grdlandmask defines a grid based on region and xinc/yinc values,
- * reads a shoreline data base, 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: P. Wessel
- * Date: 23-Sep-1994
- * Version: 3.0
- */
-
- #include "gmt.h"
- #include "gmt_shore.h" /* Defines shore structures */
-
- char *shore_resolution[5] = {"full", "high", "intermediate", "low", "crude"};
-
- struct SHORE c;
-
- float *data;
-
- main (argc, argv)
- int argc;
- char **argv;
- {
-
- int i, j, k, ij, bin, ind, nm, np, side, i_min, i_max, j_min, j_max, nx1, ny1;
- int one_or_zero, base = 3, direction, inside = 1, max_level = MAX_LEVEL, dummy[4];
-
- BOOLEAN error = FALSE, pixel = FALSE, dry_wet_only = FALSE, greenwich = FALSE, got_fh[2];
- BOOLEAN temp_shift = FALSE;
-
- double *x, *y, xmin, xmax, ymin, ymax, out_edge_in[5];
- double xinc2, yinc2, min_area = 0.0, i_dx, i_dy, edge = 0.0, del_off;
-
- char *maskfile = CNULL, res = 'l', line[80], *ptr;
-
- struct GRD_HEADER header;
- struct POL *p;
-
- argc = gmt_begin (argc, argv);
-
- grd_init (&header, argc, argv, FALSE);
-
- memset ((char *)out_edge_in, 0, 5 * sizeof (double)); /* Default "wet" value = 0 */
- out_edge_in[1] = out_edge_in[3] = 1.0; /* Default "dry" value = 1 */
-
- /* 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 'A':
- j = sscanf (&argv[i][2], "%lf/%d", &min_area, &max_level);
- if (j == 1) max_level = MAX_LEVEL;
- break;
- case 'D':
- res = argv[i][2];
- switch (res) {
- case 'f':
- base = 0;
- break;
- case 'h':
- base = 1;
- break;
- case 'i':
- base = 2;
- break;
- case 'l':
- base = 3;
- break;
- case 'c':
- base = 4;
- break;
- default:
- fprintf (stderr, "%s: GMT SYNTAX ERROR -D option: Unknown modifier %c\n", gmt_program, argv[i][2]);
- break;
- }
- break;
- case 'N':
- strcpy (line, &argv[i][2]);
- if (line[strlen(line)-1] == 'o') { /* Edge is considered outside */
- inside = 2;
- line[strlen(line)-1] = 0;
- }
- ptr = strtok (line, "/");
- j = 0;
- while (j < 5 && ptr) {
- out_edge_in[j] = (ptr[0] == 'N' || ptr[0] == 'n') ? gmt_NaN : atof (ptr);
- ptr = strtok (CNULL, "/");
- j++;
- }
- if (!(j == 2 || j == 5)) {
- fprintf (stderr, "%s: GMT SYNTAX ERROR -N option: Specify 2 or 5 arguments\n", gmt_program);
- exit (-1);
- }
- dry_wet_only = (j == 2);
- 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;
- default:
- error = TRUE;
- gmt_default_error (argv[i][1]);
- break;
- }
- }
- }
-
- find_resolutions (got_fh); /* Check to see if full &| high resolution coastlines are installed */
-
- if (argc == 1 || gmt_quick) {
- fprintf (stderr, "grdlandmask %s - Create \"wet-dry\" mask grdfile from shoreline data base\n\n", GMT_VERSION);
- fprintf (stderr, "usage: grdlandmask -G<mask_grd_file> -I<xinc[m|c]>[/<yinc>[m|c]] -R<west/east/south/north>\n");
- fprintf (stderr, "\t[-A<min_area>[/<max_level>]] [-D<resolution>] [-F] [-N<maskvalues>[o]] [-V]\n\n");
-
- if (gmt_quick) exit (-1);
-
- 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-A features smaller than <min_area> (in km^2) or of higher level (0-4) than <max_level>\n");
- fprintf (stderr, "\t will be skipped [0/4] (see pscoast for details)]\n");
- fprintf (stderr, " -D Choose one of the following resolutions:\n");
- if (got_fh[0]) fprintf (stderr, " f - full resolution (may be very slow for large regions)\n");
- if (got_fh[1]) fprintf (stderr, " h - high resolution (may be slow for large regions)\n");
- fprintf (stderr, " i - intermediate resolution\n");
- fprintf (stderr, " l - low resolution [Default]\n");
- fprintf (stderr, " c - crude resolution, for tasks that need crude continent outlines only\n");
- fprintf (stderr, "\t-F Force pixel registration for output grid [Default is gridline orientation]\n");
- fprintf (stderr, "\t-N gives values to use if a node is outside or inside a feature.\n");
- fprintf (stderr, "\t Append o to let feature boundary be considered outside [Default is inside].\n");
- fprintf (stderr, "\t Specify this information using 1 of 2 formats:\n");
- fprintf (stderr, "\t -N<wet>/<dry>.\n");
- fprintf (stderr, "\t -N<ocean>/<land>/<lake>/<island>/<pond>.\n");
- fprintf (stderr, "\t NaN is a valid entry. Default values are 0/1/0/1/0 (i.e., 0/1)\n");
- explain_option ('V');
- 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);
-
- if (header.x_min < 0.0 && header.x_max < 0.0) { /* Shift longitudes */
- temp_shift = TRUE;
- header.x_min += 360.0;
- header.x_max += 360.0;
- }
-
- if (dry_wet_only) {
- out_edge_in[3] = out_edge_in[5] = out_edge_in[7] = out_edge_in[1];
- out_edge_in[4] = out_edge_in[8] = out_edge_in[0];
- out_edge_in[6] = out_edge_in[2];
- }
-
- if (gmt_init_shore (res, &c, header.x_min, header.x_max, header.y_min, header.y_max)) {
- fprintf (stderr, "grdlandmask: %s resolution shoreline data base not installed\n", shore_resolution[base]);
- exit (-1);
- }
-
- if (gmtdefs.verbose && dry_wet_only) {
- fprintf (stderr, "grdlandmask: Nodes in water will be set to ");
- (bad_float (out_edge_in[0])) ? fprintf (stderr, "NaN\n") : fprintf (stderr, "%lg\n", out_edge_in[0]);
- fprintf (stderr, "grdlandmask: Nodes on land will be set to ");
- (bad_float (out_edge_in[1])) ? fprintf (stderr, "NaN\n") : fprintf (stderr, "%lg\n", out_edge_in[1]);
- }
- else if (gmtdefs.verbose && !dry_wet_only) {
- fprintf (stderr, "grdlandmask: Nodes in the oceans will be set to ");
- (bad_float (out_edge_in[0])) ? fprintf (stderr, "NaN\n") : fprintf (stderr, "%lg\n", out_edge_in[0]);
- fprintf (stderr, "grdlandmask: Nodes on land will be set to ");
- (bad_float (out_edge_in[1])) ? fprintf (stderr, "NaN\n") : fprintf (stderr, "%lg\n", out_edge_in[1]);
- fprintf (stderr, "grdlandmask: Nodes in lakes will be set to ");
- (bad_float (out_edge_in[2])) ? fprintf (stderr, "NaN\n") : fprintf (stderr, "%lg\n", out_edge_in[2]);
- fprintf (stderr, "grdlandmask: Nodes in islands will be set to ");
- (bad_float (out_edge_in[3])) ? fprintf (stderr, "NaN\n") : fprintf (stderr, "%lg\n", out_edge_in[3]);
- fprintf (stderr, "grdlandmask: Nodes in ponds will be set to ");
- (bad_float (out_edge_in[4])) ? fprintf (stderr, "NaN\n") : fprintf (stderr, "%lg\n", out_edge_in[4]);
- }
-
- i_dx = 1.0 / header.x_inc;
- i_dy = 1.0 / header.y_inc;
- one_or_zero = (pixel) ? 0 : 1;
- del_off = (pixel) ? 0.0 : 0.5;
- header.nx = rint((header.x_max - header.x_min) * i_dx) + one_or_zero;
- header.ny = rint((header.y_max - header.y_min) * i_dy) + one_or_zero;
- header.node_offset = pixel;
- xinc2 = (header.node_offset) ? 0.5 * header.x_inc : 0.0;
- yinc2 = (header.node_offset) ? 0.5 * header.y_inc : 0.0;
- nm = header.nx * header.ny;
- data = (float *) memory (CNULL, nm, sizeof(float), "grdlandmask");
- x = (double *) memory (CNULL, header.nx, sizeof(double), "grdlandmask");
- y = (double *) memory (CNULL, header.ny, sizeof(double), "grdlandmask");
- for (i = 0; i < header.nx; i++) x[i] = header.x_min + i * header.x_inc + xinc2;
- for (j = 0; j < header.ny; j++) y[j] = header.y_max - j * header.y_inc - yinc2;
- nx1 = header.nx - 1; ny1 = header.ny - 1;
-
- if (header.x_min < 0.0 && header.x_max > 0.0) { /* Must shift longitudes */
- greenwich = TRUE;
- edge = header.x_min;
- }
-
- map_getproject ("x1d"); /* Fake linear projection */
- map_setup (header.x_min, header.x_max, header.y_min, header.y_max);
-
- for (ind = 0; ind < c.nb; ind++) { /* Loop over necessary bins only */
-
- bin = c.bins[ind];
- if (gmtdefs.verbose) fprintf (stderr, "grdlandmask: Working on block # %5d\r", bin);
-
- gmt_get_shore_bin (ind, &c, min_area, max_level);
-
- if (c.ns == 0) { /* Initialize all nodes to lowest node level */
-
- k = MIN (MIN (c.node_level[0], c.node_level[1]) , MIN (c.node_level[2], c.node_level[3]));
- i_min = MAX (0, floor (fmod (c.lon_sw - header.x_min + 360.0, 360.0) * i_dx) + del_off);
- if (i_min > nx1) i_min = 0;
- i_max = MIN (nx1, ceil (fmod (c.lon_sw + c.bsize - header.x_min + 360.0, 360.0) * i_dx) + del_off);
- if (i_max <= 0) i_max = nx1;
- j_min = MAX (0, floor ((header.y_max - c.lat_sw - c.bsize) * i_dy) - del_off);
- j_max = MIN (ny1, ceil ((header.y_max - c.lat_sw) * i_dy) - del_off);
- for (j = j_min; j <= j_max; j++) for (i = i_min, ij = j * header.nx + i_min; i <= i_max; i++, ij++)
- data[ij] = k;
-
- continue; /* No polygon, done with bin */
- }
-
- /* Must use polygons. Go in both directions to cover both land and sea */
-
- for (direction = -1; direction < 2; direction += 2) {
-
- np = gmt_assemble_shore (&c, direction, TRUE, greenwich, edge, &p);
-
- for (k = 0; k < np; k++) {
-
- /* Find min/max of polygon */
-
- if (greenwich && p[k].lon[0] < edge) p[k].lon[0] += 360.0;
- xmin = xmax = p[k].lon[0];
- ymin = ymax = p[k].lat[0];
- for (i = 1; i < p[k].n; i++) {
- if (greenwich && p[k].lon[i] < edge) p[k].lon[i] += 360.0;
- if (p[k].lon[i] < xmin) xmin = p[k].lon[i];
- if (p[k].lon[i] > xmax) xmax = p[k].lon[i];
- if (p[k].lat[i] < ymin) ymin = p[k].lat[i];
- if (p[k].lat[i] > ymax) ymax = p[k].lat[i];
- }
- i_min = MAX (0, floor (fmod (xmin - header.x_min + 360.0, 360.0) * i_dx) + del_off);
- if (i_min > nx1) i_min = 0;
- i_max = MIN (nx1, ceil (fmod (xmax - header.x_min + 360.0, 360.0) * i_dx) + del_off);
- if (i_max <= 0) i_max = nx1;
- j_min = MAX (0, floor ((header.y_max - ymax) * i_dy) - del_off);
- j_max = MIN (ny1, ceil ((header.y_max - ymin) * i_dy) - del_off);
-
- for (j = j_min; j <= j_max; j++) {
- for (i = i_min; i <= i_max; i++) {
-
- if ((side = non_zero_winding (x[i], y[j], p[k].lon, p[k].lat, p[k].n)) < inside) continue; /* Outside */
-
- /* Here, point is inside, we must assign value */
-
- ij = j * header.nx + i;
- if (p[k].level > data[ij]) data[ij] = p[k].level;
- }
- }
- }
-
- free_polygons (p, np);
- free ((char *)p);
- }
-
- free_shore (&c);
- }
-
- shore_cleanup (&c);
-
- for (ij = 0; ij < nm; ij++) {
- k = rint (data[ij]);
- data[ij] = out_edge_in[k];
- }
-
- if (temp_shift) {
- header.x_min -= 360.0;
- header.x_max -= 360.0;
- }
-
- if (write_grd (maskfile, &header, data, 0.0, 0.0, 0.0, 0.0, dummy, FALSE)) {
- fprintf (stderr, "grdlandmask: Error writing file %s\n", maskfile);
- exit (-1);
- }
-
- if (gmtdefs.verbose) fprintf (stderr, "\ngrdlandmask: Done!\n");
-
- free ((char *)data);
- free ((char *)x);
- free ((char *)y);
-
- gmt_end (argc, argv);
- }
-