2000 #include #include #include #include #include #include #include #include #include #include #include "mapview.h" #include "wdbii.h" #include "mapgen.h" LOCATION *locs; static int nlocs; static MAP *namer_cil, *namer_riv, *namer_bdy, *namer_pby, *samer_cil, *samer_riv, *samer_bdy, *europe_cil, *europe_riv, *europe_bdy, *africa_cil, *africa_riv, *africa_bdy, *asia_cil, *asia_riv, *asia_bdy; static EXTMAP *extmaps = NULL; static int feat = 1; static int do_points = DO_POINTS; static char do_grid = DO_GRID; static double grid_deg; static char do_labels = DO_LABELS; static unsigned long bgcolor; static unsigned long color[4][15]; static int width[4][15]; long (*fortrans[MAXPROJ + 1])(double, double, double *, double *); long (*invtrans[MAXPROJ + 1])(double, double, double *, double *); double clat = 0, clon = 0; int cx, cy; double zoom = 1; double scale; static double minlat, maxlat, minlon, maxlon; static XFontStruct *fs, *gfs, *lfs; static char ls[512]; static void setfeat(void) { if (zoom == 1) feat = 1; else if (zoom == 2) feat = 1; else if (zoom == 4) feat = 2; else if (zoom == 8) feat = 2; else if (zoom == 16) feat = 3; else if (zoom == 32) feat = 4; else feat = 15; } static void getminmax(void) { double xm, ym, maxxm, maxym; if (fortrans[PROJECT](180. * D2R, 89.5 * D2R, &maxxm, &maxym)) exit(1); xm = X2XM(0); ym = Y2YM(WIN_H - TEXT_HEIGHT); if (fabs(xm) > maxxm) xm = (xm < 0) ? -maxxm : maxxm; if (fabs(ym) > maxym) ym = (ym < 0) ? -maxym : maxym; if (invtrans[PROJECT](xm, ym, &minlon, &minlat)) exit(1); minlon = (float)(minlon * R2D); minlat = (float)(minlat * R2D); xm = X2XM(WIN_W); ym = Y2YM(0); if (fabs(xm) > maxxm) xm = (xm < 0) ? -maxxm : maxxm; if (fabs(ym) > maxym) ym = (ym < 0) ? -maxym : maxym; if (invtrans[PROJECT](xm, ym, &maxlon, &maxlat)) exit(1); maxlon = (float)(maxlon * R2D); maxlat = (float)(maxlat * R2D); } static void drawlabels(void) { LOCATION *loc; struct xy { int x, y; } *xy; int i; xy = (struct xy *)malloc(nlocs * sizeof(struct xy)); setfont(lfs); loc = locs; for (i = 0; i < nlocs; i++) { if (loc->lat < minlat || loc->lat > maxlat || loc->lon < minlon || loc->lon > maxlon || loc->showzoom > zoom) { xy[i].x = -1000; loc = loc->next; continue; } xy[i].x = XM2X(loc->xm); xy[i].y = YM2Y(loc->ym); loc = loc->next; } for (i = 0; i < nlocs; i++) { if (xy[i].x == -1000) continue; fillellipse(xy[i].x - 3, xy[i].y - 3, 6, 6, LABEL_DOTCOLOR); ellipse(xy[i].x - 3, xy[i].y - 3, 6, 6, BLACK); } loc = locs; for (i = 0; i < nlocs; i++) { if (xy[i].x == -1000) { loc = loc->next; continue; } imgstring(xy[i].x + LABEL_X, xy[i].y + LABEL_Y, loc->name, LABEL_BGCOLOR, LABEL_FGCOLOR); loc = loc->next; } free(xy); } static void drawgrid(void) { double lon, lat = 0., xm, ym; int x, y; char s[80]; setfont(gfs); setlinewidth(GRID_WIDTH); for (lon = -180.; lon <= 180.; lon += grid_deg) { if (lon < minlon) continue; if (lon > maxlon) break; if (fortrans[PROJECT](lon * D2R, lat * D2R, &xm, &ym)) exit(1); x = XM2X(xm); line(x, 0, x, (WIN_H - 1) - TEXT_HEIGHT, GRID_COLOR); sprintf(s, "%g", lon); string(x + GS_LONX, GS_LONY, s, GTEXT_COLOR); } for (lat = -89.5; lat <= 89.5; lat += (lat == -89.5) ? grid_deg - (double)(grid_deg >= 1.) * .5 : grid_deg) { if (lat == -89.5 || lat < minlat) continue; if (lat > maxlat) break; if (fortrans[PROJECT](lon * D2R, lat * D2R, &xm, &ym)) exit(1); y = YM2Y(ym); line(0, y, WIN_W - 1, y, GRID_COLOR); sprintf(s, "%g", lat); string(GS_LATX, y + GS_LATY, s, GTEXT_COLOR); } } static void drawextmap(EXTMAP *map) { static XPoint p[MAXPOINTS]; MAPREC *rec; setlinewidth(map->width); for (rec = map->recs; rec; rec = rec->next) { int i; if (rec->minlat > maxlat || rec->maxlat < minlat || rec->minlon > maxlon || rec->maxlon < minlon) continue; for (i = 0; i < rec->npts; i++) { p[i].x = XM2X(rec->pts[i].xm); p[i].y = YM2Y(rec->pts[i].ym); } if (rec->npts > 1) poly(p, rec->npts, map->color); else pset(p[0].x, p[0].y, map->color); } } static void drawmap(MAP *map) { static XPoint p[MAXPOINTS]; MAPREC *rec; int forcewidth = -1; int type = map->type; switch (map->type) { case CIL: if (zoom <= CIL_FWZOOM) forcewidth = 1; break; case RIV: if (zoom <= RIV_FWZOOM) forcewidth = 1; break; case BDY: if (zoom <= BDY_FWZOOM) forcewidth = 1; break; case PBY: if (zoom <= PBY_FWZOOM) forcewidth = 1; break; } if (forcewidth != -1) setlinewidth(forcewidth); for (rec = map->recs; rec; rec = rec->next) { int i; if (rec->rank > feat) continue; if (rec->minlat > maxlat || rec->maxlat < minlat || rec->minlon > maxlon || rec->maxlon < minlon) continue; for (i = 0; i < rec->npts; i++) { p[i].x = XM2X(rec->pts[i].xm); p[i].y = YM2Y(rec->pts[i].ym); } if (rec->npts > 1) { if (forcewidth == -1) setlinewidth(width[type][(int)(rec->rank - 1)]); poly(p, rec->npts, color[type][(int)(rec->rank - 1)]); } else pset(p[0].x, p[0].y, color[type][(int)(rec->rank - 1)]); } } void drawmaps(void) { double xm, ym; char cs[40]; if (fortrans[PROJECT](clon * D2R, clat * D2R, &xm, &ym)) exit(1); cx = (int)(xm * scale * zoom); cy = (int)(ym * scale * zoom); getminmax(); cls(bgcolor); if (extmaps) { EXTMAP *map; for (map = extmaps; map; map = map->next) drawextmap(map); goto grid; } if (do_points & DO_NAMER) { if (do_points & DO_CIL) drawmap(namer_cil); if (do_points & DO_RIV) drawmap(namer_riv); if (do_points & DO_BDY) { drawmap(namer_bdy); drawmap(namer_pby); } } if (do_points & DO_SAMER) { if (do_points & DO_CIL) drawmap(samer_cil); if (do_points & DO_RIV) drawmap(samer_riv); if (do_points & DO_BDY) drawmap(samer_bdy); } if (do_points & DO_EUROPE) { if (do_points & DO_CIL) drawmap(europe_cil); if (do_points & DO_RIV) drawmap(europe_riv); if (do_points & DO_BDY) drawmap(europe_bdy); } if (do_points & DO_AFRICA) { if (do_points & DO_CIL) drawmap(africa_cil); if (do_points & DO_RIV) drawmap(africa_riv); if (do_points & DO_BDY) drawmap(africa_bdy); } if (do_points & DO_ASIA) { if (do_points & DO_CIL) drawmap(asia_cil); if (do_points & DO_RIV) drawmap(asia_riv); if (do_points & DO_BDY) drawmap(asia_bdy); } grid: if (do_grid) drawgrid(); if (do_labels) drawlabels(); fillrect(0, WIN_H - TEXT_HEIGHT, WIN_W, TEXT_HEIGHT, TEXT_BGCOLOR); setfont(fs); string(LS_X, LCS_Y, ls, TEXT_COLOR); sprintf(cs, "%8.3f %8.3f", clat, clon); string(CS_X, LCS_Y, cs, TEXT_COLOR); update(0, 0, 0, 0); } static void loadmaps(int argc, char **argv) { char *names[] = { "namer/cil", "namer/riv", "namer/bdy", "namer/pby", "samer/cil", "samer/riv", "samer/bdy", "europe/cil", "europe/riv", "europe/bdy", "africa/cil", "africa/riv", "africa/bdy", "asia/cil", "asia/riv", "asia/bdy", NULL }; MAP **maps[] = { &namer_cil, &namer_riv, &namer_bdy, &namer_pby, &samer_cil, &samer_riv, &samer_bdy, &europe_cil, &europe_riv, &europe_bdy, &africa_cil, &africa_riv, &africa_bdy, &asia_cil, &asia_riv, &asia_bdy }; char *name; int i; if (argc > 1) { EXTMAP *map, *prevmap = NULL; for (i = 1; i < argc; i++) { char fname[512], *p1, *p2; unsigned long color; int width; strcpy(fname, argv[i]); if 2000 (! (p1 = strchr(fname, ':'))) { fprintf(stderr, "Invalid argument\n"); exit(1); } *(p1++) = '\0'; if (! (p2 = strchr(p1, ':'))) { fprintf(stderr, "Invalid argument\n"); exit(1); } *(p2++) = '\0'; color = getnamedcolor(p1, NULL); width = atoi(p2); map = loadmapgen(fname, color, width); if (! extmaps) extmaps = map; if (prevmap) prevmap->next = map; prevmap = map; } return; } for (i = 0; (name = names[i]); i++) *(maps[i]) = loadwdbii(names[i]); } static void drawis(char *s) { fillrect(CS_X, WIN_H - TEXT_HEIGHT, WIN_W - CS_X, TEXT_HEIGHT, TEXT_BGCOLOR); string(CS_X, LCS_Y, s, TEXT_COLOR); update(CS_X, WIN_H - TEXT_HEIGHT, WIN_W - CS_X, TEXT_HEIGHT); } static int parseis(KeySym ks) { static char is[80], *p = NULL; static int mode; double tlat, tlon; if (! p) { if (ks == XK_c || ks == XK_d) { memset(is, 0, sizeof(is)); p = is; fillrect(CS_X, WIN_H - TEXT_HEIGHT, WIN_W - CS_X, TEXT_HEIGHT, TEXT_BGCOLOR); update(CS_X, WIN_H - TEXT_HEIGHT, WIN_W - CS_X, TEXT_HEIGHT); mode = (ks == XK_c) ? 0 : 1; return 1; } else return 0; } if (ks >= XK_0 && ks <= XK_9) { *(p++) = '0' + (ks - XK_0); drawis(is); return 1; } switch (ks) { case XK_period: *(p++) = '.'; drawis(is); return 1; case XK_minus: *(p++) = '-'; drawis(is); return 1; case XK_space: *(p++) = ' '; drawis(is); return 1; case XK_BackSpace: if (p > is) { *(--p) = '\0'; drawis(is); } return 1; case XK_Return: if (mode == 0) { if (sscanf(is, "%lf %lf", &tlat, &tlon) == 2) { if (tlat >= -89.5 && tlat <= 89.5 && tlon >= -180. && tlon <= 180.) { clat = tlat; clon = tlon; } } } else { double tmp = atof(is); if (tmp > 0.) grid_deg = tmp; } drawmaps(); p = NULL; return 1; default: return 0; } } static void parselocs(char *s) { char *tmp, *p; LOCATION *loc, *prevloc = NULL; tmp = malloc(strlen(s) + 1); strcpy(tmp, s); if (! (p = strtok(tmp, ":"))) goto error; for (;;) { loc = (LOCATION *)malloc(sizeof(LOCATION)); loc->name = (char *)malloc(strlen(p) + 1); strcpy(loc->name, p); if (! (p = strtok(NULL, ":"))) goto error; loc->lat = atof(p); if (! (p = strtok(NULL, ":"))) goto error; loc->lon = atof(p); if (! (p = strtok(NULL, ":"))) goto error; loc->showzoom = atoi(p); if (fortrans[PROJECT](loc->lon * D2R, loc->lat * D2R, &(loc->xm), &(loc->ym))) exit(1); loc->next = NULL; if (! locs) locs = loc; if (prevloc) prevloc->next = loc; prevloc = loc; nlocs++; if (! (p = strtok(NULL, ":"))) break; } free(tmp); return; error: fprintf(stderr, "Invalid location string format\n"); exit(1); } void mapinit(int argc, char **argv) { double outparm[15]; long iflag; double x, y; int i; LOCATION *loc; for (i = 0; i < 15; i++) outparm[i] = 0.; for_init(PROJECT, 0, outparm, 0, NULL, NULL, &iflag, fortrans); if (iflag) exit(1); for (i = 0; i < 15; i++) outparm[i] = 0.; inv_init(PROJECT, 0, outparm, 0, NULL, NULL, &iflag, invtrans); if (iflag) exit(1); if (fortrans[PROJECT](180. * D2R, 89.5 * D2R, &x, &y)) exit(1); scale = ((double)WIN_W / 2) / x; parselocs(LOCATIONS); loc = locs; strcpy(ls, ""); for (i = 0; i < ((nlocs >= 10) ? 10 : nlocs); i++) { int n = (i == 9) ? 0 : i + 1; sprintf(ls, "%s%d %s ", ls, n, loc->name); loc = loc->next; } xinit("mapview", "Mapview", "MapView", WIN_X, WIN_Y, WIN_W, WIN_H, 0, "black", "black", 0); fs = getfont(FONT); gfs = getfont(GRID_FONT); lfs = getfont(LABEL_FONT); setfont(fs); grid_deg = GRID_DEGREES; bgcolor = getnamedcolor("#f8f0e4", NULL); color[CIL][0] = CIL1_COLOR; color[CIL][1] = CIL2_COLOR; color[CIL][2] = CIL3_COLOR; color[CIL][3] = CIL4_COLOR; color[CIL][4] = CIL4_COLOR; color[CIL][5] = CIL5_COLOR; color[CIL][6] = CIL7_COLOR; color[CIL][7] = CIL8_COLOR; color[CIL][8] = CIL9_COLOR; color[CIL][9] = CIL10_COLOR; color[CIL][10] = CIL11_COLOR; color[CIL][11] = CIL12_COLOR; color[CIL][12] = CIL13_COLOR; color[CIL][13] = CIL14_COLOR; color[CIL][14] = CIL15_COLOR; color[RIV][0] = RIV1_COLOR; color[RIV][1] = RIV2_COLOR; color[RIV][2] = RIV3_COLOR; color[RIV][3] = RIV4_COLOR; color[RIV][4] = RIV5_COLOR; color[RIV][5] = RIV6_COLOR; color[RIV][6] = RIV7_COLOR; color[RIV][7] = RIV8_COLOR; color[RIV][8] = RIV9_COLOR; color[RIV][9] = RIV10_COLOR; color[RIV][10] = RIV11_COLOR; color[RIV][11] = RIV12_COLOR; color[BDY][0] = BDY1_COLOR; color[BDY][1] = BDY2_COLOR; color[BDY][2] = BDY3_COLOR; color[PBY][0] = PBY1_COLOR; color[PBY][1] = PBY2_COLOR; color[PBY][2] = PBY3_COLOR; width[CIL][0] = CIL1_WIDTH; width[CIL][1] = CIL2_WIDTH; width[CIL][2] = CIL3_WIDTH; width[CIL][3] = CIL4_WIDTH; width[CIL][4] = CIL4_WIDTH; width[CIL][5] = CIL5_WIDTH; width[CIL][6] = CIL7_WIDTH; width[CIL][7] = CIL8_WIDTH; width[CIL][8] = CIL9_WIDTH; width[CIL][9] = CIL10_WIDTH; width[CIL][10] = CIL11_WIDTH; width[CIL][11] = CIL12_WIDTH; width[CIL][12] = CIL13_WIDTH; width[CIL][13] = CIL14_WIDTH; width[CIL][14] = CIL15_WIDTH; width[RIV][0] = RIV1_WIDTH; width[RIV][1] = RIV2_WIDTH; width[RIV][2] = RIV3_WIDTH; width[RIV][3] = RIV4_WIDTH; width[RIV][4] = RIV5_WIDTH; width[RIV][5] = RIV6_WIDTH; width[RIV][6] = RIV7_WIDTH; width[RIV][7] = RIV8_WIDTH; width[RIV][8] = RIV9_WIDTH; width[RIV][9] = RIV10_WIDTH; width[RIV][10] = RIV11_WIDTH; width[RIV][11] = RIV12_WIDTH; width[BDY][0] = BDY1_WIDTH; width[BDY][1] = BDY2_WIDTH; width[BDY][2] = BDY3_WIDTH; width[PBY][0] = PBY1_WIDTH; width[PBY][1] = PBY2_WIDTH; width[PBY][2] = PBY3_WIDTH; loadmaps(argc, argv); drawmaps(); } int main(int argc, char **argv) { mapinit(argc, argv); for (;;) { XEvent e; while (getevent(&e)) { switch (e.type) { KeySym ks; case Expose: doexpose(&e); break; case KeyPress: ks = XLookupKeysym((XKeyEvent *)&e, 0); if (parseis(ks)) break; if (ks >= XK_0 && ks <= XK_9) { int n = ks - XK_0, i; LOCATION *loc; if (n > nlocs) break; n = (n > 0) ? n - 1 : ((nlocs >= 10) ? 9 : nlocs - 1); loc = locs; for (i = 0; i < n; i++) loc = loc->next; clat = loc->lat; clon = loc->lon; drawmaps(); break; } switch (ks) { case XK_Left: if (clon >= (-180. + (10. / zoom))) { clon -= 10. / zoom; drawmaps(); } break; case XK_Right: if (clon <= (180. - (10. / zoom))) { clon += 10. / zoom; drawmaps(); } break; case XK_Up: if (clat <= (89.5 - (10. / zoom))) { clat += 10. / zoom; drawmaps(); } break; case XK_Down: if (clat >= (-89.5 + (10. / zoom))) { clat -= 10. / zoom; drawmaps(); } break; case XK_Prior: /* Overflows at some point */ zoom *= 2; setfeat(); drawmaps(); break; case XK_Next: if (zoom > 1) { zoom /= 2; setfeat(); drawmaps(); } break; case XK_Home: clat = 0.; clon = 0.; zoom = 1.; setfeat(); drawmaps(); break; case XK_F1: do_points ^= DO_NAMER; drawmaps(); break; case XK_F2: do_points ^= DO_SAMER; drawmaps(); break; case XK_F3: do_points ^= DO_EUROPE; drawmaps(); break; case XK_F4: do_points ^= DO_AFRICA; drawmaps(); break; case XK_F5: do_points ^= DO_ASIA; drawmaps(); break; case XK_F7: do_g 29f rid ^= 1; drawmaps(); break; case XK_F8: do_labels ^= 1; drawmaps(); break; case XK_F9: do_points ^= DO_CIL; drawmaps(); break; case XK_F10: do_points ^= DO_RIV; drawmaps(); break; case XK_F11: do_points ^= DO_BDY; drawmaps(); break; case XK_minus: if (feat > 1) { feat--; drawmaps(); } break; case XK_equal: if (feat < 15) { feat++; drawmaps(); } break; case XK_q: exit(0); break; } break; } } usleep(1000); } } . 0