#include <xsimple.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <geolib/cproj.h>
#include "mapview.h"
#include "e00.h"
static E00MAP *map;
static POLY *polys;
static void utm2geo(double *lon, double *lat)
{
double xm = *lon, ym = *lat;
if (invtrans[UTM](xm, ym, lon, lat))
exit(1);
*lon *= R2D; *lat *= R2D;
}
static void clipcoord(double *lat, double *lon)
{
if (*lat < minlat) *lat = minlat;
if (*lat > maxlat) *lat = maxlat;
if (*lon < minlon) *lon = minlon;
if (*lon > maxlon) *lon = maxlon;
}
void drawe00(E00MAP *map, unsigned long (*getiscolor)(),
unsigned long (*getfillcolor)())
{
static XPoint p[MAXPOINTS];
ARC *arc;
POLY *ply;
int i, j, np;
unsigned long fillcolor, iscolor;
if (map->fillcolor == -1)
goto lines;
iscolor = bgcolor;
if (getiscolor)
iscolor = getiscolor(map);
for (ply = map->polys; ply; ply = ply->next) {
if (ply->minlat > maxlat || ply->maxlat < minlat ||
ply->minlon > maxlon || ply->maxlon < minlon)
continue;
fillcolor = map->fillcolor;
if (getfillcolor)
fillcolor = getfillcolor(map, ply);
np = 0;
for (i = 0; i < ply->narcs; i++) {
if (ply->arcids[i] == 0) {
if (np) {
if (np > 1)
fillpoly(p, np, fillcolor);
else
pset(p[0].x, p[0].y, fillcolor);
}
arc = map->arcs[abs(ply->arcids[++i]) - 1];
np = 0;
if (ply->arcids[i] < 0) {
for (j = arc->nnodes - 1; j > -1; j--) {
double lat = arc->nodes[j].lat;
double lon = arc->nodes[j].lon;
clipcoord(&lat, &lon);
ll2xy(lon, lat, &(p[np].x), &(p[np].y));
np++;
}
} else {
for (j = 0; j < arc->nnodes; j++) {
double lat = arc->nodes[j].lat;
double lon = arc->nodes[j].lon;
clipcoord(&lat, &lon);
ll2xy(lon, lat, &(p[np].x), &(p[np].y));
np++;
}
}
if (np > 1)
fillpoly(p, np, iscolor);
else
pset(p[0].x, p[0].y, iscolor);
arc->done = TRUE;
np = 0;
continue;
}
arc = map->arcs[abs(ply->arcids[i]) - 1];
if (ply->arcids[i] < 0) {
for (j = arc->nnodes - 1; j > -1; j--) {
double lat = arc->nodes[j].lat;
double lon = arc->nodes[j].lon;
clipcoord(&lat, &lon);
ll2xy(lon, lat, &(p[np].x), &(p[np].y));
np++;
}
} else {
for (j = 0; j < arc->nnodes; j++) {
double lat = arc->nodes[j].lat;
double lon = arc->nodes[j].lon;
clipcoord(&lat, &lon);
ll2xy(lon, lat, &(p[np].x), &(p[np].y));
np++;
}
}
arc->done = TRUE;
}
if (np) {
if (np > 1)
fillpoly(p, np, fillcolor);
else
pset(p[0].x, p[0].y, fillcolor);
}
}
lines:
setlinewidth(map->width);
for (i = 0; i < map->narcs; i++) {
arc = map->arcs[i];
if (arc->done)
continue;
np = 0;
for (j = 0; j < arc->nnodes; j++) {
if (arc->nodes[j].lat < minlat || arc->nodes[j].lat > maxlat ||
arc->nodes[j].lon < minlon || arc->nodes[j].lon > maxlon) {
if (np) {
if (np > 1)
poly(p, np, map->color);
else
pset(p[0].x, p[0].y, map->color);
}
np = 0;
continue;
}
ll2xy(arc->nodes[j].lon, arc->nodes[j].lat, &(p[np].x), &(p[np].y));
np++;
}
if (np) {
if (np > 1)
poly(p, np, map->color);
else
pset(p[0].x, p[0].y, map->color);
}
}
}
static void parsearc(FILE *f, int prec)
{
char s[100];
int na = 0;
for (;;) {
ARC *arc;
int cnum, cid, fnode, tnode, lpoly, rpoly, nnodes;
double lon1, lat1, lon2, lat2;
int i, nn;
fgets(s, 100, f);
sscanf(s, "%d %d %d %d %d %d %d", &cnum, &cid, &fnode, &tnode,
&lpoly, &rpoly, &nnodes);
if (cnum == -1)
break;
arc = (ARC *)malloc(sizeof(ARC));
arc->nodes = (NODE *)malloc(nnodes * sizeof(NODE));
arc->nnodes = nnodes;
arc->done = FALSE;
nn = 0;
for (i = 0; i < nnodes / ((prec == 2) ? 2 : 1); i++) {
fgets(s, 100, f);
if (prec == 2)
sscanf(s, "%lf %lf %lf %lf", &lon1, &lat1, &lon2, &lat2);
else
sscanf(s, "%lf %lf", &lon1, &lat1);
arc->nodes[nn].lon = lon1;
arc->nodes[nn].lat = lat1;
nn++;
if (prec == 2) {
arc->nodes[nn].lon = lon2;
arc->nodes[nn].lat = lat2;
nn++;
}
}
if (prec == 2 && (nnodes % 2)) {
fgets(s, 100, f);
sscanf(s, "%lf %lf", &lon1, &lat1);
arc->nodes[nn].lon = lon1;
arc->nodes[nn].lat = lat1;
nn++;
}
map->arcs[na++] = arc;
}
map->narcs = na;
}
static void parsepal(FILE *f)
{
char s[100];
POLY *ply, *prevply;
int na, np;
int first = TRUE;
polys = prevply = NULL;
np = 0;
for (;;) {
int narcs;
double xmin, ymin, xmax, ymax;
int a1id, a1fnode, a1ap, a2id, a2fnode, a2ap;
int i;
fgets(s, 100, f);
sscanf(s, "%d %lf %lf %lf %lf", &narcs, &xmin, &ymin, &xmax, &ymax);
if (narcs == -1)
break;
/* Skip universal polygon */
if (first) {
for (i = 0; i < narcs / 2; i++)
fgets(s, 100, f);
if (narcs % 2)
fgets(s, 100, f);
first = FALSE;
continue;
}
ply = (POLY *)malloc(sizeof(POLY));
ply->arcids = (int *)malloc(narcs * sizeof(int));
ply->minlat = ymin; ply->maxlat = ymax;
ply->minlon = xmin; ply->maxlon = xmax;
na = 0;
for (i = 0; i < narcs / 2; i++) {
fgets(s, 100, f);
sscanf(s, "%d %d %d %d %d %d", &a1id, &a1fnode, &a1ap,
&a2id, &a2fnode, &a2ap);
ply->arcids[na++] = a1id;
ply->arcids[na++] = a2id;
}
if (narcs % 2) {
fgets(s, 100, f);
sscanf(s, "%d %d %d", &a1id, &a1fnode, &a1ap);
ply->arcids[na++] = a1id;
}
ply->narcs = na;
ply->next = NULL;
if (! polys)
polys = ply;
if (prevply)
prevply->next = ply;
prevply = ply;
np++;
}
map->polys = polys;
map->npolys = np;
}
static void parseprj(FILE *f)
{
char s[100];
char label[50];
char proj[50], datum[50], zunits[50], units[50], spheroid[50];
int zone;
double xshift, yshift;
long outdatum = 0, indatum = 0;
long iflag;
int i;
for (;;) {
fgets(s, 100, f);
if (! strncmp(s, "EOP", 3))
break;
if (! strncmp(s, "Projection", 10)) {
sscanf(s, "%s %s", label, proj);
if (! strcmp(proj, "GEOGRAPHIC"))
map->proj = PROJ_GEO;
else if (! strcmp(proj, "UTM"))
map->proj = PROJ_UTM;
else {
fprintf(stderr, "Unsupported projection type\n");
exit(1);
}
continue;
}
if (! strncmp(s, "Zone", 4)) {
sscanf(s, "%s %d", label, &zone);
continue;
}
if (! strncmp(s, "Datum", 5)) {
sscanf(s, "%s %s", label, datum);
continue;
}
if (! strncmp(s, "Zunits", 6)) {
sscanf(s, "%s %s", label, zunits);
continue;
}
if (! strncmp(s, "Units", 5)) {
sscanf(s, "%s %s", label, units);
if (map->proj == PROJ_GEO && strcmp(units, "DD")) {
fprintf(stderr, "Unsupported unit `%s' for "
"GEOGRAPHIC projection\n", units);
exit(1);
} else if (map->proj == PROJ_UTM && strcmp(units, "METERS")) {
fprintf(stderr, "Unsupported unit `%s' for "
"UTM projection\n", units);
exit(1);
}
continue;
}
if (! strncmp(s, "Spheroid", 8)) {
sscanf(s, "%s %s", label, spheroid);
if (! strcmp(spheroid, "CLARKE1866"))
outdatum = indatum = 0;
else if (! strcmp(spheroid, "BESSEL"))
outdatum = indatum = 2;
else if (! strcmp(spheroid, "GRS1980"))
outdatum = indatum = 8;
else if (! strcmp(spheroid, "WGS84"))
outdatum = indatum = 12;
else {
fprintf(stderr, "Unsupported spheroid\n");
exit(1);
}
continue;
}
if (! strncmp(s, "Xshift", 6)) {
sscanf(s, "%s %lf", label, &xshift);
continue;
}
if (! strncmp(s, "Yshift", 6)) {
sscanf(s, "%s %lf", label, &yshift);
continue;
}
}
for_init(PROJECT, 0, outparm, outdatum, NULL, NULL, &iflag, fortrans);
if (iflag)
exit(1);
if (map->proj == PROJ_UTM) {
ARC *arc;
POLY *ply;
for (i = 0; i < 15; i++)
inparm[i] = 0.;
inv_init(UTM, zone, inparm, indatum, NULL, NULL, &iflag, invtrans);
if (iflag)
exit(1);
for (i = 0; i < map->narcs; i++) {
int j;
arc = map->arcs[i];
for (j = 0; j < arc->nnodes; j++)
utm2geo(&(arc->nodes[j].lon), &(arc->nodes[j].lat));
}
for (ply = map->polys; ply; ply = ply->next) {
utm2geo(&(ply->minlon), &(ply->minlat));
utm2geo(&(ply->maxlon), &(ply->maxlat));
}
} else {
inv_init(PROJECT, 0, inparm, indatum, NULL, NULL, &iflag, invtrans);
if (iflag)
exit(1);
}
}
E00MAP *loade00(char *fname, unsigned long color, unsigned long fillcolor,
int width, void (*parseaat)(), void (*parsepat)())
{
FILE *f;
char s[100];
int arcdone = FALSE, paldone = FALSE, prjdone = FALSE, aatdone = FALSE,
patdone = FALSE;
char *covname;
if (! (f = fopen(fname, "r"))) {
perror("fopen");
exit(1);
}
fgets(s, 100, f);
if (strncmp(s, "EXP", 3)) {
fprintf(stderr, "Not an Arc/Info export format file\n");
exit(1);
}
map = (E00MAP *)malloc(sizeof(E00MAP));
map->narcs = 0;
map->polys = NULL;
while (fgets(s, 100, f)) {
char arc[5];
int prec;
if ((! arcdone) && (! strncmp(s, "ARC", 3))) {
sscanf(s, "%s %d", arc, &prec);
parsearc(f, prec); arcdone++;
}
if ((! paldone) && (! strncmp(s, "PAL", 3))) {
parsepal(f); paldone++;
}
if ((! prjdone) && (! strncmp(s, "PRJ", 3))) {
parseprj(f); prjdone++;
}
if (parseaat && (! aatdone) && strstr(s, ".AAT")) {
parseaat(f, s, map); aatdone++;
}
if (parsepat && (! patdone) && strstr(s, ".PAT")) {
parsepat(f, s, map); patdone++;
}
}
fclose(f);
map->type = E00;
map->color = color;
map->fillcolor = fillcolor;
map->width = width;
if (! (covname = strrchr(fname, '/')))
covname = fname;
else
covname++;
*(strchr(covname, '.')) = '\0';
map->covname = (char *)malloc(strlen(covname) + 1);
strcpy(map->covname, covname);
map->next = NULL;
return map;
}