#include <xsimple.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>
#include <math.h>
#include <geolib/cproj.h>
#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;
}
}
usleep(1000);
}
}