2000 #include #include #include #include #include #include #include #include #include #include #include #include "mapview.h" static int do_points = DO_COAST | DO_ISLAND | DO_LAKE | DO_COUNTRY | DO_STATE; LOCATION loc[] = { {"Norrköping", 58.5934, 16.1946}, {"London", 51.533, 0.083}, {"Rome", 41.9, 12.45}, {"Moscow", 55.75, 37.6}, {"L.A.", 34.05, -118.25}, {"New York", 40.783, -73.966}, {"Kingston", 44.25, -76.5}, {"Sydney", -34, 151}, {"Kuala Lumpur", 3.133, 101.7}, {"Tokyo", 35.666, 139.75} }; static int nloc = sizeof(loc) / sizeof(LOCATION); static MAP *coast, *island, *lake, *river, *country, *state; static int detail = DETAIL; long (*fortrans[MAXPROJ + 1])(double, double, double *, double *); static double clat = 0., clon = 0.; static short cx, cy; static double scale; static double zoom = 1; static char ls[512]; static void drawmap(MAP *map, unsigned long color) { static XPoint p[35000]; int i, np = 0; int inside = 0; for (i = 0; i < map->npts; i++) { if (map->pts[i].hdr > 1000) { if (np && inside) { if (np > 1) poly(p, np, color); else pset(p[0].x, p[0].y, color); } inside = 0; np = 0; p[np].x = XM2X(map->pts[i].x); p[np].y = YM2Y(map->pts[i].y); if (p[np].x >= 0 && p[np].x < WIN_W && p[np].y >= 0 && p[np].y < WIN_H) inside++; np++; } else { if (map->pts[i].hdr >= detail) { short xtmp, ytmp; xtmp = XM2X(map->pts[i].x); ytmp = YM2Y(map->pts[i].y); if (abs(xtmp - p[np - 1].x) > WIN_W/2) { if (inside) { if (np > 1) poly(p, np, color); else pset(p[0].x, p[0].y, color); } inside = 0; np = 0; } p[np].x = xtmp; p[np].y = ytmp; if (p[np].x >= 0 && p[np].x < WIN_W && p[np].y >= 0 && p[np].y < WIN_H) inside++; np++; } } } if (inside) { if (np > 1) poly(p, np, color); else pset(p[0].x, p[0].y, color); } } static void drawmaps(void) { double x, y; char cs[40]; if (fortrans[MERCAT](clon * D2R, clat * D2R, &x, &y)) exit(1); cx = (short)(x * scale * zoom); cy = (short)(y * scale * zoom); cls(BGCOLOR); if (do_points & DO_COAST) drawmap(coast, COAST_COLOR); if (do_points & DO_ISLAND) drawmap(island, ISLAND_COLOR); if (do_points & DO_LAKE) drawmap(lake, LAKE_COLOR); if (do_points & DO_RIVER) drawmap(river, RIVER_COLOR); if (do_points & DO_COUNTRY) drawmap(country, COUNTRY_COLOR); if (do_points & DO_STATE) drawmap(state, STATE_COLOR); fillrect(0, WIN_H - TEXT_HEIGHT, WIN_W, TEXT_HEIGHT, TEXT_BGCOLOR); string(LS_X, LS_Y, ls, TEXT_COLOR); sprintf(cs, "%8.3f %8.3f", clat, clon); string(CS_X, CS_Y, cs, TEXT_COLOR); update(0, 0, 0, 0); } static MAP *loadmap(char *name) { char fname[1024]; int fd; struct stat sb; MAP *map; PNTREC *tmp; int i; sprintf(fname, "%s/%s.PNT", DATADIR, name); if ((fd = open(fname, O_RDONLY)) < 0) { perror("open"); exit(1); } if (fstat(fd, &sb) < 0) { perror("stat"); exit(1); } tmp = (PNTREC *)malloc(sb.st_size); read(fd, tmp, sb.st_size); map = (MAP *)malloc(sizeof(MAP)); map->npts = sb.st_size / sizeof(PNTREC); map->pts = (COORDREC *)malloc(map->npts * sizeof(COORDREC)); for (i = 0; i < map->npts; i++) { map->pts[i].hdr = tmp[i].hdr; if (fortrans[MERCAT](((double)tmp[i].lon / 60.) * D2R, ((double)tmp[i].lat / 60.) * D2R, &(map->pts[i].x), &(map->pts[i].y))) exit(1); } free(tmp); close(fd); return map; } static void loadmaps(void) { char *names[] = {"COAST", "ISLAND", "LAKE", "RIVER", "COUNTRY", "STATE", NULL}; MAP **maps[] = {&coast, &island, &lake, &river, &country, &state}; char *name; int i; for (i = 0; (name = names[i]); i++) *(maps[i]) = loadmap(names[i]); } static void drawcs(char *s) { fillrect(CS_X, WIN_H - TEXT_HEIGHT, WIN_W - CS_X, TEXT_HEIGHT, TEXT_BGCOLOR); string(CS_X, CS_Y, s, TEXT_COLOR); update(CS_X, WIN_H - TEXT_HEIGHT, WIN_W - CS_X, TEXT_HEIGHT); } static int parsecs(KeySym ks) { static char cs[80], *p = NULL; double tlat, tlon; if (! p) { if (ks == XK_c) { memset(cs, 0, sizeof(cs)); p = cs; 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); return 1; } else return 0; } if (ks >= XK_0 && ks <= XK_9) { *(p++) = '0' + (ks - XK_0); drawcs(cs); return 1; } switch (ks) { case XK_period: *(p++) = '.'; drawcs(cs); return 1; case XK_minus: *(p++) = '-'; drawcs(cs); return 1; case XK_space: *(p++) = ' '; drawcs(cs); return 1; case XK_BackSpace: if (p > cs) { *(--p) = '\0'; drawcs(cs); } return 1; case XK_Return: if (sscanf(cs, "%lf %lf", &tlat, &tlon) == 2) { if (tlat >= -89.5 && tlat <= 89.5 && tlon >= -180. && tlon <= 180.) { clat = tlat; clon = tlon; } } drawmaps(); p = NULL; return 1; default: return 0; } } void mapinit(void) { double outparm[15]; long iflag; double x, y; int i; XFontStruct *fs; for (i = 0; i < 15; i++) outparm[i] = 0.; for_init(MERCAT, 0, outparm, 0, NULL, NULL, &iflag, fortrans); if (iflag) exit(1); if (fortrans[MERCAT](180. * D2R, 89.5 * D2R, &x, &y)) exit(1); scale = ((double)WIN_W / 2) / x; strcpy(ls, ""); for (i = 0; i < nloc; i++) { int n = (i == nloc - 1) ? 0 : i + 1; sprintf(ls, "%s%d %s ", ls, n, loc[i].name); } xinit("mapview", "Mapview", "MapView", WIN_X, WIN_Y, WIN_W, WIN_H, 0, "black", "black", 0); fs = getfont(FONT); setfont(fs); loadmaps(); drawmaps(); } int main(int argc, char **argv) { mapinit(); for (;;) { XEvent e; while (getevent(&e)) { switch (e.type) { KeySym ks; case Expose: doexpose(&e); break; case KeyPress: ks = XLookupKeysym((XKeyEvent *)&e, 0); if (parsecs(ks)) break; if (ks >= XK_0 && ks <= XK_9) { int n = ks - XK_0; n = (n > 0) ? n - 1 : nloc - 1; clat = loc[n].lat; clon = loc[n].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: if (zoom < 64) { zoom *= 2; drawmaps(); } break; case XK_Next: if (zoom > 1) { zoom /= 2; drawmaps(); } break; case XK_Home: clat = 0.; clon = 0.; zoom = 1.; drawmaps(); break; case XK_F1: do_points ^= DO_LAKE; drawmaps(); break; case XK_F2: do_points ^= DO_RIVER; drawmaps(); break; case XK_F3: do_points ^= DO_COUNTRY; drawmaps(); break; case XK_F4: do_points ^= DO_STATE; drawmaps(); break; case XK_minus: if (detail < 5) { detail++; drawmaps(); } break; case XK_equal: if (detail > 1) { detail--; drawmaps(); } break; case XK_q: exit(0); break; } break; } } us 1a leep(1000); } } . 0