/* * Usage: cbd2else [-rezfile name] [-output name] [-format type] * [-continents list] [-types list] * [-ascii type] [-verbose] [-silent] * where format type is one of NONE (default), TEXT, JPD * and TXT ascii type is one of DXDY (default), INT, REAL * */ #include #include #include #include #include #include #define TOTALSEG 31844 /* number of segments in WDB is really 31845, but one river showing up in Uganda is faulty and must be deleted ! */ #define CBD_MAGIC 0x20770002 #define REZ_MAGIC 0x86460346 #define JPD_MAGIC "!JPD1.0\n" #define SHORTFLAG 0x4000 #define BIT32 int #define BIT16 short #define DEBUG 1 enum { AFRICA=0, ASIA, EUROPE, NAMERICA, SAMERICA }; enum { BDY=0, PBY, RIV, CIL }; enum {NONE=0, TEXT, REZ, JPD }; enum {INT=0, REAL, BOTH}; struct cbdhead { BIT32 magic; /* Magic number */ BIT32 dictaddr; /* Offset of segment dictionary in file */ BIT32 segcount; /* Number of segments in file */ BIT32 segsize; /* Size of segment dictionary */ BIT32 segmax; /* Size of largest segment's strokes, /2 */ BIT32 fill[(40 / sizeof (BIT32)) - 5]; /* Filler */ }; struct segdict { BIT32 segid; BIT32 maxlat, minlat, maxlong, minlong; BIT32 absaddr; BIT16 nbytes; BIT16 rank; }; struct segment { BIT32 orgx, orgy; BIT32 id; BIT16 nstrokes; BIT16 dummy; }; /* * Change the two routines below to accomodate the byte ordering on your * machine! - Joe Dellinger */ #if __BYTE_ORDER == __BIG_ENDIAN void twiddle32 (i32) BIT32 *i32; { BIT32 temp; temp = 0; temp |= 0xFF000000 & ((0x000000FF & *i32) << 24); temp |= 0x00FF0000 & ((0x0000FF00 & *i32) << 8); temp |= 0x0000FF00 & ((0x00FF0000 & *i32) >> 8); temp |= 0x000000FF & ((0xFF000000 & *i32) >> 24); *i32 = temp; } void twiddle16 (i16) BIT16 *i16; { BIT16 temp; temp = 0; temp |= 0xFF00 & ((0x00FF & *i16) << 8); temp |= 0x00FF & ((0xFF00 & *i16) >> 8); *i16 = temp; } #else void twiddle32 (i32) BIT32 *i32; { } void twiddle16 (i16) BIT16 *i16; { } #endif void fpr2(FILE * f, BIT32 n) { fprintf(f, "%c%c", n&255, (n>>8)&255); } void fpr3(FILE * f, BIT32 n) { fprintf(f, "%c%c%c", n&255, (n>>8)&255, (n>>16)&255); } void fpr4(FILE * f, BIT32 n) { fprintf(f, "%c%c%c%c", n&255, (n>>8)&255, (n>>16)&255, n>>24); } void prascii(int u, int v, int text_output_type) { if (text_output_type == INT) printf("%7d %7d\n", u, v); else if (text_output_type == REAL) printf("%3.6f %3.6f\n", (double)u/3600.0, (double)v/3600.0); else if (text_output_type == BOTH) printf("%7d %7d | %3.6f %3.6f\n", u, v, (double)u/3600.0, (double)v/3600.0); } void usage() { fprintf(stderr, "Usage: cbd2else [-datadir name] [-outdir name] [-numseg number]\n" " [-format type] [-ascii type]\n" "where format type is one of NONE (default), TEXT, REZ, JPD,\n" "and TEXT ascii type is one of DXDY (default), INT, REAL\n\n"); exit(-1); } int main (argc, argv) int argc; char **argv; { FILE * fi, * fh, * fd; char filename[512]; char * data_dir = NULL, * out_dir = NULL; char magic[20]; int dx[20000], dy[20000]; int Ifile; int u, v, w, j, k, oln, olt, idx, idy, rejected, text_output_type; int format, numseg, totalseg, addr, maxlength, maxwidth, maxheight; #if DEBUG int w1, w2, z1, z2; #endif int segbufsize, segcount, jstroke, iseg, ignore; char *cont_name[] = { "africa", "asia", "europe", "namer", "samer" }; char *type_name[] = { "bdy", "pby", "riv", "cil" }; int rez_type_code[4] = { 2, 0, 1, 3 }; char *comment[3] = { "((int) lat, long)", "(lat, long °decimal)", "((int) lat, long | lat, long °)" }; #define U -1 char targets[4][20]; int jpd_encod[4][16] = { { U, 0, 1, 2, U, U, U, U, U, U, U, U, U, U, U, U }, { U, 3, U, 4, U, U, U, U, U, U, U, U, U, U, U, U }, { U, 5, 6, 7, 8, 9, 10, 11, 12, U, 13, 14, U, 15, U, U }, { U, 16, 17, 18, 19, U, 20, 21, 22, 23, 24, U, U, 25, 26, 27 } }; int jpd_min[4] = { 0, 3, 5, 16 }; int jpd_max[4] = { 2, 4, 15, 27 }; int jpd_seg_count[5][28]; BIT32 i32; BIT16 *segbuf; struct cbdhead header; struct segdict *sd, *sdbuf; struct segment sb; #if __BYTE_ORDER == __BIG_ENDIAN fprintf(stderr, "Detected bigendian processor...\n"); #endif /* * Parse options */ format = TEXT; totalseg = TOTALSEG; text_output_type = REAL; for (j=1; jsegid)); twiddle32 (&(sd->maxlat)); twiddle32 (&(sd->minlat)); twiddle32 (&(sd->maxlong)); twiddle32 (&(sd->minlong)); twiddle32 (&(sd->absaddr)); twiddle16 (&(sd->nbytes)); twiddle16 (&(sd->rank)); if (format==JPD) { if (jpd_encod[v][sd->rank]!=w) continue; } lseek (Ifile, sd->absaddr, L_SET); read (Ifile, &sb, sizeof sb); twiddle32 (&(sb.orgx)); twiddle32 (&(sb.orgy)); twiddle32 (&(sb.id)); twiddle16 (&(sb.nstrokes)); if (sd->nbytes > segbufsize) { fprintf (stderr, "Segment %d needs %d bytes; buffer limit is %d.\n", iseg, sd->nbytes, segbufsize); close (Ifile); free (sdbuf); free (segbuf); return -1; } read (Ifile, segbuf, sd->nbytes); k = 0; oln = sb.orgx; olt = sb.orgy; if (format == TEXT) { printf("Continent [%s], type [%s]\n", cont_name[u], type_name[v]); printf("segid = %d\n", sd->segid); /* printf("sb.id = %d\n", sb.id); */ printf("minlat = %d\n", sd->minlat); printf("maxlat = %d\n", sd->maxlat); printf("minlong = %d\n", sd->minlong); printf("maxlong = %d\n", sd->maxlong); printf("absaddr = %d\n", sd->absaddr); printf("nbytes = %d\n", sd->nbytes); printf("rank = %d\n", sd->rank); printf("nstrokes = %d %s\n", sb.nstrokes, comment[text_output_type]); prascii(olt, oln, text_output_type); } ignore = 0; for (jstroke = 1; jstroke <= sb.nstrokes; jstroke++) { twiddle16 (&segbuf[k]); 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; else idx &= ~SHORTFLAG; #if DEBUG w1 = idx; #endif twiddle16 (&segbuf[k]); /* Modification by J.-P. Demailly to correct calculation of cobal data for which there is a big jump from longitude -180 to longitude +180 Notice that 14720 = 20*65536-1296000 where 1296000=360*60*60 */ if (idx==19) idx = 14720 + segbuf[k]; else if (idx==-20) idx = segbuf[k] - 14720; else idx = (idx << 16) | segbuf[k]; #if DEBUG w2 = segbuf[k]; #endif k++; twiddle16 (&segbuf[k]); idy = segbuf[k]; #if DEBUG z1 = idy; #endif k++; if (idy < 0) idy |= SHORTFLAG; twiddle16 (&segbuf[k]); #if DEBUG z2 = segbuf[k]; #endif idy = (idy << 16) | segbuf[k]; k++; if (abs(idx)>8000 || abs(idy)>8000) { #if DEBUG fprintf(stderr, "Segment %d, index %d : %d %d !!! %d %d %d %d\n", iseg, jstroke, idx, idy, w1, w2, z1, z2); #endif ignore = 1; } } dx[jstroke] = idx; dy[jstroke] = idy; oln = oln + idx; olt = olt + idy; if (format == TEXT) prascii(olt, oln, text_output_type); } if (ignore) { ++rejected; continue; } targets[v][sd->rank] = '1'; if (format == REZ) { fpr4(fh, sd->maxlat); fpr4(fh, sd->minlat); fpr4(fh, sd->maxlong); fpr4(fh, sd->minlong); fpr4(fh, addr); fpr4(fh, 1<rank); addr += 12 + 8*sb.nstrokes; fpr4(fd, sb.orgx); fpr4(fd, sb.orgy); fpr4(fd, sb.nstrokes); for (jstroke = 1; jstroke <= sb.nstrokes; jstroke++) { fpr4(fd, dx[jstroke]); fpr4(fd, dy[jstroke]); } } if (format == JPD) { int dm, count, quot, xp, yp, xt, yt, s; jpd_seg_count[u][w] += 1; /* if (jpd_seg_count[u][w]%100==0) fprintf(stderr, "Reached seg[%d,%d] = %d\n", u, w, jpd_seg_count[u][w]); */ fpr3(fd, sb.orgx); fpr3(fd, sb.orgy); count = 0; for (jstroke = 1; jstroke <= sb.nstrokes; jstroke++) { dm = dx[jstroke]; if (dm<0) dm = -dm; if (dy[jstroke]>dm) dm = dy[jstroke]; if (-dy[jstroke]>dm) dm = -dy[jstroke]; if (dm<128) { fprintf(fd, "%c%c", (dx[jstroke])&255, (dy[jstroke])&255 ); ++count; } else { quot = 1+(dm/128); xp = yp = 0; for (s=1; s<=quot; s++) { xt = xp; yt = yp; xp = (s*dx[jstroke])/quot; yp = (s*dy[jstroke])/quot; fprintf(fd, "%c%c", (xp-xt)&255, (yp-yt)&255 ); } count += quot; } } fpr3(fh, sd->minlong); fpr3(fh, sd->maxlong); fpr3(fh, sd->minlat); fpr3(fh, sd->maxlat); addr += 6+2*count; fpr4(fh, addr); } numseg += 1; if (sb.nstrokes>maxlength) maxlength = sb.nstrokes; i32 = sd->maxlong-sd->minlong; if (i32>maxwidth) maxwidth = i32; i32 = sd->maxlat-sd->minlat; if (i32>maxheight) maxheight = i32; } close (Ifile); free (sdbuf); free (segbuf); } if (format == REZ) { fclose(fh); fclose(fd); } if (format == JPD) { fclose(fh); fclose(fd); } if (format==JPD) { int count = 0; fpr4(fi, maxlength); for (u=0; u<5; u++) for (w=0; w<28; w++) { count += jpd_seg_count[u][w]; fpr4(fi, count); fprintf(stderr, "Segment index [cont=%d, type=%d] = %d\n", u, w, count); } fclose(fi); } fprintf(stderr, "Scanned %d segments, %d rejected\n", numseg, rejected); fprintf(stderr, "Max length of segments %d\n", maxlength); fprintf(stderr, "Max width of segments %d\n", maxwidth); fprintf(stderr, "Max height of segments %d\n", maxheight); for (v=0; v<4; v++) fprintf(stderr, "%s : %s\n", type_name[v], targets[v]); return 0; }