home *** CD-ROM | disk | FTP | other *** search
- /*--------------------------------------------------------------------
- * The GMT-system: @(#)pscoast.c 3.14 30 Jun 1995
- *
- * Copyright (c) 1991-1995 by P. Wessel and W. H. F. Smith
- * See README file for copying and redistribution conditions.
- *--------------------------------------------------------------------*/
- /*
- * pscoast can draw shorelines, paint the landward and/or seaward side of
- * the shoreline, paint lakes, draw political borders, and rivers. Three
- * data sets are considered: shores, borders, and rivers. Each of these
- * data sets come in 5 different resolutions. The lower resolution files
- * are derived from the full resolution data using the Douglas-Peucker (DP)
- * line reduction algorithm. By giving a tolerance in km, the algorithm
- * will remove points that do not depart more than the tolerance from the
- * straight line that would connect the points if the point in question was
- * removed. The resolutions are:
- *
- * full - The complete World Vector Shoreline + CIA data base
- * high - DP reduced with tolerance = 0.2 km
- * intermediate - DP reduced with tolerance = 1 km
- * low - DP reduced with tolerance = 5 km
- * crude - DP reduced with tolerance = 25 km
- *
- * If selected, pscoast will open the desired binned shoreline file and fill
- * the landmasses and/or oceans/lakes as shaded/colored/textured polygons. The
- * shoreline may also be drawn. Political boundaries and rivers may be plotted,
- * too. If only land is filled, then the 'wet' areas remain transparent.
- * If only oceans are filled, then the 'dry' areas remain transparent. This
- * allows the user to overlay land or ocean without wiping out the plot.
- * For more information about the binned polygon file, see the GMT Technical
- * Reference and Cookbook.
- *
- *
- * Author: Paul Wessel
- * Date: 26-AUG-1994
- * Version: 3.0 Rewritten from 2.1.4 to handle high-resolution
- * WVS + CIA reformatted and binned database
- *
- */
-
- #include "gmt.h"
- #include "gmt_shore.h" /* Defines shore structures */
-
- struct SHORE c;
- struct BR b, r;
-
- char *shore_resolution[5] = {"full", "high", "intermediate", "low", "crude"};
-
- main (argc, argv)
- int argc;
- char **argv; {
- int i, j, n, np, ind, bin, base = 3, n_use, start, anti_bin = -1, level;
- int level_to_be_painted, max_level = MAX_LEVEL, direction, np_new, k, last_k;
- int blevels[N_BLEVELS], n_blevels = 0, rlevels[N_RLEVELS], n_rlevels = 0;
-
- BOOLEAN error = FALSE, set_lake_fill = FALSE, draw_river = FALSE, shift, need_coast_base;
- BOOLEAN greenwich = FALSE, draw_coast = FALSE, fill_ocean = FALSE, fill_land = FALSE, possibly_donut_hell = FALSE;
- BOOLEAN clobber_background, draw_border = FALSE, paint_polygons = FALSE, donut, fill_in_use = FALSE;
- BOOLEAN miles = FALSE, draw_scale = FALSE, gave_xy = FALSE, fancy = FALSE, donut_hell = FALSE, got_fh[2];
-
- double west = 0.0, east = 0.0, south = 0.0, north = 0.0, bin_x[5], bin_y[5];
- double west_border, east_border, anti_lon, anti_lat, edge = 720.0, left, right;
- double *xtmp, *ytmp, min_area = 0.0, x0, y0, scale_lat, length, step = 0.01;
- double anti_x, anti_y, x_0, y_0, x_c, y_c, dist;
-
- char res = 'l', key[5], *string, txt_a[32], txt_b[32], txt_c[32];
-
- struct PEN coast, pen, bpen[N_BLEVELS], rpen[N_RLEVELS];
- struct FILL fill[5]; /* Colors for (0) water, (1) land, (2) lakes, (3) islands in lakes, (4) lakes in islands in lakes */
-
- struct POL *p;
-
- gmt_init_fill (&fill[0], 255, 255, 255); /* Default Ocean color */
- gmt_init_fill (&fill[1], 0, 0, 0); /* Default Land color */
- gmt_init_fill (&fill[2], 255, 255, 255); /* Default Lake color */
- fill[3] = fill[1];
- fill[4] = fill[2];
- gmt_init_pen (&coast, 1);
- gmt_init_pen (&pen, 1);
- for (k = 0; k < N_RLEVELS; k++) gmt_init_pen (&rpen[k], 1);
- for (k = 0; k < N_BLEVELS; k++) gmt_init_pen (&bpen[k], 1);
-
- memset ((char *)rlevels, 0, N_RLEVELS * sizeof (int));
- memset ((char *)blevels, 0, N_BLEVELS * sizeof (int));
-
- argc = gmt_begin (argc, argv);
-
- /* Check and interpret the command line arguments */
-
- for (i = 1; i < argc; i++) {
- if (argv[i][0] == '-') {
- switch(argv[i][1]) {
-
- /* Common parameters */
-
- case 'B': /* Get tickmark information */
- 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':
- n = sscanf (&argv[i][2], "%lf/%d", &min_area, &max_level);
- if (n == 1) max_level = MAX_LEVEL;
- break;
- case 'C': /* Lake color */
- if (argv[i][2] && gmt_getfill (&argv[i][2], &fill[2])) {
- gmt_fill_syntax ('C');
- error++;
- }
- set_lake_fill = TRUE;
- fill[4] = fill[2];
- 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 'E':
- sscanf (&argv[i][2], "%lf/%lf", &z_project.view_azimuth, &z_project.view_elevation);
- 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 or pattern */
- fill_land = TRUE;
- if (argv[i][2] && gmt_getfill (&argv[i][2], &fill[1])) {
- gmt_fill_syntax ('G');
- error++;
- }
- fill[3] = fill[1];
- break;
- case 'L':
- j = 2;
- if (argv[i][j] == 'f') fancy = TRUE, j++;
- if (argv[i][j] == 'x') gave_xy = TRUE, j++;
- k = sscanf (&argv[i][j], "%[^/]/%[^/]/%[^/]/%lf", txt_a, txt_b, txt_c, &length);
- x0 = ddmmss_to_degree (txt_a);
- y0 = ddmmss_to_degree (txt_b);
- scale_lat = ddmmss_to_degree (txt_c);
- if (k != 4) {
- fprintf (stderr, "%s: GMT SYNTAX ERROR -L option: Correct syntax\n", gmt_program);
- fprintf (stderr, " -L[f][x]<x0>/<y0>/<lat>/<length>[m], append m for miles [Default is km]\n");
- error++;
- }
- miles = (strchr (&argv[i][2], 'm') != CNULL);
- draw_scale = TRUE;
- break;
- case 'N':
- if (!argv[i][2]) {
- fprintf (stderr, "%s: GMT SYNTAX ERROR: -N option takes two arguments\n", gmt_program);
- error++;
- continue;
- }
- draw_border = TRUE;
- for (k = 2; argv[i][k] && argv[i][k] != '/'; k++);
- if (argv[i][k] && argv[i][k] == '/') { /* Specified pen args */
- strncpy (key, &argv[i][2], k-2);
- string = &argv[i][k+1];
- }
- else { /* No pen specified, use default */
- strcpy (key, &argv[i][2]);
- string = CNULL;
- }
- gmt_init_pen (&pen, 1);
- if (string && gmt_getpen (string, &pen)) {
- gmt_pen_syntax ('N');
- error++;
- }
-
- switch (key[0]) {
- case 'a':
- for (k = 0; k < N_BLEVELS; k++) blevels[k] = TRUE;
- for (k = 0; k < N_BLEVELS; k++) bpen[k] = pen;
- break;
- default:
- k = atoi (key) - 1;
- if (k < 0 || k >= N_BLEVELS) {
- fprintf (stderr, "%s: GMT SYNTAX ERROR -N option: Feature not in list!\n", gmt_program);
- error++;
- }
- else {
- blevels[k] = TRUE;
- bpen[k] = pen;
- }
- break;
- }
- break;
-
- case 'I':
- if (!argv[i][2]) {
- fprintf (stderr, "%s: GMT SYNTAX ERROR: -I option takes two arguments\n", gmt_program);
- error++;
- continue;
- }
- draw_river = TRUE;
- for (k = 2; argv[i][k] && argv[i][k] != '/'; k++);
- if (argv[i][k] && argv[i][k] == '/') { /* Specified pen args */
- strncpy (key, &argv[i][2], k-2);
- string = &argv[i][k+1];
- }
- else { /* No pen specified, use default */
- strcpy (key, &argv[i][2]);
- string = CNULL;
- }
- gmt_init_pen (&pen, 1);
- if (string && gmt_getpen (string, &pen)) {
- gmt_pen_syntax ('I');
- error++;
- }
-
- switch (key[0]) {
- case 'a':
- for (k = 0; k < N_RLEVELS; k++) rlevels[k] = TRUE;
- for (k = 0; k < N_RLEVELS; k++) rpen[k] = pen;
- break;
- case 'r':
- for (k = 0; k < 4; k++) rlevels[k] = TRUE;
- for (k = 0; k < 4; k++) rpen[k] = pen;
- break;
- case 'i':
- for (k = 5; k < 8; k++) rlevels[k] = TRUE;
- for (k = 5; k < 8; k++) rpen[k] = pen;
- break;
- case 'c':
- rlevels[8] = rlevels[9] = TRUE;
- rpen[8] = rpen[9] = pen;
- break;
- default:
- k = atoi (key) - 1;
- if (k < 0 || k >= N_RLEVELS) {
- fprintf (stderr, "%s: GMT SYNTAX ERROR -I option: Feature not in list!\n", gmt_program);
- error++;
- }
- else {
- rlevels[k] = TRUE;
- rpen[k] = pen;
- }
- break;
- }
- break;
-
- case 'S': /* Set ocean color if needed */
- if (argv[i][2] && gmt_getfill (&argv[i][2], &fill[0])) {
- gmt_fill_syntax ('S');
- error++;
- }
- fill_ocean = TRUE;
- break;
- case 'W':
- if (argv[i][2] && gmt_getpen (&argv[i][2], &coast)) {
- gmt_pen_syntax ('W');
- error++;
- }
- draw_coast = TRUE;
- break;
- case '-': /* Undocumented option to increase path-fix resolution */
- step = atof (&argv[i][2]);
- break;
-
- default: /* Options not recognized */
- 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) { /* Display usage */
- fprintf (stderr,"pscoast %s - Plot continents, shorelines, rivers, and borders on maps\n\n", GMT_VERSION);
- fprintf (stderr,"usage: pscoast -J<params> -R<west>/<east>/<south>/<north> [-A<min_area>[/<max_level>]] [-B<tickinfo>]\n");
- fprintf (stderr, " [-C[<fill>]] [-D<resolution>] [-Eaz/el] [-F<r/g/b] [-G[<fill>]] [-I<feature>[/<pen>]]\n");
- fprintf (stderr, " [-K] [-L[f][x]<lon0>/<lat0>/<slat>/<length>[m]] [-N<feature>[/<pen>]] [-O] [-P]\n");
- fprintf (stderr, " [-S<fill>] [-U[dx/dy/][label]] [-V] [-W[<pen>]] [-X<x_shift>] [-Y<y_shift>] [-c<ncopies>]\n");
-
- if (gmt_quick) exit (-1);
-
- explain_option ('j');
- explain_option ('R');
- fprintf (stderr, "\n\tOPTIONS:\n");
- fprintf (stderr, " -A features smaller than <min_area> (in km^2) or of higher level (0-4) than <max_level>\n");
- fprintf (stderr, " will be skipped [0/4 (4 means lake inside island inside lake)]\n");
- explain_option ('b');
- fprintf (stderr, " -C sets separate color for lakes. [Default is same as ocean (white)]. Set\n");
- fprintf (stderr, " 1) <r/g/b> (each 0-255) for color or <gray> (0-255) for gray-shade [0].\n");
- fprintf (stderr, " 2) p[or P]<iconsize>/<pattern> for predefined patterns (0-31).\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 busy plots that need crude continent outlines only\n");
- fprintf (stderr, " -E set azimuth and elevation of viewpoint for 3-D perspective [180/90]\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 Paint \"dry\" areas. Append desired paint [Default is black] as:\n");
- fprintf (stderr, " 1) <r/g/b> (each 0-255) for color or <gray> (0-255) for gray-shade [0].\n");
- fprintf (stderr, " 2) p[or P]<iconsize>/<pattern> for predefined patterns (0-31).\n");
- fprintf (stderr, " -I draws rIvers. Specify feature and optionally append pen [Default is solid line of unit thickness].\n");
- fprintf (stderr, " Choose from the features below. Repeat the -I option as many times as needed\n");
- fprintf (stderr, " 1 = Permanent major rivers\n");
- fprintf (stderr, " 2 = Additional major rivers\n");
- fprintf (stderr, " 3 = Additional rivers\n");
- fprintf (stderr, " 4 = Minor rivers\n");
- fprintf (stderr, " 5 = Double lined rivers\n");
- fprintf (stderr, " 6 = Intermittent rivers - major\n");
- fprintf (stderr, " 7 = Intermittent rivers - additional\n");
- fprintf (stderr, " 8 = Intermittent rivers - minor\n");
- fprintf (stderr, " 9 = Major canals\n");
- fprintf (stderr, " 10 = Minor canals\n");
- fprintf (stderr, " a = All rivers and canals (1-10)\n");
- fprintf (stderr, " r = All permanent rivers (1-4)\n");
- fprintf (stderr, " i = All intermittent rivers (6-8)\n");
- fprintf (stderr, " c = All canals (9-10)\n");
- explain_option ('K');
- fprintf (stderr, " -L draws a simple map scaLe centered on <lon0>/<lat0>. Use -Lx to specify cartesian coordinates instead.\n");
- fprintf (stderr, " Scale is calculated at latitude <slat>. <length> is in km, or miles is m is appended\n");
- fprintf (stderr, " -Lf draws a \"fancy\" scale [Default is plain]\n");
- fprintf (stderr, " -N draws boundaries. Specify feature and optionally append pen [Default is solid line of unit thickness]\n");
- fprintf (stderr, " Choose from the features below. Repeat the -N option as many times as needed\n");
- fprintf (stderr, " 1 = National boundaries\n");
- fprintf (stderr, " 2 = State boundaries within the Americas\n");
- fprintf (stderr, " 3 = Marine boundaries\n");
- fprintf (stderr, " a = All boundaries (1-3)\n");
- explain_option ('O');
- explain_option ('P');
- fprintf (stderr, " -S Paint \"wet\" areas. Append desired paint [Default is white] as:\n");
- fprintf (stderr, " 1) <r/g/b> (each 0-255) for color or <gray> (0-255) for gray-shade [0].\n");
- fprintf (stderr, " 2) p[or P]<iconsize>/<pattern> for predefined patterns (0-31).\n");
- explain_option ('U');
- explain_option ('V');
- fprintf (stderr," -W draw shorelines. Append pen [Default is solid line of unit thickness].\n");
- explain_option ('X');
- explain_option ('c');
- explain_option ('.');
- exit (-1);
- }
-
- /* Check that the options selected are mutually consistant */
-
- if (!project_info.region_supplied) {
- fprintf (stderr, "%s: GMT SYNTAX ERROR: Must specify -R option\n", gmt_program);
- error++;
- }
- if (coast.width < 0) {
- fprintf (stderr, "%s: GMT SYNTAX ERROR -W option: Pen thickness cannot be negative\n", gmt_program);
- error++;
- }
- if (!(fill_land || fill_ocean || draw_coast || draw_border || draw_river)) {
- fprintf (stderr, "%s: GMT SYNTAX ERROR: Must specify at least one of -G, -S, -I, -N, and -W\n", gmt_program);
- error++;
- }
- if (z_project.view_azimuth > 360.0 || z_project.view_elevation <= 0.0 || z_project.view_elevation > 90.0) {
- fprintf (stderr, "%s: GMT SYNTAX ERROR -E option: Enter azimuth in 0-360 range, elevation in 0-90 range\n", gmt_program);
- error++;
- }
-
- if (draw_river) {
- for (k = 0; k < N_RLEVELS; k++) {
- if (!rlevels[k]) continue;
- if (rpen[k].width < 0) {
- fprintf (stderr, "%s: GMT SYNTAX ERROR -I option: Pen thickness cannot be negative\n", gmt_program);
- error++;
- }
- rlevels[n_rlevels] = k + 1;
- rpen[n_rlevels] = rpen[k];
- n_rlevels++;
- }
- }
-
- if (draw_border) {
- for (k = 0; k < N_BLEVELS; k++) {
- if (!blevels[k]) continue;
- if (bpen[k].width < 0) {
- fprintf (stderr, "%s: GMT SYNTAX ERROR -N option: Pen thickness cannot be negative\n", gmt_program);
- error++;
- }
- blevels[n_blevels] = k + 1;
- bpen[n_blevels] = bpen[k];
- n_blevels++;
- }
- }
-
- if (error) exit (-1);
-
- need_coast_base = (fill_land || fill_ocean || draw_coast);
- clobber_background = (fill_land && fill_ocean);
- paint_polygons = (fill_land || fill_ocean);
-
- if (east > 360.0) {
- west -= 360.0;
- east -= 360.0;
- }
-
- map_setup (west, east, south, north);
-
- if (need_coast_base && gmt_init_shore (res, &c, project_info.w, project_info.e, project_info.s, project_info.n)) {
- fprintf (stderr, "%s: %s resolution shoreline data base not installed\n", gmt_program, shore_resolution[base]);
- need_coast_base = FALSE;
- }
-
- if (draw_border && gmt_init_br ('b', res, &b, project_info.w, project_info.e, project_info.s, project_info.n)) {
- fprintf (stderr, "%s: %s resolution political boundary data base not installed\n", gmt_program, shore_resolution[base]);
- draw_border = FALSE;
- }
-
- if (draw_river && gmt_init_br ('r', res, &r, project_info.w, project_info.e, project_info.s, project_info.n)) {
- fprintf (stderr, "%s: %s resolution river data base not installed\n", gmt_program, shore_resolution[base]);
- draw_river = FALSE;
- }
-
- if (! (need_coast_base || draw_border || draw_river)) {
- fprintf (stderr, "%s: No databases available - aborts\n", gmt_program);
- exit (-1);
- }
-
-
- 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);
- if (base > 0) ps_command ("2 setlinejoin"); /* Avoid excessive mitering for cruder lines */
-
- if (project_info.three_D) ps_transrotate (-z_project.xmin, -z_project.ymin, 0.0);
-
- if (fill_ocean && !set_lake_fill) fill[2] = fill[4] = fill[0]; /* Use ocean fill by default for lakes */
-
- for (i = 0; i < 5; i++) if (fill[i].use_pattern) { /* Must initialize patterns */
- ps_imagefill_init (fill[i].pattern_no, fill[i].pattern, fill[i].inverse, fill[i].icon_size);
- fill_in_use = TRUE;
- }
-
- if (fill_in_use && !clobber_background) { /* Force clobber when fill is used for now */
- fprintf (stderr, "%s: Warning: Pattern fill requires oceans to be painted first\n", gmt_program);
- clobber_background = TRUE;
- }
-
- if (project_info.projection == AZ_EQDIST && fabs (project_info.w - project_info.e) == 360.0 && (project_info.n - project_info.s) == 180.0) {
- possibly_donut_hell = TRUE;
- anti_lon = project_info.central_meridian + 180.0;
- if (anti_lon >= 360.0) anti_lon -= 360.0;
- anti_lat = -project_info.pole;
- anti_bin = floor ((90.0 - anti_lat) / c.bsize) * c.bin_nx + floor (anti_lon / c.bsize);
- geo_to_xy (anti_lon, anti_lat, &anti_x, &anti_y);
- geo_to_xy (project_info.central_meridian, project_info.pole, &x_0, &y_0);
- if (fill_land) {
- fprintf (stderr, "%s: Warning: Fill continent option (-G) may not work for this projection.\n", gmt_program);
- fprintf (stderr, "If the antipole (%lg/%lg) is in the ocean then chances are good\n", anti_lon, anti_lat);
- fprintf (stderr, "Else: avoid projection center coordinates that are exact multiples of %lg degrees\n", c.bsize);
- }
- }
-
- if (possibly_donut_hell && !clobber_background) { /* Force clobber when donuts may be called for now */
- fprintf (stderr, "%s: Warning: -JE requires oceans to be painted first\n", gmt_program);
- clobber_background = TRUE;
- }
-
- if (clobber_background) { /* Paint entire map as ocean first, then lay land on top */
- n = map_clip_path (&xtmp, &ytmp, &donut);
- if (donut) {
- ps_line (xtmp, ytmp, n, 1, TRUE, FALSE);
- ps_line (&xtmp[n], ytmp[n], n, -1, TRUE, FALSE);
- dump_paint (xtmp, ytmp, n, &fill[0], -1);
- }
- else
- dump_paint (xtmp, ytmp, n, &fill[0], FALSE);
- free ((char *)xtmp);
- free ((char *)ytmp);
- fill_ocean = FALSE;
- direction = 1;
- }
- else if (fill_land) {
- direction = 1;
- level_to_be_painted = 1;
- }
- else {
- direction = -1;
- level_to_be_painted = 0;
- }
-
- if (west < 0.0 && east > 0.0 && project_info.projection > 5) greenwich = TRUE;
- if (gmt_world_map && greenwich)
- edge = project_info.central_meridian;
- else if (!gmt_world_map && greenwich) {
- shift = TRUE;
- edge = west; if (edge < 0.0) edge += 360.0;
- if (edge > 180.0) edge = 180.0;
- }
-
- west_border = project_info.w; east_border = project_info.e;
- if (project_info.w < 0.0 && project_info.e <= 0.0) { /* Temporarily shift boundaries */
- project_info.w += 360.0;
- project_info.e += 360.0;
- }
-
- if (draw_coast) {
- ps_setpaint (coast.r, coast.g, coast.b);
- ps_setline (coast.width);
- if (coast.texture) ps_setdash (coast.texture, coast.offset);
- }
-
- for (ind = 0; need_coast_base && ind < c.nb; ind++) { /* Loop over necessary bins only */
-
- bin = c.bins[ind];
- gmt_get_shore_bin (ind, &c, min_area, max_level);
-
- if (gmtdefs.verbose) fprintf (stderr, "pscoast: Working on block # %5d\r", bin);
- printf ("%% Bin # %d\n", bin);
-
- if (gmt_world_map && greenwich) {
- left = c.bsize * (bin % c.bin_nx); right = left + c.bsize;
- shift = ((left - edge) <= 180.0 && (right - edge) > 180.0);
- }
-
- if (anti_bin == bin)
- anti_bin = bin;
-
- if (possibly_donut_hell) {
- bin_x[0] = bin_x[3] = bin_x[4] = c.lon_sw;
- bin_x[1] = bin_x[2] = c.lon_sw + c.bsize;
- bin_y[0] = bin_y[1] = bin_y[4] = c.lat_sw;
- bin_y[2] = bin_y[3] = c.lat_sw + c.bsize;
- geo_to_xy (c.lon_sw + 0.5 * c.bsize, c.lat_sw + 0.5 * c.bsize, &x_c, &y_c);
- dist = hypot (x_c - x_0, y_c - y_0);
- donut_hell = non_zero_winding (anti_lon, anti_lat, bin_x, bin_y, 5);
- if (!donut_hell) donut_hell = (dist > 0.8 * project_info.r);
- }
-
- if (paint_polygons && (np = gmt_assemble_shore (&c, direction, TRUE, shift, edge, &p))) {
-
- /* Have assembled segments into polygons */
-
- np_new = np;
-
- for (k = 0; k < np; k++) {
-
- if (donut_hell) p[k].n = fix_up_path (&p[k].lon, &p[k].lat, p[k].n, greenwich, step);
-
- /* Clip polygon against map boundary if necessary and return plot x,y in inches */
-
- if ((n = clip_to_map (p[k].lon, p[k].lat, p[k].n, &xtmp, &ytmp)) == 0) { /* Completely outside */
- p[k].n = 0;
- continue;
- }
-
- /* Must check if polygon must be split and partially plotted at both edges of map */
-
- if (will_it_wrap (xtmp, ytmp, n, &start)) { /* Polygon does indeed wrap */
-
- /* First truncate agains left border */
-
- gmt_n_plot = truncate_left (xtmp, ytmp, n, start);
- n_use = compact_line (gmt_x_plot, gmt_y_plot, gmt_n_plot, FALSE, 0);
- if (project_info.three_D) two_d_to_three_d (gmt_x_plot, gmt_y_plot, gmt_n_plot);
- p[k].lon = (double *) memory ((char *)p[k].lon, n_use, sizeof (double), "pscoast");
- p[k].lat = (double *) memory ((char *)p[k].lat, n_use, sizeof (double), "pscoast");
- memcpy ((char *)p[k].lon, (char *)gmt_x_plot, n_use * sizeof (double));
- memcpy ((char *)p[k].lat, (char *)gmt_y_plot, n_use * sizeof (double));
- p[k].n = n_use;
-
- /* Then truncate agains right border */
-
- gmt_n_plot = truncate_right (xtmp, ytmp, n, start);
- n_use = compact_line (gmt_x_plot, gmt_y_plot, gmt_n_plot, FALSE, 0);
- if (project_info.three_D) two_d_to_three_d (gmt_x_plot, gmt_y_plot, gmt_n_plot);
- p = (struct POL *) memory ((char *)p, np_new + 1, sizeof (struct POL), "pscoast");
- p[np_new].lon = (double *) memory (CNULL, n_use, sizeof (double), "pscoast");
- p[np_new].lat = (double *) memory (CNULL, n_use, sizeof (double), "pscoast");
- memcpy ((char *)p[np_new].lon, (char *)gmt_x_plot, n_use * sizeof (double));
- memcpy ((char *)p[np_new].lat, (char *)gmt_y_plot, n_use * sizeof (double));
- p[np_new].n = n_use;
- p[np_new].interior = p[k].interior;
- p[np_new].level = p[k].level;
- np_new++;
- }
- else {
- n_use = compact_line (xtmp, ytmp, n, FALSE, 0);
- if (project_info.three_D) two_d_to_three_d (xtmp, ytmp, n_use);
- if (anti_bin == bin && step == 0.0) { /* Must warn for donut effect */
- fprintf (stderr, "%s: GMT Warning: Antipodal bin # %d not filled!\n", gmt_program, anti_bin);
- free ((char *)xtmp);
- free ((char *)ytmp);
- continue;
- }
-
- else {
- p[k].lon = (double *) memory ((char *)p[k].lon, n_use, sizeof (double), "pscoast");
- p[k].lat = (double *) memory ((char *)p[k].lat, n_use, sizeof (double), "pscoast");
- memcpy ((char *)p[k].lon, (char *)xtmp, n_use * sizeof (double));
- memcpy ((char *)p[k].lat, (char *)ytmp, n_use * sizeof (double));
- p[k].n = n_use;
- }
- }
-
- free ((char *)xtmp);
- free ((char *)ytmp);
- }
-
- /* Now we have clipped polygons in x,y inches that can be plotted */
-
- if (clobber_background) { /* Simply points all polygons as is */
- for (k = 0; k < np_new; k++) {
- level = MIN (p[k].level, 2);
- if (donut_hell && non_zero_winding (anti_x, anti_y, p[k].lon, p[k].lat, p[k].n)) { /* Antipode inside polygon, must do donut */
- n = map_clip_path (&xtmp, &ytmp, &donut);
- ps_line (xtmp, ytmp, n, 1, TRUE, FALSE);
- ps_line (p[k].lon, p[k].lat, p[k].n, -1, TRUE, FALSE);
- dump_paint (xtmp, ytmp, n, &fill[level], -1);
- free ((char *)xtmp);
- free ((char *)ytmp);
- }
- else
- dump_paint (p[k].lon, p[k].lat, p[k].n, &fill[level], FALSE);
- }
- }
- else { /* Must avoid pointing anything but the polygons inside */
-
- for (k = level_to_be_painted; k < MAX_LEVEL - 1; k++) {
- recursive_painting (-1, np_new, p, k, k, fill);
- }
-
- for (k = 0; k < np_new; k++) { /* Do any remaining interior polygons */
- if (p[k].n == 0) continue;
- if (p[k].level%2 == level_to_be_painted)
- dump_paint (p[k].lon, p[k].lat, p[k].n, &fill[p[k].level], FALSE);
- }
-
- }
-
- free_polygons (p, np_new);
- free ((char *)p);
- }
-
- if (draw_coast && c.ns) { /* Draw shorelines, no need to assemble polygons */
-
- np = gmt_assemble_shore (&c, direction, FALSE, shift, edge, &p);
-
- for (i = 0; i < np; i++) {
- if (donut_hell) p[i].n = fix_up_path (&p[i].lon, &p[i].lat, p[i].n, greenwich, step);
- gmt_n_plot = geo_to_xy_line (p[i].lon, p[i].lat, p[i].n);
- if (gmt_n_plot) gmt_plot_line (gmt_x_plot, gmt_y_plot, gmt_pen, gmt_n_plot);
- }
-
- free_polygons (p, np);
- free ((char *)p);
- }
-
- free_shore (&c);
-
- }
- if (need_coast_base) shore_cleanup (&c);
-
- if (gmtdefs.verbose) fprintf (stderr, "\n");
-
- if (draw_river) { /* Read rivers file and plot as lines */
-
- if (gmtdefs.verbose) fprintf (stderr, "pscoast: Adding Rivers...");
- ps_comment ("Start of River segments");
- last_k = -1;
-
- for (ind = 0; ind < r.nb; ind++) { /* Loop over necessary bins only */
-
- bin = r.bins[ind];
- gmt_get_br_bin (ind, &r, rlevels, n_rlevels);
-
- if (r.ns == 0) continue;
-
- if (gmt_world_map && greenwich) {
- left = r.bsize * (bin % r.bin_nx); right = left + r.bsize;
- shift = ((left - edge) <= 180.0 && (right - edge) > 180.0);
- }
-
- np = gmt_assemble_br (&r, shift, edge, &p);
-
- for (i = 0; i < np; i++) {
- gmt_n_plot = geo_to_xy_line (p[i].lon, p[i].lat, p[i].n);
- if (!gmt_n_plot) continue;
-
- k = p[i].level - 1;
- if (k != last_k) {
- ps_setline (rpen[k].width);
- ps_setpaint (rpen[k].r, rpen[k].g, rpen[k].b);
- if (rpen[k].texture) ps_setdash (rpen[k].texture, rpen[k].offset);
- last_k = k;
- }
- gmt_plot_line (gmt_x_plot, gmt_y_plot, gmt_pen, gmt_n_plot);
- }
-
- /* Free up memory */
-
- free_br (&r);
- for (k = 0; k < np; k++) {
- free ((char *)p[k].lon);
- free ((char *)p[k].lat);
- }
- free ((char *)p);
- }
- br_cleanup (&r);
- ps_setdash (CNULL, 0);
-
- if (gmtdefs.verbose) fprintf (stderr, "\n");
- }
-
- if (draw_border) { /* Read borders file and plot as lines */
-
- if (gmtdefs.verbose) fprintf (stderr, "pscoast: Adding Borders...");
- ps_comment ("Start of Border segments");
-
- /* Must resample borders because some points may be too far apart and look like 'jumps' */
-
- step = MAX (fabs(project_info.w - project_info.e), fabs (project_info.n - project_info.s)) / 4.0;
-
- last_k = -1;
-
- for (ind = 0; ind < b.nb; ind++) { /* Loop over necessary bins only */
-
- bin = b.bins[ind];
- gmt_get_br_bin (ind, &b, blevels, n_blevels);
-
- if (b.ns == 0) continue;
-
- if (gmt_world_map && greenwich) {
- left = b.bsize * (bin % b.bin_nx); right = left + b.bsize;
- shift = ((left - edge) <= 180.0 && (right - edge) > 180.0);
- }
-
- np = gmt_assemble_br (&b, shift, edge, &p);
- for (i = 0; i < np; i++) {
- p[i].n = fix_up_path (&p[i].lon, &p[i].lat, p[i].n, greenwich, step);
- gmt_n_plot = geo_to_xy_line (p[i].lon, p[i].lat, p[i].n);
- if (!gmt_n_plot) continue;
-
- k = p[i].level - 1;
- if (k != last_k) {
- ps_setline (bpen[k].width);
- ps_setpaint (bpen[k].r, bpen[k].g, bpen[k].b);
- if (bpen[k].texture) ps_setdash (bpen[k].texture, bpen[k].offset);
- last_k = k;
- }
- gmt_plot_line (gmt_x_plot, gmt_y_plot, gmt_pen, gmt_n_plot);
- }
-
- /* Free up memory */
-
- free_br (&b);
- for (k = 0; k < np; k++) {
- free ((char *)p[k].lon);
- free ((char *)p[k].lat);
- }
- free ((char *)p);
- }
- br_cleanup (&b);
- ps_setdash (CNULL, 0);
-
- if (gmtdefs.verbose) fprintf (stderr, "\n");
- }
-
- if (base > 0) ps_command ("0 setlinejoin"); /* Reset mitering */
-
- if (frame_info.plot) {
- project_info.w = west_border;
- project_info.e = east_border;
- ps_setpaint (gmtdefs.basemap_frame_rgb[0], gmtdefs.basemap_frame_rgb[1], gmtdefs.basemap_frame_rgb[2]);
- map_basemap ();
- }
-
- if (draw_scale) draw_map_scale (x0, y0, scale_lat, length, miles, gave_xy, fancy);
-
- ps_setpaint (gmtdefs.background_rgb[0], gmtdefs.background_rgb[1], gmtdefs.background_rgb[2]);
-
- if (project_info.three_D) ps_rotatetrans (z_project.xmin, z_project.ymin, 0.0);
- ps_plotend (gmtdefs.last_page);
-
- gmt_end (argc, argv);
- }
-
- int dump_paint (x, y, n, f, status)
- double x[], y[];
- int n;
- struct FILL *f;
- BOOLEAN status; {
- if (f->use_pattern)
- ps_imagefill (x, y, n, f->pattern_no, f->pattern, f->inverse, f->icon_size, status);
- else
- ps_polygon (x, y, n, f->r, f->g, f->b, status);
- }
-
- int recursive_painting (k0, np, p, level, start_level, fill)
- int k0, np, level, start_level;
- struct POL p[];
- struct FILL fill[]; {
- int k, flag;
- BOOLEAN go;
- char text[50];
- if (level > MAX_LEVEL) return;
- flag = (level == start_level) ? 1 : 0;
- for (k = k0 + 1; k < np; k++) {
- if (p[k].n == 0 || p[k].level < level) continue;
- go = (p[k].level == level) ? ((k0 == -1) ? TRUE : non_zero_winding (p[k].lon[0], p[k].lat[0], p[k0].lon, p[k0].lat, p[k0].n)) : FALSE;
- if (go) {
- sprintf (text, "Polygon %d\0", k);
- ps_comment (text);
- ps_clipon (p[k].lon, p[k].lat, p[k].n, -1, -1, -1, flag);
- recursive_painting (k, np, p, level+1, start_level, fill);
- p[k].n = 0;
- }
-
- if (p[k].level == start_level) { /* Done nesting, time to paint */
- ps_clipon (p[k].lon, p[k].lat, 0, -1, -1, -1, 4); /* Dummy to end path */
- dump_paint (p[k].lon, p[k].lat, p[k].n, &fill[p[k].level], -1);
- }
- }
-
- return;
- }
-