#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <winlib/winlib.h>
#include "gshhs.h"
#define LEVEL_LAND 1
#define LEVEL_LAKE 2
#define LEVEL_ISLAND_IN_LAKE 3
#define LEVEL_POND_IN_ISLAND_IN_LAKE 4
typedef struct {
double lon;
double lat;
} MAP_POINT;
typedef struct mapPoly {
char level;
unsigned short nPoints;
MAP_POINT *points;
struct mapPoly *next;
} MAP_POLY;
MAP_POLY *mapData = NULL;
HINSTANCE hInst;
HWND hwndStatus;
int statusHeight;
BOOL ReadMapData(void)
{
FILE *f;
double w, e, s, n, area, lon, lat;
char source;
int i;
int max_east = 270000000;
struct GSHHS h;
struct GSHHS_POINT p;
MAP_POLY *newPoly, *prevPoly = NULL;
if (! (f = fopen("d:/Graphics/GIS/GSHHS/gshhs_l.b", "rb"))) {
MessageBox(NULL, "Missing map data file", "DrawMap",
MB_OK | MB_ICONERROR);
return FALSE;
}
while (fread((void *)&h, (size_t)sizeof (struct GSHHS), (size_t)1, f) == 1) {
h.id = swabi4 ((unsigned int)h.id);
h.n = swabi4 ((unsigned int)h.n);
h.level = swabi4 ((unsigned int)h.level);
h.west = swabi4 ((unsigned int)h.west);
h.east = swabi4 ((unsigned int)h.east);
h.south = swabi4 ((unsigned int)h.south);
h.north = swabi4 ((unsigned int)h.north);
h.area = swabi4 ((unsigned int)h.area);
h.greenwich = swabi2 ((unsigned int)h.greenwich);
h.source = swabi2 ((unsigned int)h.source);
newPoly = (MAP_POLY *)malloc(sizeof(MAP_POLY));
newPoly->level = (char)h.level;
newPoly->nPoints = (unsigned short)h.n;
newPoly->points = (MAP_POINT *)malloc(sizeof(MAP_POINT) * h.n);
newPoly->next = NULL;
w = h.west * 1.0e-6;
e = h.east * 1.0e-6;
s = h.south * 1.0e-6;
n = h.north * 1.0e-6;
source = (h.source == 1) ? 'W' : 'C';
area = 0.1 * h.area;
for (i = 0; i < h.n; i++) {
if (fread ((void *)&p, (size_t)sizeof(struct GSHHS_POINT),
(size_t)1, f) != 1) {
MBPrintf("DrawMap", "Error reading file for polygon %d, point %d.\n", h.id, i);
return FALSE;
}
p.x = swabi4 ((unsigned int)p.x);
p.y = swabi4 ((unsigned int)p.y);
newPoly->points[i].lon = (h.greenwich && p.x > max_east) ?
p.x * 1.0e-6 - 360.0 : p.x * 1.0e-6;
newPoly->points[i].lat = p.y * 1.0e-6;
}
if (! mapData)
mapData = newPoly;
if (prevPoly)
prevPoly->next = newPoly;
prevPoly = newPoly;
max_east = 180000000;
}
fclose(f);
return TRUE;
}
BOOL DrawMap(HWND hwnd, HDC hdc)
{
MAP_POLY *mapPoly;
POINT *dPoints;
RECT rect;
HBRUSH hBrush;
HPEN hPen;
double xScaleFact, yScaleFact;
int i;
BOOL retVal = TRUE;
COLORREF color;
ShowStatus(hwndStatus, 0, "Processing...");
GetClientRect(hwnd, &rect);
xScaleFact = (double)rect.right / 360.0;
yScaleFact = (300.0 * ((double)rect.right / 600.0)) / 180.0;
rect.bottom -= statusHeight;
hBrush = CreateSolidBrush(0x00ffd0d0);
FillRect(hdc, &rect, hBrush);
DeleteObject(hBrush);
for (mapPoly = mapData; mapPoly; mapPoly = mapPoly->next) {
dPoints = (POINT *)malloc(sizeof(POINT) * (int)(mapPoly->nPoints));
for (i = 0; i < (int)mapPoly->nPoints; i++) {
dPoints[i].x = (mapPoly->points[i].lon * xScaleFact);
dPoints[i].y = (rect.bottom / 2) -
(mapPoly->points[i].lat * yScaleFact);
}
switch (mapPoly->level) {
case LEVEL_LAND:
color = 0x00209020;
break;
case LEVEL_LAKE:
color = 0x00b00000;
break;
case LEVEL_ISLAND_IN_LAKE:
color = 0x00209020;
break;
case LEVEL_POND_IN_ISLAND_IN_LAKE:
color = 0x00b00000;
break;
}
hBrush = SelectObject(hdc, CreateSolidBrush(color));
hPen = SelectObject(hdc, CreatePen(PS_SOLID, 0, color));
if (! Polygon(hdc, dPoints, (int)mapPoly->nPoints)) {
DeleteObject(SelectObject(hdc, hBrush));
DeleteObject(SelectObject(hdc, hPen));
free(dPoints);
MBPrintf("DrawMap", "Polygon overflow: %d points",
mapPoly->nPoints);
retVal = FALSE;
goto end;
}
DeleteObject(SelectObject(hdc, hBrush));
DeleteObject(SelectObject(hdc, hPen));
free(dPoints);
}
end:
ShowStatus(hwndStatus, 0, "Done");
return retVal;
}
LRESULT CALLBACK MainWndProc(HWND hwnd, UINT msg, WPARAM wParam,
LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
RECT rect;
BOOL r;
int x, y;
switch (msg) {
case WM_CREATE:
hwndStatus = CreateStatusWnd(hInst, hwnd, 2);
GetWindowRect(hwndStatus, &rect);
statusHeight = rect.bottom - rect.top;
x = (int)(((LPCREATESTRUCT)lParam)->x);
y = (int)(((LPCREATESTRUCT)lParam)->y);
MoveWindow(hwnd, x, y,
600 + (GetSystemMetrics(SM_CXSIZEFRAME) * 2),
300 + statusHeight + GetSystemMetrics(SM_CYCAPTION) +
(GetSystemMetrics(SM_CYSIZEFRAME) * 2),
TRUE);
return 0;
case WM_SIZE:
SendMessage(hwndStatus, WM_SIZE, wParam, lParam);
SetStatusParts(hwndStatus, 2);
return 0;
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);
r = DrawMap(hwnd, hdc);
EndPaint(hwnd, &ps);
if (! r)
exit(1);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd,msg,wParam,lParam);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, INT nCmdShow)
{
WNDCLASS wc;
HWND hwnd;
MSG msg;
if (! ReadMapData())
return 0;
hInst = hInstance;
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = (WNDPROC)MainWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(hInstance, IDI_WINLOGO);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.lpszMenuName = NULL;
wc.lpszClassName = "MainWndClass";
if (! RegisterClass(&wc))
return 0;
hwnd = CreateWindow(
"MainWndClass",
"DrawMap",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, 600, 340,
NULL, NULL, hInstance, NULL);
ShowWindow(hwnd, nCmdShow);
while (GetMessage (&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}