#include "gshhsmap.h" int gshhs_unstuff_hdr(GSHHSHdr **gshhs, char **stream) int gshhs_skip_pts(GSHHSHdr *gshhs, char **stream) int gshhsmap_open(void **handle) int gshhsmap_select(void *handle, char *types, char *resolution, double bb_lonwest, double bb_loneast, double bb_latsouth, double bb_latnorth, double bb_lonref, double bb_latref) int gshhsmap_nextseg(void *handle, int *npts, int *bufsize, float **lon, float **lat, char *type, int *level, int *antipode)
The subroutines in this utility form two interfaces into the GSHHS files; a generic file unstuffing interface, provided by gshhs_unstuff_hdr and gshhs_skip_pts, and a specialized map coordinate retrieval interface, provided by gshhsmap_open, gshhsmap_select and gshhsmap_nextseg, similar to the gmtmap(3) utility.
GSHHS data files are composed of binary SUN network byte order data arranged as a list of polygon blocks. Each polygon block consists of a binary header block followed by the binary vector polygon boundary data. gshhs_unstuff_header will unstuff a GSHHS polygon block header into an internal C-structure. stream is the byte stream that represents the GSHHS file and can be conveniently obtained with the mapfile(3) subroutine. The header is returned in gshhs which will be either malloc'ed, if the input value is NULL, or reused, if the input value is not NULL. A -1 return value indicates an error. The GSHHSHdr structure is defined in gshhsmap.h as follows:
typedef struct gshhs_hdr_ { /* Global Self-consistant Hierarchical High-resolution Shorelines Header */ int id; /* Unique polygon id number, starting at 0 */ int n; /* Number of points in this polygon */ int level; /* 1 land, 2 lake, 3 island_in_lake, 4 pond_in_island_in_lake */ int west, east, south, north; /* min/max extent in micro-degrees */ int area; /* Area of polygon in 1/10 km^2 */ short int greenwich; /* Greenwich is 1 if Greenwich is crossed */ short int source; /* 0 = CIA WDBII, 1 = WVS */ } GSHHSHdr;
After return from gshhs_unstuff_header, the stream pointer is positioned at the start of the vector data portion of the polygon block. A call to gshhs_skip_pts will advance the stream pointer to the next polygon block header.
The gshhsmap_... subroutines are hardwired to look for the particular GSHHS files that are contained in the Antelope distribution. A gshhsmap object must first be created and initialized with a call to gshhsmap_open, which returns a pointer to the object in handle. The new object is malloc'ed if the input handle value is NULL and the object is reused otherwise.
After opening the gshhsmap object, a set of map coordinates can be selected with a call to gshhsmap_select. One or more map types (for this case either coastline boundary or filled land/water mass) and map levels (a map level for these data refers to the level land/water embeddedness, for instance, level 1 coastlines refer to ocean shorelines, level 2 refer to inland lake or sea shorelines, level 3 refer to island-within-lake shorelines, etc.) can be specified in the types string which must be one to four whitespace delimited type-levelbitmap specifications in the form "<type1>:<levelbitmap1> [<type2>:<levelbitmap2> [...]]". The <typeX> specifications must be "c", for coastline boundary, or "f, for filled land/water mass. The <levelbitmapX> specifications are bitmaps in which the LSB corresponds to level 1, etc. Each set bit will cause the return of map coordinates at that level. For example, the types string for map coordinates of filled land/water masses at both the continental and major inland lake/sea levels and also coastline boundaries at only the continental level would be "f:3 c:1". Note that if the <levelbitmapX> specification is set to 0, then no levels and no coordinates will be returned. The desired resolution of the map coordinates is specified with the resolution argument which must be one of "f", for full, "h", for high, "i", for intermediate, "l" for low and "c", for crude. A latitude-longitude bounding box can be specified with the bb_lonwest, ... arguments which will limit the returned map coordinates to those within the bounding box.
Although the actual data points for the c and f map types are the same, the way in which they are ordered are different, so that the f, or filled, map type will produce highly ordered and layered sets of points that are suitable for immediate complex polygon fill rendering. This is supported by the bb_lonref and bb_latref arguments to gshhsmap_select, which should be specified as a geographic coordinate that will be within the rendered map and, for equal distance projections, should be the reference coordinate used to compute the projection. Although no projections are done in these subroutines, the bb_latref,bb_lonref coordinates are used to unwind the map longitude coordinates and to specify an antipodal coordinate (the antipode is compute as -bb_latref, 180.0+bb_lonref). The antipodal coordinate is needed for filled map types in order to determine if it is within a land mass or water mass which is needed to determine what fill color (land or water) to start with in rendering an equal distance projection map.
After the map is selected, then the coordinates can be retrieved with calls to gshhsmap_nextseg. Each call will return the value 1 and fill in the next contiguous set of map coordinates. When there are no more segments for the current map selection, then gshhsmap_nextseg will return 0. After all of the segments have been retrieved, another call to gshhsmap_select can be made to select another set of coordinates and gshhsmap_nextseg can be called again to process the segments from the new selection. The number of points for a particular segment are returned in npts. The map coordinates themselves are returned in the lat and lon floating arrays. The memory for these arrays is dynamically allocated or reused according to the incoming values of lat and lon, along with the bufsize argument. If the input values of lat and lon are NULL, then they are malloc'ed and bufsize is set to the size of the buffers in units of floats. If the input values of lat and lon are not NULL, then they are reused and potentially realloc'ed according to npts and the input value of bufsize. For each segment, the map type ("f" or "c") and level are returned in type and level. For filled map types the antipode returned value indicates if the antipode to the reference coordinate is inside a water mass (returned as 0) or land mass (returned at 1).
% cat testgshhs.c #include <stdlib.h> #include "brttutil.h" #include "stock.h" #include "gshhsmap.h" int main (int argc, char **argv) { void *handle = NULL; int nsegs, i, j, ret; int npts, bufsize = 0; float *lat=NULL; float *lon=NULL; char type[4]; int level; int antipode; if (argc != 3) { fprintf (stderr, "usage: testgshhs types resolution\n"); exit (1); } /* open the gshhsmap */ if (gshhsmap_open (&handle) < 0) { die (0, "gshhsmap_open() error.\n"); } /* select the map */ nsegs = gshhsmap_select (handle, argv[1], argv[2], -180.0, 180.0, -90.0, 90.0, 0.0, 0.0); if (nsegs < 0) { die (0, "gshhsmap_select(%s,%s) error.\n", argv[1], argv[2] ); } printf ("gshhsmap_select(%s,%s) returns %d segments\n", argv[1], argv[2], nsegs); /* parse through the first few segments and print out a few coordinates */ for (i=0; i<nsegs; i++) { if (i > 3) { printf ("...\n"); break; } ret = gshhsmap_nextseg (handle, &npts, &bufsize, &lon, &lat, type, &level, &antipode); if (ret < 0) { die (0, "gshhsmap_nextseg(%d) fatal error.\n", i); } if (ret == 0) break; printf ("gshhsmap_nextseg(%d) returns %d points for type/level %s:%d%d:\n", i, npts, type, level, antipode); for (j=0; j<npts; j++) { if (j >= 10) { printf ("\t...\n"); break; } printf ("\t%9.4f %8.4f\n", lon[j], lat[j]); } } exit (0); } % cat Makefile BIN = testgshhs MAN1 = PF = ldlibs= -lmappts -lbrttutil -lstock -ldeviants include $(ANTELOPEMAKE) DIRS= OBJS= \ testgshhs.o testgshhs : $(OBJS) $(CC) $(CFLAGS) -o $@ $(OBJS) $(LDFLAGS) $(LDLIBS) % testgshhs f:3 c gshhsmap_select(f:3,c) returns 1840 segments gshhsmap_nextseg(0) returns 1240 points for type/level l:1:0: 180.0000 68.9938 176.0816 69.8837 173.2232 69.7654 170.5499 70.1196 170.1624 69.5975 171.1792 69.0300 170.4816 68.7637 168.3216 69.2221 167.8084 69.7645 166.8734 69.4621 ... gshhsmap_nextseg(1) returns 969 points for type/level l:1:0: 286.6383 -53.0004 287.0224 -53.0824 287.0732 -52.5563 288.4549 -52.5689 288.6508 -53.1275 288.0333 -53.5788 288.1449 -53.2313 287.5158 -53.3950 288.7166 -53.9004 289.1171 -52.7390 ... gshhsmap_nextseg(2) returns 292 points for type/level l:1:0: 315.3007 59.9950 315.8866 60.3529 316.8609 60.0717 315.7807 60.5525 317.1284 60.5462 316.4708 60.8117 317.2958 61.0558 316.3708 61.1241 317.3616 61.0854 316.7491 61.3267 ... gshhsmap_nextseg(3) returns 197 points for type/level l:1:0: 360.0000 -68.9258 358.8521 -68.9460 359.3480 -69.5892 357.6267 -70.2006 352.1315 -70.6533 350.9827 -70.4266 347.7882 -71.3590 347.1135 -72.0321 344.8961 -72.0800 342.6167 -72.6742 ... ...