#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <io.h>
#include <sys\stat.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;
if (v->minMax.minLat < -89.5)
v->minMax.minLat = -89.5;
if (v->minMax.maxLat > 89.5)
v->minMax.maxLat = 89.5;
/* 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;
DPOINT p;
MAP_POLY *newPoly;
char tmp[1024];
int i, np = 0;
int maxNp = 0;
struct stat st;
MAP_REC *dataBuf;
sprintf(tmp, "%s\\%s.PNT", v->dataDir, name);
if ((fd = open(tmp, O_RDONLY | O_BINARY)) == -1) {
MBPrintf("MapPlot", "Couldn't open data file '%s'", tmp);
return FALSE;
}
stat(tmp, &st);
dataBuf = (MAP_REC *)malloc(st.st_size);
read(fd, dataBuf, st.st_size);
close(fd);
for (i = 0; i < (st.st_size / sizeof(MAP_REC)); i++) {
if (dataBuf[i].code > 5) {
if (np) {
newPoly->nPoints = np;
if (! v->mapData)
v->mapData = newPoly;
if (v->prevPoly)
v->prevPoly->next = newPoly;
v->prevPoly = newPoly;
}
newPoly = (MAP_POLY *)malloc(sizeof(MAP_POLY));
if (dataBuf[i].code < 2001)
newPoly->feature = 1;
else if (dataBuf[i].code < 4001)
newPoly->feature = 2;
else if (dataBuf[i].code < 5001)
newPoly->feature = 4;
else if (dataBuf[i].code < 6001)
newPoly->feature = 5;
else if (dataBuf[i].code < 7001)
newPoly->feature = 6;
else
newPoly->feature = 7;
newPoly->points = (MAP_POINT *)malloc(sizeof(MAP_POINT));
newPoly->next = NULL;
np = 0;
newPoly->points[np].lon = (double)dataBuf[i].lon / 60.;
newPoly->points[np].lat = (double)dataBuf[i].lat / 60.;
newPoly->points[np].level = 100;
np++;
} else {
newPoly->points = (MAP_POINT *)realloc(newPoly->points,
sizeof(MAP_POINT) * (np + 1));
newPoly->points[np].lon = (double)dataBuf[i].lon / 60.;
newPoly->points[np].lat = (double)dataBuf[i].lat / 60.;
newPoly->points[np].level = (char)dataBuf[i].code;
np++;
}
}
if (np) {
newPoly->nPoints = np;
if (! v->mapData)
v->mapData = newPoly;
if (v->prevPoly)
v->prevPoly->next = newPoly;
v->prevPoly = newPoly;
}
close(fd);
free(dataBuf);
return TRUE;
}
BOOL ReadMaps(VARS *v)
{
char *names[] = {"PCOAST", "PISLAND", "PLAKE", "RIVER", "PUSA48",
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 = v->minMax.minLon; deg <= v->minMax.maxLon;
deg += (double)v->gridDeg) {
for (deg2 = v->minMax.minLat, i = 0; deg2 <= v->minMax.maxLat;
deg2++, i++) {
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 = v->minMax.minLat; deg <= ((v->minMax.maxLat == 89.5) ? 90. : v->minMax.maxLat);
deg += (deg == -89.5) ? (double)v->gridDeg - .5: (double)v->gridDeg) {
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);
for (deg = v->minMax.minLon; deg <= v->minMax.maxLon; deg += (double)v->gridDeg) {
if ((deg == v->minMax.minLon) || (deg == v->minMax.maxLon))
continue;
if (v->ForTrans[v->project](deg * D2R, v->minMax.maxLat * 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));
}
for (deg = v->minMax.minLat; deg <= v->minMax.maxLat;
deg += (deg == -89.5) ? (double)v->gridDeg - .5: (double)v->gridDeg) {
if ((deg == v->minMax.minLat) || (deg == v->minMax.maxLat))
continue;
if (v->ForTrans[v->project](v->minMax.minLon * 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 = v->minMax.minLon; deg <= v->minMax.maxLon; deg += (double)v->gridDeg) {
MoveToEx(hdc, (int)(deg * 100.), (int)(v->minMax.maxLat * 100.), &oldPt);
LineTo(hdc, (int)(deg * 100.), (int)(v->minMax.minLat * 100.));
}
for (deg = v->minMax.minLat; deg <= v->minMax.maxLat; deg += (double)v->gridDeg) {
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 = v->minMax.minLon; deg <= v->minMax.maxLon; 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 = v->minMax.minLat; deg <= v->minMax.maxLat; 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;
RECT rect;
HBRUSH hBrush;
HPEN hPen = NULL;
COLORREF color;
int i, np;
double lonRad, latRad, x, y;
double lastLon = 0.;
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:
exit(1);
continue;
}
pts = (POINT *)malloc(sizeof(POINT) * (int)mapPoly->nPoints);
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].level < 1)
continue;
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) {
if (np == 1)
SetPixel(hdc, pts[0].x, pts[0].y, color);
else
Polyline(hdc, pts, np);
np = 0;
}
continue;
}
if (fabs(lastLon - mapPoly->points[i].lon) > 180.) {
if (np) {
if (np == 1)
SetPixel(hdc, pts[0].x, pts[0].y, color);
else
Polyline(hdc, pts, np);
np = 0;
}
}
if (np == 16000) {
Polyline(hdc, pts, 16000);
np = 0;
}
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++;
lastLon = mapPoly->points[i].lon;
}
if (np) {
if (np == 1)
SetPixel(hdc, pts[0].x, pts[0].y, color);
else
Polyline(hdc, pts, np);
}
DeleteObject(SelectObject(hdc, hBrush));
DeleteObject(SelectObject(hdc, hPen));
hPen = NULL;
free(pts);
pts = NULL;
}
if (v->shwFeatures & SHW_GRID) {
if (! DrawGrid(v, hdc))
goto error;
}
ShowStatus(v->hwndStatus, 0, "Done");
return TRUE;
error:
if (pts)
free(pts);
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);
}