home *** CD-ROM | disk | FTP | other *** search
- /*--------------------------------------------------------------------
- * The GMT-system: @(#)gmt_shore.c 3.9 26 Jun 1995
- *
- * Copyright (c) 1991-1995 by P. Wessel and W. H. F. Smith
- * See README file for copying and redistribution conditions.
- *--------------------------------------------------------------------*/
-
- #include "gmt.h"
- #include "gmt_shore.h"
-
- int find_resolutions (fh)
- BOOLEAN fh[2];
- {
- /* Checks if full and high resolution coastline files are available */
-
- char file[80];
- /*----------------------------------------------------------------------
- * Modifications made to permit the use of an environmental variable
- * (defined in the header file gmt_os2.h) to be used to specify the
- * data path for the GMT data files required.
- *----------------------------------------------------------------------*/
- char *gmt_data_path;
- gmt_data_path = getenv (GMTDATAPATH);
- sprintf (file, "%s/binned_shore_f.cdf\0", gmt_data_path);
- fh[0] = !access (file, R_OK);
- sprintf (file, "%s/binned_shore_h.cdf\0", gmt_data_path);
- fh[1] = !access (file, R_OK);
-
- /* -------------------Original coding below----------------------------
- *
- * sprintf (file, "%s/binned_shore_f.cdf\0", LIBDIR);
- * fh[0] = !access (file, R_OK);
- *
- * sprintf (file, "%s/binned_shore_h.cdf\0", LIBDIR);
- * fh[1] = !access (file, R_OK);
- * --------------------------------------------------------------------*/
- }
-
- int gmt_init_shore (res, c, w, e, s, n)
- char res; /* Resolution (f, h, i, l, c */
- struct SHORE *c;
- double w, e, s, n; {
- int i, nb, idiv, iw, ie, is, in, this_south, this_west;
- short *stmp;
- nclong *itmp;
- nclong start[1], count[1];
- char file[80];
- /*----------------------------------------------------------------------
- * Modifications made to permit the use of an environmental variable
- * (defined in the header file gmt_os2.h) to be used to specify the
- * data path for the GMT data files required.
- *----------------------------------------------------------------------*/
- char *gmt_data_path;
- gmt_data_path = getenv (GMTDATAPATH);
- sprintf (file, "%s/binned_shore_%c.cdf\0", gmt_data_path, res);
-
- /* -------------------Original coding below----------------------------
- * sprintf (file, "%s/binned_shore_%c.cdf\0", LIBDIR, res);
- * --------------------------------------------------------------------*/
-
- if (access (file, R_OK)) return (-1);
- if ((c->cdfid = ncopen (file, NC_NOWRITE)) == -1) return (-1);
-
- /* Get all id tags */
-
- c->bin_size_id = ncvarid (c->cdfid, "Bin size in minutes");
- c->bin_nx_id = ncvarid (c->cdfid, "N bins in 0-360 longitude range");
- c->bin_ny_id = ncvarid (c->cdfid, "N bins in -90 +90 latitude range");
- c->n_bin_id = ncvarid (c->cdfid, "N bins in file");
- c->n_seg_id = ncvarid (c->cdfid, "N segments in file");
- c->n_pt_id = ncvarid (c->cdfid, "N points in file");
-
- c->bin_firstseg_id = ncvarid (c->cdfid, "Id of first segment in a bin");
- c->bin_info_id = ncvarid (c->cdfid, "Embedded node levels in a bin");
- c->bin_nseg_id = ncvarid (c->cdfid, "N segments in a bin");
-
- c->seg_info_id = ncvarid (c->cdfid, "Embedded <npts, levels, exit, entry> for a segment");
- c->seg_area_id = ncvarid (c->cdfid, "Area in 0.1km^2 of the parent polygon of a segment");
- c->seg_start_id = ncvarid (c->cdfid, "Id of first point in a segment");
-
- c->pt_dx_id = ncvarid (c->cdfid, "Relative longitude from SE corner of bin");
- c->pt_dy_id = ncvarid (c->cdfid, "Relative latitude from SE corner of bin");
-
- /* Get attributes */
-
- ncattget (c->cdfid, c->pt_dx_id, "units", (void *)c->units);
- ncattget (c->cdfid, NC_GLOBAL, "title", (void *)c->title);
- ncattget (c->cdfid, NC_GLOBAL, "source", (void *)c->source);
-
- /* Get global variables */
-
- start[0] = 0;
- ncvarget1 (c->cdfid, c->bin_size_id, start, (void *)&c->bin_size);
- ncvarget1 (c->cdfid, c->bin_nx_id, start, (void *)&c->bin_nx);
- ncvarget1 (c->cdfid, c->bin_ny_id, start, (void *)&c->bin_ny);
- ncvarget1 (c->cdfid, c->n_bin_id, start, (void *)&c->n_bin);
- ncvarget1 (c->cdfid, c->n_seg_id, start, (void *)&c->n_seg);
- ncvarget1 (c->cdfid, c->n_pt_id, start, (void *)&c->n_pt);
-
- c->scale = (c->bin_size / 60.0) / 65535.0;
- c->bsize = c->bin_size / 60.0;
-
- c->bins = (int *) memory ((char *)NULL, (int)c->n_bin, sizeof (int), "gmt_init_shore");
-
- /* Round off area to nearest multiple of block-dimension */
-
- iw = floor (w / c->bsize) * c->bsize;
- ie = ceil (e / c->bsize) * c->bsize;
- is = 90 - ceil ((90.0 - s) / c->bsize) * c->bsize;
- in = 90 - floor ((90.0 - n) / c->bsize) * c->bsize;
- idiv = rint (360.0 / c->bsize); /* Number of blocks per latitude band */
-
- for (i = nb = 0; i < c->n_bin; i++) { /* Find which bins are needed */
- this_south = 90 - c->bsize * ((i / idiv) + 1);
- if (this_south < is || this_south >= in) continue;
- this_west = c->bsize * (i % idiv) - 360;
- while (this_west < iw) this_west += 360;
- if (this_west >= ie) continue;
- c->bins[nb] = i;
- nb++;
- }
- c->bins = (int *) memory ((char *)c->bins, nb, sizeof (int), "gmt_init_shore");
- c->nb = nb;
-
- /* Get bin variables, then extract only those corresponding to the bins to use */
-
- /* Allocate space for arrays of bin information */
-
- c->bin_info = (short *) memory ((char *)NULL, nb, sizeof (short), "gmt_init_shore");
- c->bin_nseg = (short *) memory ((char *)NULL, nb, sizeof (short), "gmt_init_shore");
- c->bin_firstseg = (nclong *) memory ((char *)NULL, nb, sizeof (nclong), "gmt_init_shore");
-
- count[0] = c->n_bin;
- stmp = (short *) memory ((char *)NULL, (int)c->n_bin, sizeof (short), "gmt_init_shore");
-
- ncvarget (c->cdfid, c->bin_info_id, start, count, (void *)stmp);
- for (i = 0; i < c->nb; i++) c->bin_info[i] = stmp[c->bins[i]];
-
- ncvarget (c->cdfid, c->bin_nseg_id, start, count, (void *)stmp);
- for (i = 0; i < c->nb; i++) c->bin_nseg[i] = stmp[c->bins[i]];
- free ((char *)stmp);
-
- itmp = (nclong *) memory ((char *)NULL, (int)c->n_bin, sizeof (nclong), "gmt_init_shore");
- ncvarget (c->cdfid, c->bin_firstseg_id, start, count, (void *)itmp);
- for (i = 0; i < c->nb; i++) c->bin_firstseg[i] = itmp[c->bins[i]];
-
- free ((char *)itmp);
-
- return (0);
- }
-
- int gmt_get_shore_bin (b, c, min_area, max_level)
- int b; /* index number into c->bins */
- struct SHORE *c;
- double min_area; /* Polygons with area less than this are ignored */
- int max_level; { /* Polygons with higher levels are ignored */
- nclong start[1], count[1];
- nclong cut_area, *seg_area, *seg_info, *seg_start;
- int s, i;
-
- c->node_level[0] = MIN (((ushort)c->bin_info[b] >> 9) & 7, max_level);
- c->node_level[1] = MIN (((ushort)c->bin_info[b] >> 6) & 7, max_level);
- c->node_level[2] = MIN (((ushort)c->bin_info[b] >> 3) & 7, max_level);
- c->node_level[3] = MIN ((ushort)c->bin_info[b] & 7, max_level);
- c->lon_sw = (c->bins[b] % c->bin_nx) * c->bin_size / 60.0;
- c->lat_sw = 90.0 - ((c->bins[b] / c->bin_nx) + 1) * c->bin_size / 60.0;
- c->ns = 0;
-
- if (c->bin_nseg[b] == 0) return;
-
- cut_area = rint (10.0 * min_area);
- start[0] = c->bin_firstseg[b];
- count[0] = c->bin_nseg[b];
-
- seg_area = (nclong *) memory ((char *)NULL, (int)c->bin_nseg[b], sizeof (nclong), "gmt_get_shore_bin");
- seg_info = (nclong *) memory ((char *)NULL, (int)c->bin_nseg[b], sizeof (nclong), "gmt_get_shore_bin");
- seg_start = (nclong *) memory ((char *)NULL, (int)c->bin_nseg[b], sizeof (nclong), "gmt_get_shore_bin");
-
- ncvarget (c->cdfid, c->seg_area_id, start, count, (void *)seg_area);
- ncvarget (c->cdfid, c->seg_info_id, start, count, (void *)seg_info);
- ncvarget (c->cdfid, c->seg_start_id, start, count, (void *)seg_start);
-
- /* First tally how many useful segments */
-
- for (s = i = 0; i < c->bin_nseg[b]; i++) {
- if (cut_area > 0 && seg_area[i] < cut_area) continue;
- if (((seg_info[i] >> 6) & 7) > max_level) continue;
- seg_area[s] = seg_area[i];
- seg_info[s] = seg_info[i];
- seg_start[s] = seg_start[i];
- s++;
- }
- c->ns = s;
-
- if (c->ns == 0) { /* No useful segments in this bin */
- free ((char *) seg_info);
- free ((char *) seg_area);
- free ((char *) seg_start);
- return;
- }
-
- c->seg = (struct SHORE_SEGMENT *) memory ((char *)NULL, c->ns, sizeof (struct SHORE_SEGMENT), "gmt_get_shore_bin");
-
- for (s = 0; s < c->ns; s++) {
- c->seg[s].level = (seg_info[s] >> 6) & 7;
- c->seg[s].n = (seg_info[s] >> 9);
- c->seg[s].entry = (seg_info[s] >> 3) & 7;
- c->seg[s].exit = seg_info[s] & 7;
- c->seg[s].dx = (short *) memory ((char *)NULL, (int)c->seg[s].n, sizeof (short), "gmt_get_shore_bin");
- c->seg[s].dy = (short *) memory ((char *)NULL, (int)c->seg[s].n, sizeof (short), "gmt_get_shore_bin");
- start[0] = seg_start[s];
- count[0] = c->seg[s].n;
- ncvarget (c->cdfid, c->pt_dx_id, start, count, (void *)c->seg[s].dx);
- ncvarget (c->cdfid, c->pt_dy_id, start, count, (void *)c->seg[s].dy);
-
- }
-
- free ((char *) seg_info);
- free ((char *) seg_area);
- free ((char *) seg_start);
-
- }
-
- int gmt_init_br (which, res, c, w, e, s, n)
- char which; /* r(iver) or b(order) */
- char res; /* Resolution (f, h, i, l, c */
- struct BR *c;
- double w, e, s, n; {
- int i, nb, idiv, iw, ie, is, in, this_south, this_west;
- short *stmp;
- nclong *itmp;
- nclong start[1], count[1];
- char file[80];
- char *gmt_data_path;
- gmt_data_path = getenv (GMTDATAPATH);
-
- if (which == 'r')
- /* sprintf (file, "%s/binned_river_%c.cdf\0", LIBDIR, res); */
- sprintf (file, "%s/binned_river_%c.cdf\0", gmt_data_path, res);
- else
- /* sprintf (file, "%s/binned_border_%c.cdf\0", LIBDIR, res); */
- sprintf (file, "%s/binned_border_%c.cdf\0", gmt_data_path, res);
-
- if (access (file, R_OK)) return (-1);
- if ((c->cdfid = ncopen (file, NC_NOWRITE)) == -1) return (-1);
-
- /* Get all id tags */
-
- c->bin_size_id = ncvarid (c->cdfid, "Bin size in minutes");
- c->bin_nx_id = ncvarid (c->cdfid, "N bins in 0-360 longitude range");
- c->bin_ny_id = ncvarid (c->cdfid, "N bins in -90 +90 latitude range");
- c->n_bin_id = ncvarid (c->cdfid, "N bins in file");
- c->n_seg_id = ncvarid (c->cdfid, "N segments in file");
- c->n_pt_id = ncvarid (c->cdfid, "N points in file");
-
- c->bin_firstseg_id = ncvarid (c->cdfid, "Id of first segment in a bin");
- c->bin_nseg_id = ncvarid (c->cdfid, "N segments in a bin");
-
- c->seg_n_id = ncvarid (c->cdfid, "N points for a segment");
- c->seg_level_id = ncvarid (c->cdfid, "Hierarchial level of a segment");
- c->seg_start_id = ncvarid (c->cdfid, "Id of first point in a segment");
-
- c->pt_dx_id = ncvarid (c->cdfid, "Relative longitude from SE corner of bin");
- c->pt_dy_id = ncvarid (c->cdfid, "Relative latitude from SE corner of bin");
-
- /* Get attributes */
-
- ncattget (c->cdfid, c->pt_dx_id, "units", (void *)c->units);
- ncattget (c->cdfid, NC_GLOBAL, "title", (void *)c->title);
- ncattget (c->cdfid, NC_GLOBAL, "source", (void *)c->source);
-
- /* Get global variables */
-
- start[0] = 0;
- ncvarget1 (c->cdfid, c->bin_size_id, start, (void *)&c->bin_size);
- ncvarget1 (c->cdfid, c->bin_nx_id, start, (void *)&c->bin_nx);
- ncvarget1 (c->cdfid, c->bin_ny_id, start, (void *)&c->bin_ny);
- ncvarget1 (c->cdfid, c->n_bin_id, start, (void *)&c->n_bin);
- ncvarget1 (c->cdfid, c->n_seg_id, start, (void *)&c->n_seg);
- ncvarget1 (c->cdfid, c->n_pt_id, start, (void *)&c->n_pt);
-
- c->scale = (c->bin_size / 60.0) / 65535.0;
- c->bsize = c->bin_size / 60.0;
-
- c->bins = (int *) memory ((char *)NULL, (int)c->n_bin, sizeof (int), "gmt_init_br");
-
- /* Round off area to nearest multiple of block-dimension */
-
- iw = floor (w / c->bsize) * c->bsize;
- ie = ceil (e / c->bsize) * c->bsize;
- is = 90 - ceil ((90.0 - s) / c->bsize) * c->bsize;
- in = 90 - floor ((90.0 - n) / c->bsize) * c->bsize;
- idiv = rint (360.0 / c->bsize); /* Number of blocks per latitude band */
-
- for (i = nb = 0; i < c->n_bin; i++) { /* Find which bins are needed */
- this_south = 90 - c->bsize * ((i / idiv) + 1);
- if (this_south < is || this_south >= in) continue;
- this_west = c->bsize * (i % idiv) - 360;
- while (this_west < iw) this_west += 360;
- if (this_west >= ie) continue;
- c->bins[nb] = i;
- nb++;
- }
- c->bins = (int *) memory ((char *)c->bins, nb, sizeof (int), "gmt_init_br");
- c->nb = nb;
-
- /* Get bin variables, then extract only those corresponding to the bins to use */
-
- /* Allocate space for arrays of bin information */
-
- c->bin_nseg = (short *) memory ((char *)NULL, nb, sizeof (short), "gmt_init_br");
- c->bin_firstseg = (nclong *) memory ((char *)NULL, nb, sizeof (nclong), "gmt_init_br");
-
- count[0] = c->n_bin;
- stmp = (short *) memory ((char *)NULL, (int)c->n_bin, sizeof (short), "gmt_init_br");
-
- ncvarget (c->cdfid, c->bin_nseg_id, start, count, (void *)stmp);
- for (i = 0; i < c->nb; i++) c->bin_nseg[i] = stmp[c->bins[i]];
- free ((char *)stmp);
-
- itmp = (nclong *) memory ((char *)NULL, (int)c->n_bin, sizeof (nclong), "gmt_init_br");
- ncvarget (c->cdfid, c->bin_firstseg_id, start, count, (void *)itmp);
- for (i = 0; i < c->nb; i++) c->bin_firstseg[i] = itmp[c->bins[i]];
-
- free ((char *)itmp);
-
- return (0);
- }
-
- int gmt_get_br_bin (b, c, level, n_levels)
- int b; /* index number into c->bins */
- struct BR *c;
- int level[]; /* Levels of features to extract */
- int n_levels; /* # of such levels. 0 means use all levels */
- {
- nclong start[1], count[1];
- nclong *seg_start;
- short *seg_n, *seg_level;
- int s, i, k, skip;
-
- c->lon_sw = (c->bins[b] % c->bin_nx) * c->bin_size / 60.0;
- c->lat_sw = 90.0 - ((c->bins[b] / c->bin_nx) + 1) * c->bin_size / 60.0;
- c->ns = c->bin_nseg[b];
-
- if (c->ns == 0) return;
-
- start[0] = c->bin_firstseg[b];
- count[0] = c->bin_nseg[b];
-
- seg_n = (short *) memory ((char *)NULL, (int)c->bin_nseg[b], sizeof (short), "gmt_get_br_bin");
- seg_level = (short *) memory ((char *)NULL, (int)c->bin_nseg[b], sizeof (short), "gmt_get_br_bin");
- seg_start = (nclong *) memory ((char *)NULL, (int)c->bin_nseg[b], sizeof (nclong), "gmt_get_br_bin");
-
- ncvarget (c->cdfid, c->seg_n_id, start, count, (void *)seg_n);
- ncvarget (c->cdfid, c->seg_level_id, start, count, (void *)seg_level);
- ncvarget (c->cdfid, c->seg_start_id, start, count, (void *)seg_start);
-
- c->seg = (struct BR_SEGMENT *) memory ((char *)NULL, c->ns, sizeof (struct BR_SEGMENT), "gmt_get_br_bin");
-
- for (s = i = 0; i < c->ns; i++) {
- if (n_levels == 0)
- skip = FALSE;
- else {
- for (k = 0, skip = TRUE; skip && k < n_levels; k++)
- if (seg_level[i] == level[k]) skip = FALSE;
- }
- if (skip) continue;
-
- c->seg[s].n = seg_n[i];
- c->seg[s].level = seg_level[i];
- c->seg[s].dx = (short *) memory ((char *)NULL, (int)c->seg[s].n, sizeof (short), "gmt_get_br_bin");
- c->seg[s].dy = (short *) memory ((char *)NULL, (int)c->seg[s].n, sizeof (short), "gmt_get_br_bin");
- start[0] = seg_start[i];
- count[0] = c->seg[s].n;
- ncvarget (c->cdfid, c->pt_dx_id, start, count, (void *)c->seg[s].dx);
- ncvarget (c->cdfid, c->pt_dy_id, start, count, (void *)c->seg[s].dy);
-
- s++;
- }
-
- c->ns = s;
-
- free ((char *) seg_n);
- free ((char *) seg_level);
- free ((char *) seg_start);
-
- }
-
- int get_position (side, x, y)
- int side;
- short x, y; {
- /* Returns the position along the given side */
-
- return ((side%2) ? ((side == 1) ? (ushort)y : MAX_DELTA - (ushort)y) : ((side == 0) ? (ushort)x : MAX_DELTA - (ushort)x));
- }
-
- int gmt_prepare_sides (c, dir)
- struct SHORE *c;
- int dir;
- {
- int s, i, n[4], asc_sort(), desc_sort();
-
- c->lon_corner[0] = c->lon_sw + ((dir == 1) ? c->bsize : 0.0);
- c->lon_corner[1] = c->lon_sw + c->bsize;
- c->lon_corner[2] = c->lon_sw + ((dir == 1) ? 0.0 : c->bsize);
- c->lon_corner[3] = c->lon_sw;
- c->lat_corner[0] = c->lat_sw;
- c->lat_corner[1] = c->lat_sw + ((dir == 1) ? c->bsize : 0.0);
- c->lat_corner[2] = c->lat_sw + c->bsize;
- c->lat_corner[3] = c->lat_sw + ((dir == 1) ? 0.0 : c->bsize);
-
- for (i = 0; i < 4; i++) c->nside[i] = n[i] = 1;
- /* for (s = 0; s < c->ns; s++) if (c->seg[s].level < 3 && c->seg[s].entry < 4) c->nside[c->seg[s].entry]++; */
- for (s = 0; s < c->ns; s++) if (c->seg[s].entry < 4) c->nside[c->seg[s].entry]++;
-
- for (i = c->n_entries = 0; i < 4; i++) { /* Allocate memory and add corners */
- c->side[i] = (struct SIDE *) memory (CNULL, c->nside[i], sizeof (struct SIDE), "gmt_prepare_sides");
- c->side[i][0].pos = (dir == 1) ? MAX_DELTA : 0;
- c->side[i][0].id = i - 4;
- c->n_entries += c->nside[i] - 1;
- }
-
- for (s = 0; s < c->ns; s++) { /* Add entry points */
- /* if (c->seg[s].level > 2 || (i = c->seg[s].entry) == 4) continue; */
- if ((i = c->seg[s].entry) == 4) continue;
- c->side[i][n[i]].pos = get_position (i, c->seg[s].dx[0], c->seg[s].dy[0]);
- c->side[i][n[i]].id = s;
- n[i]++;
- }
-
- for (i = 0; i < 4; i++) { /* sort on position */
- if (dir == 1)
- qsort ((char *)c->side[i], c->nside[i], sizeof (struct SIDE), asc_sort);
- else
- qsort ((char *)c->side[i], c->nside[i], sizeof (struct SIDE), desc_sort);
- }
- }
-
- int gmt_assemble_shore (c, dir, assemble, shift, edge, pol)
- struct SHORE *c;
- int dir;
- BOOLEAN assemble; /* TRUE if polygons is needed */
- BOOLEAN shift; /* TRUE if longitudes may have to be shifted */
- double edge; /* Edge test for shifting */
- struct POL *pol[];
- {
- struct POL *p;
- int start_side, next_side, id, P = 0, more, p_alloc, i0, i1, j, wet_or_dry, use_this_level;
- int n_alloc, cid, nid, add, first_pos, entry_pos, n, low_level, high_level;
- BOOLEAN completely_inside;
- double *xtmp, *ytmp, plon, plat;
-
- if (!assemble) { /* Easy, just need to scale all segments to degrees and return */
-
- p = (struct POL *) memory (CNULL, c->ns, sizeof (struct POL), "gmt_assemble_shore");
-
- for (id = 0; id < c->ns; id++) {
- p[id].lon = (double *) memory (CNULL, (int)c->seg[id].n, sizeof (double), "gmt_assemble_shore");
- p[id].lat = (double *) memory (CNULL, (int)c->seg[id].n, sizeof (double), "gmt_assemble_shore");
- p[id].n = copy_to_shore_path (p[id].lon, p[id].lat, c, id);
- p[id].level = c->seg[id].level;
- p[id].interior = FALSE;
- if (shift) gmt_path_shift (p[id].lon, p[id].lat, p[id].n, edge);
- }
-
- *pol = p;
- return (c->ns);
- }
-
- for (n = high_level = 0; n < 4; n++) high_level = MAX (c->node_level[n], high_level);
- wet_or_dry = (dir == 1) ? 1 : 0;
- use_this_level = (high_level%2 == wet_or_dry);
-
- if (c->ns == 0 && !use_this_level) return (0); /* No polygons for this bin */
-
- /* Here we must assemble [at least one] polygons in the correct order */
-
- for (n = 0, completely_inside = TRUE; completely_inside && n < c->ns; n++) if (c->seg[n].entry != 4) completely_inside = FALSE;
-
- gmt_prepare_sides (c, dir);
-
- p_alloc = (c->ns == 0) ? 1 : GMT_SMALL_CHUNK;
- p = (struct POL *) memory (CNULL, p_alloc, sizeof (struct POL), "gmt_assemble_shore");
-
- low_level = MAX_LEVEL;
-
- if (completely_inside && use_this_level) { /* Must include path of this bin outline as first polygon */
- for (i0 = j = n = n_alloc = 0; j < 4; j++) {
- i1 = (i0 + dir + 4) % 4;
- if ((add = map_path (c->lon_corner[i0], c->lat_corner[i0], c->lon_corner[i1], c->lat_corner[i1], &xtmp, &ytmp))) {
- n_alloc += add;
- p[0].lon = (double *) memory ((char *)p[0].lon, n_alloc, sizeof (double), "gmt_assemble_shore");
- p[0].lat = (double *) memory ((char *)p[0].lat, n_alloc, sizeof (double), "gmt_assemble_shore");
- memcpy ((char *)&p[0].lon[n], (char *)xtmp, add * sizeof (double));
- memcpy ((char *)&p[0].lat[n], (char *)ytmp, add * sizeof (double));
- n += add;
- free ((char *)xtmp);
- free ((char *)ytmp);
- }
- i0 = i1;
- }
- p[0].n = n;
- p[0].level = c->node_level[0]; /* Any corner will do */
- p[0].interior = FALSE;
- P = 1;
- }
-
- while (c->n_entries > 0) { /* More segments to connect */
-
- low_level = MAX_LEVEL;
- start_side = 0;
- id = get_first_entry (c, dir, &start_side);
- next_side = c->seg[id].exit;
-
- n_alloc = c->seg[id].n;
- p[P].lon = (double *) memory (CNULL, n_alloc, sizeof (double), "gmt_assemble_shore");
- p[P].lat = (double *) memory (CNULL, n_alloc, sizeof (double), "gmt_assemble_shore");
- n = copy_to_shore_path (p[P].lon, p[P].lat, c, id);
- if (c->seg[id].level < low_level) low_level = c->seg[id].level;
-
- more = TRUE;
- first_pos = get_position (start_side, c->seg[id].dx[0], c->seg[id].dy[0]);
- while (more) {
-
- id = get_next_entry (c, dir, next_side, id);
-
- if (id < 0) { /* Corner */
- cid = id + 4;
- nid = (dir == 1) ? (cid + 1) % 4 : cid;
- if ((add = map_path (p[P].lon[n-1], p[P].lat[n-1], c->lon_corner[cid], c->lat_corner[cid], &xtmp, &ytmp))) {
- n_alloc += add;
- p[P].lon = (double *) memory ((char *)p[P].lon, n_alloc, sizeof (double), "gmt_assemble_shore");
- p[P].lat = (double *) memory ((char *)p[P].lat, n_alloc, sizeof (double), "gmt_assemble_shore");
- memcpy ((char *)&p[P].lon[n], (char *)xtmp, add * sizeof (double));
- memcpy ((char *)&p[P].lat[n], (char *)ytmp, add * sizeof (double));
- n += add;
- }
- next_side = ((id + 4) + dir + 4) % 4;
- if (c->node_level[nid] < low_level) low_level = c->node_level[nid];
- }
- else {
- shore_to_degree (c, c->seg[id].dx[0], c->seg[id].dy[0], &plon, &plat);
- if ((add = map_path (p[P].lon[n-1], p[P].lat[n-1], plon, plat, &xtmp, &ytmp))) {
- n_alloc += add;
- p[P].lon = (double *) memory ((char *)p[P].lon, n_alloc, sizeof (double), "gmt_assemble_shore");
- p[P].lat = (double *) memory ((char *)p[P].lat, n_alloc, sizeof (double), "gmt_assemble_shore");
- memcpy ((char *)&p[P].lon[n], (char *)xtmp, add * sizeof (double));
- memcpy ((char *)&p[P].lat[n], (char *)ytmp, add * sizeof (double));
- n += add;
- }
- entry_pos = get_position (next_side, c->seg[id].dx[0], c->seg[id].dy[0]);
- if (next_side == start_side && entry_pos == first_pos)
- more = FALSE;
- else {
- n_alloc += c->seg[id].n;
- p[P].lon = (double *) memory ((char *)p[P].lon, n_alloc, sizeof (double), "gmt_assemble_shore");
- p[P].lat = (double *) memory ((char *)p[P].lat, n_alloc, sizeof (double), "gmt_assemble_shore");
- n += copy_to_shore_path (&p[P].lon[n], &p[P].lat[n], c, id);
- next_side = c->seg[id].exit;
- if (c->seg[id].level < low_level) low_level = c->seg[id].level;
- }
- }
- if (add) {
- free ((char *)xtmp);
- free ((char *)ytmp);
- }
- }
- p[P].n = n;
- p[P].interior = FALSE;
- p[P].level = (dir == 1) ? 2 * ((low_level - 1) / 2) + 1: 2 * (low_level/2);
- P++;
- if (P == p_alloc) {
- p_alloc += GMT_SMALL_CHUNK;
- p = (struct POL *) memory ((char *)p, p_alloc, sizeof (struct POL), "gmt_assemble_shore");
- }
-
- }
-
- /* Then add all interior polygons, if any */
-
- for (id = 0; id < c->ns; id++) {
- if (c->seg[id].entry < 4) continue;
- n_alloc = c->seg[id].n;
- p[P].lon = (double *) memory (CNULL, n_alloc, sizeof (double), "gmt_assemble_shore");
- p[P].lat = (double *) memory (CNULL, n_alloc, sizeof (double), "gmt_assemble_shore");
- p[P].n = copy_to_shore_path (p[P].lon, p[P].lat, c, id);
- p[P].interior = TRUE;
- p[P].level = c->seg[id].level;
- P++;
- if (P == p_alloc) {
- p_alloc += GMT_SMALL_CHUNK;
- p = (struct POL *) memory ((char *)p, p_alloc, sizeof (struct POL), "gmt_assemble_shore");
- }
- }
-
- gmt_pau_sides (c);
-
- if (c->ns > 0) p = (struct POL *) memory ((char *)p, P, sizeof (struct POL), "gmt_assemble_shore");
-
- if (shift) for (id = 0; id < P; id++) gmt_path_shift (p[id].lon, p[id].lat, p[id].n, edge);
-
- *pol = p;
- return (P);
- }
-
- int gmt_assemble_br (c, shift, edge, pol)
- struct BR *c;
- BOOLEAN shift; /* TRUE if longitudes may have to be shifted */
- double edge; /* Edge test for shifting */
- struct POL *pol[];
- {
- struct POL *p;
- int id;
-
- p = (struct POL *) memory (CNULL, c->ns, sizeof (struct POL), "gmt_assemble_br");
-
- for (id = 0; id < c->ns; id++) {
- p[id].lon = (double *) memory (CNULL, (int)c->seg[id].n, sizeof (double), "gmt_assemble_br");
- p[id].lat = (double *) memory (CNULL, (int)c->seg[id].n, sizeof (double), "gmt_assemble_br");
- p[id].n = copy_to_br_path (p[id].lon, p[id].lat, c, id);
- p[id].level = c->seg[id].level;
- if (shift) gmt_path_shift (p[id].lon, p[id].lat, p[id].n, edge);
- }
-
- *pol = p;
- return (c->ns);
- }
-
- int copy_to_shore_path (lon, lat, s, id)
- double lon[];
- double lat[];
- struct SHORE *s;
- int id; {
- int i;
- for (i = 0; i < s->seg[id].n; i++)
- shore_to_degree (s, s->seg[id].dx[i], s->seg[id].dy[i], &lon[i], &lat[i]);
- return (s->seg[id].n);
- }
-
- int copy_to_br_path (lon, lat, s, id)
- double lon[];
- double lat[];
- struct BR *s;
- int id; {
- int i;
- for (i = 0; i < s->seg[id].n; i++)
- br_to_degree (s, s->seg[id].dx[i], s->seg[id].dy[i], &lon[i], &lat[i]);
- return (s->seg[id].n);
- }
-
- int shore_to_degree (c, dx, dy, lon, lat)
- struct SHORE *c;
- short dx, dy;
- double *lon, *lat; {
- *lon = c->lon_sw + ((ushort)dx) * c->scale;
- *lat = c->lat_sw + ((ushort)dy) * c->scale;
- }
-
- int br_to_degree (c, dx, dy, lon, lat)
- struct BR *c;
- short dx, dy;
- double *lon, *lat; {
- *lon = c->lon_sw + ((ushort)dx) * c->scale;
- *lat = c->lat_sw + ((ushort)dy) * c->scale;
- }
-
- int get_next_entry (c, dir, side, id)
- struct SHORE *c;
- int dir, id;
- int side; {
- /* Finds the next entry point on the given side that is further away
- * in the <dir> direction than previous point. It removes the info
- * regarding the new entry from the SIDE structure */
-
- int k, pos, n;
-
- if (id < 0)
- pos = (dir == 1) ? 0 : MAX_DELTA;
- else {
- n = c->seg[id].n - 1;
- pos = get_position (side, c->seg[id].dx[n], c->seg[id].dy[n]);
- }
-
- if (dir == 1) {
- for (k = 0; k < c->nside[side] && c->side[side][k].pos < pos; k++);
- id = c->side[side][k].id;
- for (k++; k < c->nside[side]; k++) c->side[side][k-1] = c->side[side][k];
- c->nside[side]--;
- }
- else {
- for (k = 0; k < c->nside[side] && c->side[side][k].pos > pos; k++);
- id = c->side[side][k].id;
- for (k++; k < c->nside[side]; k++) c->side[side][k-1] = c->side[side][k];
- c->nside[side]--;
- }
- if (id >= 0) c->n_entries--;
- return (id);
- }
-
- int get_first_entry (c, dir, side)
- struct SHORE *c;
- int dir;
- int *side; {
- int try = 0;
- while (try < 4 && (c->nside[*side] == 0 || (c->nside[*side] == 1 && c->side[*side][0].id < 0))) { /* No entries or only a corner left on this side */
- try++;
- *side = (*side + dir + 4) % 4;
- }
- if (try == 4) return (-5);
- return (c->side[*side][0].id);
- }
-
- int asc_sort (a, b)
- struct SIDE *a, *b; {
- if (a->pos < b->pos) return (-1);
- if (a->pos > b->pos) return (1);
- return (0);
- }
-
- int desc_sort (a, b)
- struct SIDE *a, *b; {
- if (a->pos < b->pos) return (1);
- if (a->pos > b->pos) return (-1);
- return (0);
- }
-
- int free_shore (c)
- struct SHORE *c; { /* Removes allocated variables for this block only */
- int i;
-
- for (i = 0; i < c->ns; i++) {
- free ((char *)c->seg[i].dx);
- free ((char *)c->seg[i].dy);
- }
- if (c->ns) free ((char *)c->seg);
- }
-
- int free_br (c)
- struct BR *c; { /* Removes allocated variables for this block only */
- int i;
-
- for (i = 0; i < c->ns; i++) {
- free ((char *)c->seg[i].dx);
- free ((char *)c->seg[i].dy);
- }
- if (c->ns) free ((char *)c->seg);
- }
-
- int shore_cleanup (c)
- struct SHORE *c; {
- free ((char *)c->bins);
- free ((char *)c->bin_info);
- free ((char *)c->bin_nseg);
- free ((char *)c->bin_firstseg);
- ncclose (c->cdfid);
- }
-
- int br_cleanup (c)
- struct BR *c; {
- free ((char *)c->bins);
- free ((char *)c->bin_nseg);
- free ((char *)c->bin_firstseg);
- ncclose (c->cdfid);
- }
-
- int gmt_pau_sides (c)
- struct SHORE *c;
- {
- int i;
- for (i = 0; i < 4; i++) free ((char *)c->side[i]);
- }
-
- int free_polygons (p, n)
- struct POL p[];
- int n; {
- int k;
- for (k = 0; k < n; k++) {
- free ((char *)p[k].lon);
- free ((char *)p[k].lat);
- }
- }
-
- int gmt_path_shift (lon, lat, n, edge)
- double lon[], lat[];
- int n;
- double edge; {
- int i;
-
- for (i = 0; i < n; i++) if (lon[i] >= edge) lon[i] -= 360.0;
- }
-
-