#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 <geolib/cproj.h>
#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 (! (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_grid ^= 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);
}
}