#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <io.h>
#include <winlib/winlib.h>
#include <geolib/cproj.h>
#include <geolib/proj.h>
#include "mapplot.h"
#include "wdb-ii.h"
#include "map.h"
BOOL SetupOtherWorld(VARS *v, HDC hdc)
{
RECT rect;
POINT origPt;
int i;
double outParm[15];
long iFlag;
double lonRad, latRad, x, x2, y;
double extX, extY;
/* Report errors */
init(0, -1, NULL, NULL);
for(i = 0; i < 15; i++)
outParm[i] = 0.;
/*
Mercator:
0, 1 Semi-major/semi-minor axis of ellipsoid
4 Longitude of the central meridian
5 Latitude of true scale
6 False easting in the same units as the semi-major axis
7 False northing in the same units as the semi-major axis
Robinson, Hammer:
0 Sphere
4 Central meridian
6 False easting in the same units as the semi-major axis
7 False northing in the same units as the semi-major axis
Orthographic;
0 Sphere
4 Central longitude
5 Central latitude
6 False easting in the same units as the semi-major axis
7 False northing in the same units as the semi-major axis
*/
for_init(v->project, 0, outParm, 0, NULL, NULL, &iFlag, v->ForTrans);
if (iFlag)
return FALSE;
inv_init(v->project, 0, outParm, 0, NULL, NULL, &iFlag, v->InvTrans);
if (iFlag)
return FALSE;
switch (v->project) {
case MERCAT:
lonRad = 180. * D2R;
latRad = 89.5 * D2R;
if (v->ForTrans[v->project](lonRad, latRad, &x, &y))
return FALSE;
break;
case ROBIN:
case HAMMER:
lonRad = 180. * D2R;
latRad = 0.;
if (v->ForTrans[v->project](lonRad, latRad, &x, &y))
return FALSE;
lonRad = 0.;
latRad = 89.5 * D2R;
if (v->ForTrans[v->project](lonRad, latRad, &x2, &y))
return FALSE;
break;
case ORTHO:
lonRad = 90. * D2R;
latRad = 0.;
if (v->ForTrans[v->project](lonRad, latRad, &x, &y))
return FALSE;
lonRad = 0. * D2R;
latRad = 89.5 * D2R;
if (v->ForTrans[v->project](lonRad, latRad, &x2, &y))
return FALSE;
break;
}
extX = (y > x) ? 32767. * (x / y) : 32767.;
extY = (y > x) ? 32767. : 32767. * (y / x);
v->scale = 32767. / max(x, y);
GetClientRect(v->hwndCont, &rect);
SetMapMode(hdc, MM_ISOTROPIC);
SetWindowExtEx(hdc, (int)extX, (int)extY, NULL);
SetViewportExtEx(hdc, (rect.right / 2) * v->zoom,
(-rect.bottom / 2) * v->zoom, NULL);
lonRad = v->origLon * D2R;
latRad = v->origLat * D2R;
if (v->ForTrans[v->project](lonRad, latRad, &x, &y))
return FALSE;
origPt.x = (LONG)(x * v->scale);
origPt.y = (LONG)(y * v->scale);
LPtoDP(hdc, &origPt, 1);
SetViewportOrgEx(hdc, rect.right / 2 - origPt.x,
rect.bottom / 2 - origPt.y, NULL);
return TRUE;
}
BOOL SetupWorld(VARS *v, HDC hdc)
{
RECT rect;
POINT origPt;
if (v->project != PLATE_CARREE)
return SetupOtherWorld(v, hdc);
if (v->minMax.minLat == -89.5)
v->minMax.minLat = -90.;
if (v->minMax.maxLat == 89.5)
v->minMax.maxLat = 90.;
GetClientRect(v->hwndCont, &rect);
SetMapMode(hdc, MM_ISOTROPIC);
SetWindowExtEx(hdc, 18000, 9000, NULL);
SetViewportExtEx(hdc, (rect.right / 2) * v->zoom,
(-rect.bottom / 2) * v->zoom, NULL);
origPt.x = (LONG)(v->origLon * 100.);
origPt.y = (LONG)(v->origLat * 100.);
LPtoDP(hdc, &origPt, 1);
SetViewportOrgEx(hdc, rect.right / 2 - origPt.x,
rect.bottom / 2 - origPt.y, NULL);
return TRUE;
}
BOOL ReadMap(VARS *v, char *name)
{
int fd, numRead, toRead;
HDR h;
DPOINT p;
MAP_POLY *newPoly;
char tmp[1024];
int i;
while (1) {
sprintf(tmp, "%s\\mw%s.vec", v->dataDir, name);
if ((fd = open(tmp, O_RDONLY | O_BINARY)) == -1) {
MBPrintf("MapPlot", "Couldn't open data file '%s'", tmp);
if (! GetDataDir(v))
return FALSE;
} else
break;
}
while (read(fd, &h, sizeof(HDR)) > 0) {
if ((int)h.np == 0) {
close(fd);
return TRUE;
}
newPoly = (MAP_POLY *)malloc(sizeof(MAP_POLY));
newPoly->feature = (char)h.feature;
newPoly->nPoints = (unsigned short)h.np;
newPoly->points = (MAP_POINT *)malloc(sizeof(MAP_POINT) * (int)h.np);
newPoly->next = NULL;
toRead = sizeof(MAP_POINT) * newPoly->nPoints;
numRead = read(fd, newPoly->points, toRead);
if (numRead != toRead) {
close(fd);
MBPrintf("MapPlot", "Premature end of file");
return FALSE;
}
for (i = 0; i < (int)h.np; i++) {
newPoly->points[i].lon /= 60.;
newPoly->points[i].lat /= 60.;
}
if (! v->mapData)
v->mapData = newPoly;
if (v->prevPoly)
v->prevPoly->next = newPoly;
v->prevPoly = newPoly;
}
close(fd);
return TRUE;
}
BOOL ReadMaps(VARS *v)
{
char *names[] = {"coast", "nation", "state", "island",
"lake", "river", NULL};
char *name;
int i;
for (i = 0; name = names[i]; i++) {
if (! ReadMap(v, name))
return FALSE;
}
return TRUE;
}
BOOL DrawOtherGrid(VARS *v, HDC hdc)
{
HFONT hFnt = NULL;
HBRUSH hBrush;
HPEN hPen;
POINT oldPt;
POINT pts[800];
RECT rect;
int i, gridDeg;
double lonRad, latRad, x, x2, y;
char tmp[30];
double deg, deg2;
hBrush = SelectObject(hdc, CreateSolidBrush(v->colors[CLR_GRID]));
hPen = SelectObject(hdc, CreatePen(PS_SOLID, 0, v->colors[CLR_GRID]));
for (deg = -180.; deg <= 180.; deg += (double)v->gridDeg) {
if ((deg < v->minMax.minLon) || (deg > v->minMax.maxLon))
continue;
for (deg2 = v->minMax.minLat, i = 0; deg2 <= v->minMax.maxLat;
deg2++, i++) {
if (deg2 == -90.)
deg2 = -89.5;
if (deg2 == 90.)
deg2 = 89.5;
lonRad = deg * D2R;
latRad = deg2 * D2R;
if (v->ForTrans[v->project](lonRad, latRad, &x, &y))
goto error;
pts[i].x = (int)(x * v->scale);
pts[i].y = (int)(y * v->scale);
}
Polyline(hdc, pts, i);
}
for (deg = -90.; deg <= 90.;
deg += (deg == -89.5) ? (double)v->gridDeg - .5: (double)v->gridDeg) {
if ((deg < v->minMax.minLat) || (deg > v->minMax.maxLat))
continue;
if (deg == -90)
deg = -89.5;
if (deg == 90)
deg = 89.5;
for (deg2 = v->minMax.minLon, i = 0; deg2 <= v->minMax.maxLon;
deg2++, i++) {
lonRad = deg2 * D2R;
latRad = (deg == 90.) ? 89.5 * D2R: deg * D2R;
if (v->ForTrans[v->project](lonRad, latRad, &x, &y))
goto error;
pts[i].x = (int)(x * v->scale);
pts[i].y = (int)(y * v->scale);
}
Polyline(hdc, pts, i);
}
DeleteObject(SelectObject(hdc, hBrush));
DeleteObject(SelectObject(hdc, hPen));
if (! (v->shwFeatures & SHW_DEGREES))
return TRUE;
GetClientRect(v->hwndCont, (LPRECT) &rect);
DPtoLP(hdc, (LPPOINT) &rect, 2);
hFnt = SelectObject(hdc, EzCreateFont(hdc, "Arial", 65, 0, 0, TRUE));
hBrush = SelectObject(hdc, CreateSolidBrush(0x00000000));
hPen = SelectObject(hdc, CreatePen(PS_SOLID, 0, 0x00000000));
SetBkMode(hdc, TRANSPARENT);
deg2 = v->minMax.maxLat;
if (deg2 == 90.)
deg2 = 89.5;
for (deg = -180.; deg <= 180.; deg += (double)v->gridDeg) {
if ((deg <= v->minMax.minLon) || (deg >= v->minMax.maxLon))
continue;
if (v->ForTrans[v->project](deg * D2R, deg2 * D2R, &x, &y))
goto error;
if ((double)(rect.top / v->scale) < y) {
if (v->InvTrans[v->project](x, (double)(rect.top / v->scale),
&lonRad, &latRad))
goto error;
if (v->ForTrans[v->project](deg * D2R, latRad, &x, &y))
goto error;
}
sprintf(tmp, "%d", (int)deg);
TextOut(hdc,
(int)(x * v->scale), (int)(y * v->scale), tmp, strlen(tmp));
}
deg2 = v->minMax.minLon;
for (deg = -90.; deg <= 90.;
deg += (deg == -89.5) ? (double)v->gridDeg - .5: (double)v->gridDeg) {
if ((deg <= v->minMax.minLat) || (deg >= v->minMax.maxLat))
continue;
if (deg == -90.)
deg = -89.5;
if (deg == 90.)
deg = 89.5;
if (v->ForTrans[v->project](deg2 * D2R, deg * D2R, &x, &y))
goto error;
if ((double)(rect.left / v->scale) > x) {
if (v->InvTrans[v->project]((double)rect.left / v->scale, y,
&lonRad, &latRad))
goto error;
if (v->ForTrans[v->project](lonRad, deg * D2R, &x, &y))
goto error;
}
sprintf(tmp, "%d", (int)deg);
TextOut(hdc, (int)(x * v->scale), (int)(y * v->scale),
tmp, strlen(tmp));
}
DeleteObject(SelectObject(hdc, hBrush));
DeleteObject(SelectObject(hdc, hPen));
DeleteObject(SelectObject(hdc, hFnt));
return TRUE;
error:
DeleteObject(SelectObject(hdc, hBrush));
DeleteObject(SelectObject(hdc, hPen));
if (hFnt)
DeleteObject(SelectObject(hdc, hFnt));
return FALSE;
}
BOOL DrawGrid(VARS *v, HDC hdc)
{
HFONT hFnt;
HBRUSH hBrush;
HPEN hPen;
POINT oldPt;
RECT rect;
char tmp[30];
double deg;
if (v->project != PLATE_CARREE)
return DrawOtherGrid(v, hdc);
hBrush = SelectObject(hdc, CreateSolidBrush(v->colors[CLR_GRID]));
hPen = SelectObject(hdc, CreatePen(PS_SOLID, 0, v->colors[CLR_GRID]));
for (deg = -180.; deg <= 180.; deg += (double)v->gridDeg) {
if ((deg < v->minMax.minLon) || (deg > v->minMax.maxLon))
continue;
MoveToEx(hdc, (int)(deg * 100.), (int)(v->minMax.maxLat * 100.), &oldPt);
LineTo(hdc, (int)(deg * 100.), (int)(v->minMax.minLat * 100.));
}
for (deg = -90.; deg <= 90.; deg += (double)v->gridDeg) {
if ((deg < v->minMax.minLat) || (deg > v->minMax.maxLat))
continue;
MoveToEx(hdc, (int)(v->minMax.minLon * 100.), (int)(deg * 100.), &oldPt);
LineTo(hdc, (int)(v->minMax.maxLon * 100.), (int)(deg * 100.));
}
DeleteObject(SelectObject(hdc, hBrush));
DeleteObject(SelectObject(hdc, hPen));
if (! (v->shwFeatures & SHW_DEGREES))
return TRUE;
GetClientRect(v->hwndCont, (LPRECT) &rect);
DPtoLP(hdc, (LPPOINT) &rect, 2);
hFnt = SelectObject(hdc, EzCreateFont(hdc, "Arial", 65, 0, 0, TRUE));
hBrush = SelectObject(hdc, CreateSolidBrush(0x00000000));
hPen = SelectObject(hdc, CreatePen(PS_SOLID, 0, 0x00000000));
SetBkMode(hdc, TRANSPARENT);
for (deg = -180.; deg <= 180.; deg += (double)v->gridDeg) {
if ((deg <= v->minMax.minLon) || (deg >= v->minMax.maxLon))
continue;
sprintf(tmp, "%d", (int)deg);
TextOut(hdc, (int)(deg * 100.),
(rect.top <= (int)(v->minMax.maxLat * 100.)) ? rect.top :
(int)(v->minMax.maxLat * 100.),
tmp, strlen(tmp));
}
for (deg = -90.; deg <= 90.; deg += (double)v->gridDeg) {
if ((deg <= v->minMax.minLat) || (deg >= v->minMax.maxLat))
continue;
sprintf(tmp, "%d", (int)deg);
TextOut(hdc,
(rect.left >= (int)(v->minMax.minLon * 100.)) ? rect.left :
(int)(v->minMax.minLon * 100.),
(int)(deg * 100.), tmp, strlen(tmp));
}
DeleteObject(SelectObject(hdc, hBrush));
DeleteObject(SelectObject(hdc, hPen));
DeleteObject(SelectObject(hdc, hFnt));
return TRUE;
}
BOOL DoDrawMap(VARS *v, HDC hdc)
{
MAP_POLY *mapPoly;
POINT pts[1000];
RECT rect;
HBRUSH hBrush;
HPEN hPen = NULL;
COLORREF color;
int i, np;
double lonRad, latRad, x, y;
ShowStatus(v->hwndStatus, 0, "Processing...");
GetClientRect(v->hwndCont, &rect);
hBrush = CreateSolidBrush(v->colors[CLR_BACKGR]);
FillRect (hdc, &rect, hBrush);
DeleteObject(hBrush);
if (! SetupWorld(v, hdc))
goto error;
for (mapPoly = v->mapData; mapPoly; mapPoly = mapPoly->next) {
switch (mapPoly->feature) {
case FEAT_COAST:
if (! (v->shwFeatures & SHW_COAST))
continue;
color = v->colors[CLR_COAST];
break;
case FEAT_COUNTRY:
if (! (v->shwFeatures & SHW_COUNTRY))
continue;
color = v->colors[CLR_COUNTRY];
break;
case FEAT_STATE:
if (! (v->shwFeatures & SHW_STATE))
continue;
color = v->colors[CLR_STATE];
break;
case FEAT_ISLAND:
if (! (v->shwFeatures & SHW_ISLAND))
continue;
color = v->colors[CLR_ISLAND];
break;
case FEAT_LAKE:
if (! (v->shwFeatures & SHW_LAKE))
continue;
color = v->colors[CLR_LAKE];
break;
case FEAT_RIVER:
if (! (v->shwFeatures & SHW_RIVER))
continue;
color = v->colors[CLR_RIVER];
break;
default:
continue;
}
hBrush = SelectObject(hdc, CreateSolidBrush(color));
hPen = SelectObject(hdc, CreatePen(PS_SOLID, 0, color));
np = 0;
for (i = 0; i < (int)mapPoly->nPoints; i++) {
if ((mapPoly->points[i].lon > v->minMax.maxLon) ||
(mapPoly->points[i].lon < v->minMax.minLon) ||
(mapPoly->points[i].lat > v->minMax.maxLat) ||
(mapPoly->points[i].lat < v->minMax.minLat)) {
if (np) {
Polyline(hdc, pts, np);
np = 0;
}
continue;
}
if (v->project == PLATE_CARREE) {
pts[np].x = (int)(mapPoly->points[i].lon * 100.);
pts[np].y = (int)(mapPoly->points[i].lat * 100.);
} else {
lonRad = mapPoly->points[i].lon * D2R;
latRad = mapPoly->points[i].lat * D2R;
if (v->ForTrans[v->project](lonRad, latRad, &x, &y))
goto error;
pts[np].x = (int)(x * v->scale);
pts[np].y = (int)(y * v->scale);
}
np++;
}
if (np)
Polyline(hdc, pts, np);
DeleteObject(SelectObject(hdc, hBrush));
DeleteObject(SelectObject(hdc, hPen));
hPen = NULL;
}
if (v->shwFeatures & SHW_GRID) {
if (! DrawGrid(v, hdc))
goto error;
}
ShowStatus(v->hwndStatus, 0, "Done");
return TRUE;
error:
if (hPen) {
DeleteObject(SelectObject(hdc, hBrush));
DeleteObject(SelectObject(hdc, hPen));
}
ShowStatus(v->hwndStatus, 0, "");
return FALSE;
}
void DrawMap(VARS *v, HDC hdc)
{
if (v->wdbIIMode)
DrawWDBIIMaps(v, hdc);
else
DoDrawMap(v, hdc);
}