1532 #include #include #include #include #include #include #include #include #include #include "mapview.h" #include "wdbii.h" static POINT *pts; static int npts = 0; static int penup = TRUE; static WDBMAP *map; static WDBMAPREC *recs, *prevrec; void drawwdbii(WDBMAP *map) { static XPoint p[MAXPOINTS]; WDBMAPREC *rec; int np; setlinewidth(map->width); for (rec = map->recs; rec; rec = rec->next) { int i; np = 0; for (i = 0; i < rec->npts; i++) { if (rec->pts[i].lat < minlat || rec->pts[i].lat > maxlat || rec->pts[i].lon < minlon || rec->pts[i].lon > maxlon) { if (np) { if (np > 1) poly(p, np, map->color); else pset(p[0].x, p[0].y, map->color); } np = 0; continue; } ll2xy(rec->pts[i].lon, rec->pts[i].lat, &(p[np].x), &(p[np].y)); np++; } if (np) { if (np > 1) poly(p, np, map->color); else pset(p[0].x, p[0].y, map->color); } } } static void addrec(SEGDICT *sd) { WDBMAPREC *rec = (WDBMAPREC *)malloc(sizeof(WDBMAPREC)); rec->rank = (char)sd->rank; rec->pts = (POINT *)malloc(npts * sizeof(POINT)); rec->npts = npts; rec->minlat = sd->minlat / 3600.; rec->maxlat = sd->maxlat / 3600.; rec->minlon = sd->minlon / 3600.; rec->maxlon = sd->maxlon / 3600.; rec->next = NULL; memcpy(rec->pts, pts, npts * sizeof(POINT)); if (! recs) recs = rec; if (prevrec) prevrec->next = rec; prevrec = rec; } static void pendn(double lon, double lat, SEGDICT *sd) { static SEGDICT *prevsd; if (lat < iminlat || lat > imaxlat || lon < iminlon || lon > imaxlon) { if (npts) addrec(prevsd); npts = 0; return; } if (penup) { if (npts) addrec(prevsd); npts = 0; penup = FALSE; } pts[npts].lat = lat; pts[npts].lon = lon; if (++npts == MAXPOINTS) { addrec(sd); npts = 0; } prevsd = sd; } WDBMAP *loadwdbii(char *fname, unsigned long color, unsigned long fillcolor, int width) { int fd, segcount, idx, idy, segbufsize, olt, oln, k, stroke, iseg; char *databuf; BIT32 i32; BIT16 *segbuf; double lastlon = 0.; double lon, lat; struct stat st; int pos; CBDHEAD *header; SEGDICT *sd, *sdbuf; SEGBUF sb; recs = prevrec = NULL; if ((fd = open(fname, O_RDONLY)) < 0) { perror("open"); exit(1); } if (fstat(fd, &st) < 0) { perror("fstat"); exit(1); } pts = (POINT *)malloc(MAXPOINTS * sizeof(POINT)); databuf = (char*)malloc(st.st_size); read(fd, databuf, st.st_size); close(fd); /* * Check the file header for the correct magic number, * and learn the address of the segment dictionary */ header = (CBDHEAD *)databuf; if (header->magic != CBD_MAGIC) { fprintf(stderr, "File has bad magic number %X != %X\n", header->magic, CBD_MAGIC); exit(1); } /* allocate space for the segment buffer */ segbufsize = 2 * header->segmax; segbuf = (BIT16 *) malloc (50 + segbufsize); /* allocate space for the segment dictionary */ sdbuf = (SEGDICT *) malloc (100 + (header->segsize)); sd = sdbuf; sd++; /* Get the segment dictionary (it's at the end of the file) */ memcpy(sd, databuf + header->dictaddr, header->segsize); /* * Now look at each segment and decide if we're * going to keep it or not */ segcount = header->segcount; npts = 0; sd = sdbuf; for (iseg = 1; iseg <= segcount; iseg++) { sd++; /* does this really work? wow! */ pos = sd->absaddr; memcpy(&sb, databuf + pos, sizeof(sb)); pos += sizeof(sb); if (sd->nbytes > segbufsize) { fprintf(stderr, "Segment %d needs %d bytes; buffer limit is %d.\n", iseg, sd->nbytes, segbufsize); exit(1); } memcpy(segbuf, databuf + pos, sd->nbytes); k = 0; oln = sb.orgx; olt = sb.orgy; lon = oln / 3600.; lat = olt / 3600.; penup = TRUE; pendn(lon, lat, sd); lastlon = lon; for (stroke = 1; stroke <= sb.nstrokes; stroke++) { if (segbuf[k] & SHORTFLAG) { /* Flag bit on: unpack a 16-bit field into dx and dy */ i32 = segbuf[k++]; if (i32 > 0) i32 &= ~SHORTFLAG; idy = i32 & 0xFF; if (idy & 0x80) idy |= ~0xFF; /* extend sign */ idx = i32 >> 8; if (idx & 0x80) idx |= ~0xBF; /* extend sign */ } else { /* Flag bit off: take dx and dy from 32-bit fields. */ idx = segbuf[k++]; if (idx < 0) idx |= SHORTFLAG; idx = (idx << 16) | (unsigned short) segbuf[k]; k++; idy = segbuf[k]; k++; if (idy < 0) idy |= SHORTFLAG; idy = (idy << 16) | segbuf[k]; k++; } oln = (oln + idx); olt = (olt + idy); lon = oln / 3600.; lat = olt / 3600.; if (fabs(lastlon - lon) > 180.) penup = TRUE; pendn(lon, lat, sd); lastlon = lon; } } if (npts) addrec(sd); free(sdbuf); free(segbuf); free(databuf); free(pts); map = (WDBMAP *)malloc(sizeof(WDBMAP)); map->type = WDBII; map->color = color; map->fillcolor = fillcolor; map->width = width; map->recs = recs; map->next = NULL; return map; } . 0