#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 "config.h"
#include "wdbii.h"
#include "mapgen.h"
#include "e00.h"
#include "dcw.h"
char datadir[1024];
LOCATION *locs;
int nlocs;
MAPARG *mapargs = NULL;
static MAP *maps = NULL;
int dogrid;
int dolabels;
double griddeg;
double movedeg;
char bgcolor_s[80] = "#f8f0e4";
unsigned long bgcolor;
char label_bgcolor_s[80] = "#f8f0e0";
unsigned long label_bgcolor;
double inparm[15], outparm[15];
long (*fortrans[MAXPROJ + 1])(double, double, double *, double *);
long (*invtrans[MAXPROJ + 1])(double, double, double *, double *);
double iminlat, imaxlat, iminlon, imaxlon;
double minlat, maxlat, minlon, maxlon;
double bminlat, bmaxlat, bminlon, bmaxlon;
double clat, clon;
int cx, cy;
unsigned int scale, bscale;
double iscale;
static XFontStruct *fs, *gfs, *lfs;
static char ls[512];
void ftrans(double lon, double lat, double *xm, double *ym)
{
if (fortrans[PROJECT](lon * D2R, lat * D2R, xm, ym))
exit(1);
}
void itrans(double xm, double ym, double *lon, double *lat)
{
if (invtrans[PROJECT](xm, ym, lon, lat))
exit(1);
*lon *= R2D; *lat *= R2D;
}
void ll2xy(double lon, double lat, short *x, short *y)
{
double xm, ym;
if (fortrans[PROJECT](lon * D2R, lat * D2R, &xm, &ym))
exit(1);
*x = XM2X(xm);
*y = YM2Y(ym);
}
static void setscale(void)
{
iscale = PPCM / ((double)scale / 100.);
movedeg = MOVEDEG;
}
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->showscale < scale) {
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, BLACK);
loc = loc->next;
}
free(xy);
}
static void drawgrid(void)
{
XPoint pts[1000];
double lon, lat = 0.;
// char s[80];
int i;
setfont(gfs);
setlinewidth(GRID_WIDTH);
for (lon = -180.; lon <= 180.; lon += griddeg) {
if (lon < minlon || lon > maxlon)
continue;
for (lat = minlat, i = 0; lat <= maxlat; lat++, i++)
ll2xy(lon, lat, &(pts[i].x), &(pts[i].y));
poly(pts, i, GRID_COLOR);
// sprintf(s, "%g", lon);
// string(x + GS_LONX, GS_LONY, s, GTEXT_COLOR);
}
for (lat = -90.; lat <= 90.; lat += griddeg) {
if (lat < minlat || lat > maxlat)
continue;
for (lon = minlon, i = 0; lon <= maxlon; lon++, i++)
ll2xy(lon, lat, &(pts[i].x), &(pts[i].y));
poly(pts, i, GRID_COLOR);
// sprintf(s, "%g", lon);
// string(x + GS_LONX, GS_LONY, s, GTEXT_COLOR);
}
}
void drawmaps(void)
{
double xm, ym;
char cs[40], ss[40], rs[50];
MAP *map;
ftrans(clon, clat, &xm, &ym);
cx = (int)(xm * iscale);
cy = (int)(ym * iscale);
cls(bgcolor);
for (map = maps; map; map = map->next) {
switch (map->type) {
case MAPGEN:
drawmapgen((MGMAP *)map);
break;
case WDBII:
drawwdbii((WDBMAP *)map);
break;
case E00:
drawe00((E00MAP *)map, NULL, NULL);
break;
case DCW:
drawdcw((E00MAP *)map);
break;
}
}
if (dogrid)
drawgrid();
if (dolabels)
drawlabels();
fillrect(0, 0, WIN_W, TEXT_HEIGHT, TEXT_BGCOLOR);
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);
sprintf(ss, "Scale: 1:%u", scale);
string(SS_X, SRS_Y, ss, TEXT_COLOR);
sprintf(rs, "Region: %g %g %g %g", minlat, maxlat, minlon, maxlon);
string(RS_X, SRS_Y, rs, TEXT_COLOR);
update(0, 0, 0, 0);
}
static void loadmaps(void)
{
if (mapargs) {
MAPARG *arg;
MAP *map = NULL, *prevmap = NULL;
for (arg = mapargs; arg; arg = arg->next) {
char tmp[1024], fname[512], color_s[30], fillcolor_s[30];
unsigned long color, fillcolor;
int type, width, r;
strcpy(tmp, arg->data);
r = sscanf(tmp, "%[^:]:%d:%d:%[^:]:%[^:]", fname, &type,
&width, color_s, fillcolor_s);
color = getnamedcolor(color_s, NULL);
fillcolor = -1;
if (r == 5)
fillcolor = getnamedcolor(fillcolor_s, NULL);
switch (type) {
case MAPGEN:
map = (MAP *)loadmapgen(fname, color, fillcolor, width);
break;
case WDBII:
map = (MAP *)loadwdbii(fname, color, fillcolor, width);
break;
case E00:
map = (MAP *)loade00(fname, color, fillcolor, width,
NULL, NULL);
break;
case DCW:
map = (MAP *)loaddcw(fname, color, fillcolor, width);
break;
}
if (! maps)
maps = map;
if (prevmap)
prevmap->next = map;
prevmap = map;
}
return;
}
}
static void drawis(char *s)
{
fillrect(LS_X, WIN_H - TEXT_HEIGHT, WIN_W - LS_X, TEXT_HEIGHT,
TEXT_BGCOLOR);
string(LS_X, LCS_Y, s, TEXT_COLOR);
update(LS_X, WIN_H - TEXT_HEIGHT, WIN_W, 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 || ks == XK_s || ks == XK_r) {
memset(is, 0, sizeof(is));
p = is;
fillrect(LS_X, WIN_H - TEXT_HEIGHT, WIN_W - LS_X, TEXT_HEIGHT,
TEXT_BGCOLOR);
update(LS_X, WIN_H - TEXT_HEIGHT, WIN_W - LS_X, TEXT_HEIGHT);
switch (ks) {
case XK_c: mode = 0; break;
case XK_d: mode = 1; break;
case XK_s: mode = 2; break;
case XK_r: mode = 3; break;
}
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:
switch (mode) {
case 0:
if (sscanf(is, "%lf %lf", &tlat, &tlon) == 2) {
if (tlat >= -89.5 && tlat <= 89.5 &&
tlon >= -180. && tlon <= 180.) {
clat = tlat; clon = tlon;
}
}
break;
case 1: {
double tmp = atof(is);
if (tmp > 0.) griddeg = tmp;
}
break;
case 2: {
double tmp = atof(is);
if (tmp > 0.) { scale = tmp; setscale(); }
}
break;
case 3: {
double tminlat, tmaxlat, tminlon, tmaxlon;
if (sscanf(is, "%lf %lf %lf %lf", &tminlat, &tmaxlat,
&tminlon, &tmaxlon) == 4) {
minlat = tminlat; maxlat = tmaxlat;
minlon = tminlon; maxlon = tmaxlon;
clat = minlat + (maxlat - minlat) / 2;
clon = minlon + (maxlon - minlon) / 2;
}}
break;
}
drawmaps();
p = NULL;
return 1;
default:
return 0;
}
}
void mapinit(int argc, char **argv)
{
char fname[512];
FILE *f;
int i;
LOCATION *loc;
if (argc > 2 && (! strcmp(argv[1], "-c"))) {
if (! (f = fopen(argv[2], "r"))) {
fprintf(stderr, "Can't open configuration file `%s'\n", argv[2]);
exit(1);
}
argc -= 2; argv += 2;
} else {
strcpy(fname, ".mapviewrc");
if (! (f = fopen(fname, "r"))) {
sprintf(fname, "%s/.mapviewrc", getenv("HOME"));
if (! (f = fopen(fname, "r"))) {
fprintf(stderr, "No .mapviewrc found\n");
exit(1);
}
}
}
readconfig(f, argc, argv);
if (! mapargs) {
fprintf(stderr, "No maps defined\n");
exit(1);
}
setscale();
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);
bgcolor = getnamedcolor(bgcolor_s, NULL);
label_bgcolor = getnamedcolor(label_bgcolor_s, NULL);
loadmaps();
for (loc = locs; loc; loc = loc->next)
ftrans(loc->lon, loc->lat, &(loc->xm), &(loc->ym));
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 >= (minlon + movedeg)) {
clon -= movedeg;
drawmaps();
}
break;
case XK_Right:
if (clon <= (maxlon - movedeg)) {
clon += movedeg;
drawmaps();
}
break;
case XK_Up:
if (clat <= (maxlat - movedeg)) {
clat += movedeg;
drawmaps();
}
break;
case XK_Down:
if (clat >= (minlat + movedeg)) {
clat -= movedeg;
drawmaps();
}
break;
case XK_Prior:
/* Overflows at some point */
scale /= 2.;
setscale();
drawmaps();
break;
case XK_Next:
if (scale < 2000000000) {
scale *= 2;
setscale();
drawmaps();
}
break;
case XK_Home:
minlat = bminlat; maxlat = bmaxlat;
minlon = bminlon; maxlon = bmaxlon;
clat = minlat + (maxlat - minlat) / 2;
clon = minlon + (maxlon - minlon) / 2;
scale = bscale;
setscale();
drawmaps();
break;
case XK_F5:
dogrid ^= 1;
drawmaps();
break;
case XK_F6:
dolabels ^= 1;
drawmaps();
break;
case XK_q:
exit(0);
break;
}
break;
}
}
usleep(1000);
}
}