#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <io.h>
#include <sys\stat.h>
#include <math.h>
#include <winlib/winlib.h>
#include <geolib/cproj.h>
#include <geolib/proj.h>
#include "mapplot.h"
#include "map.h"
#include "wdb-ii.h"
#include "fsbox.h"
static BOOL penUp = TRUE;
static POINT dPoints[16000];
static int nPoints;
BOOL uPenDn(VARS *v, HDC hdc, double lon, double lat)
{
double lonRad, latRad, x, y;
if ((lon > v->minMax.maxLon) || (lon < v->minMax.minLon) ||
(lat > v->minMax.maxLat) || (lat < v->minMax.minLat)) {
if (nPoints)
Polyline(hdc, dPoints, 16000);
nPoints = 0;
return TRUE;
}
if (penUp) {
if (nPoints)
Polyline(hdc, dPoints, 16000);
nPoints = 0;
penUp = FALSE;
}
if (v->project == PLATE_CARREE) {
dPoints[nPoints].x = (int)(lon * 100.);
dPoints[nPoints].y = (int)(lat * 100.);
} else {
lonRad = lon * D2R;
latRad = lat * D2R;
if (v->ForTrans[v->project](lonRad, latRad, &x, &y))
return FALSE;
dPoints[nPoints].x = (int)(x * v->scale);
dPoints[nPoints].y = (int)(y * v->scale);
}
if (++nPoints == 16000) {
Polyline(hdc, dPoints, 16000);
nPoints = 0;
}
return TRUE;
}
BOOL DrawWDBIIMap(VARS *v, HDC hdc, char *fileName, BOOL clear)
{
int Ifile, segCount, idx, idy, segBufSize, olt, oln, j, k, jStroke, iSeg;
char *dataBuf;
BIT32 i32;
BIT16 *segBuf;
RECT rect;
HBRUSH hBrush;
HPEN hPen;
COLORREF color;
double lastLon = 0.;
double lon, lat;
char *features;
struct stat st;
int pos;
BOOL retVal = TRUE;
struct segDict {
BIT32 segid;
BIT32 maxLat, minLat, maxLon, minLon;
BIT32 absAddr;
BIT16 nBytes;
BIT16 rank;
} *sd, *sdBuf;
struct segment {
BIT32 orgX, orgY;
BIT32 id;
BIT16 nStrokes;
BIT16 dummy;
} sb;
struct cbdHead *header;
if ((Ifile = open(fileName, O_RDONLY | O_BINARY)) == -1) {
MBPrintf("", "%s", strerror(errno));
return FALSE;
}
ShowStatus(v->hwndStatus, 0, "Processing...");
stat(fileName, &st);
dataBuf = (char*)malloc(st.st_size);
read(Ifile, dataBuf, st.st_size);
close(Ifile);
if (clear) {
GetClientRect(v->hwndMain, &rect);
hBrush = CreateSolidBrush(v->colors[6]);
FillRect (hdc, &rect, hBrush);
DeleteObject(hBrush);
if (! SetupWorld(v, hdc))
return FALSE;
}
if (strstr(fileName, "cil.")) {
color = v->colors[CLR_COAST];
features = v->wdbShwCilFeatures;
} else if (strstr(fileName, "bdy.")) {
color = v->colors[CLR_COUNTRY];
features = v->wdbShwBdyFeatures;
} else if (strstr(fileName, "riv.")) {
color = v->colors[CLR_RIVER];
features = v->wdbShwRivFeatures;
} else {
color = 0x00000000;
}
hBrush = SelectObject(hdc, CreateSolidBrush(color));
hPen = SelectObject(hdc, CreatePen(PS_SOLID, 0, color));
/*
* Check the file header for the correct magic number,
* and learn the address of the segment dictionary
*/
header = (struct cbdHead *)dataBuf;
if (header->magic != CBD_MAGIC) {
MBPrintf ("", "File has bad magic number %X != %X\n",
header->magic, CBD_MAGIC);
free(dataBuf);
DeleteObject(SelectObject(hdc, hBrush));
DeleteObject(SelectObject(hdc, hPen));
return FALSE;
}
/* allocate space for the segment buffer */
segBufSize = 2 * header->segMax;
segBuf = (BIT16 *) malloc (50 + segBufSize);
/* allocate space for the segment dictionary */
sdBuf = (struct segDict *) malloc (100 + (header->segSize));
sd = sdBuf;
sd++;
/* Get the segment dictionary (it's at the end of the file) */
memcpy(sd, dataBuf + header->dictAddr, header->segSize);
/*
* Now look at each segment and decide if we're
* going to keep it or not
*/
segCount = header->segCount;
nPoints = 0;
sd = sdBuf;
for (iSeg = 1; iSeg <= segCount; iSeg++) {
sd++; /* does this really work? wow! */
if (! features[sd->rank])
continue;
pos = sd->absAddr;
memcpy(&sb, dataBuf + pos, sizeof(sb));
pos += sizeof(sb);
if (sd->nBytes > segBufSize) {
MBPrintf("", "Segment %d needs %d bytes; buffer limit is %d.\n", iSeg, sd->nBytes, segBufSize);
retVal = FALSE;
goto end;
}
memcpy(segBuf, dataBuf + pos, sd->nBytes);
k = 0;
oln = sb.orgX;
olt = sb.orgY;
lon = oln / 3600.;
lat = olt / 3600.;
penUp = TRUE;
if (! uPenDn(v, hdc, lon, lat)) {
retVal = FALSE;
goto end;
}
lastLon = lon;
for (jStroke = 1; jStroke <= sb.nStrokes; jStroke++) {
if (segBuf[k] & SHORTFLAG) {
/* Flag bit on: unpack a 16-bit field into dx and dy */
i32 = segBuf[k++];
if (i32 > 0)
i32 &= ~SHORTFLAG;
idy = i32 & 0xFF;
if (idy & 0x80)
idy |= ~0xFF; /* extend sign */
idx = i32 >> 8;
if (idx & 0x80)
idx |= ~0xBF; /* extend sign */
} else {
/* Flag bit off: take dx and dy from 32-bit fields. */
idx = segBuf[k++];
if (idx < 0)
idx |= SHORTFLAG;
idx = (idx << 16) | (unsigned short) segBuf[k];
k++;
idy = segBuf[k];
k++;
if (idy < 0)
idy |= SHORTFLAG;
idy = (idy << 16) | segBuf[k];
k++;
}
oln = (oln + idx);
olt = (olt + idy);
lon = oln / 3600.;
lat = olt / 3600.;
if (fabs(lastLon - lon) > 180.)
penUp = TRUE;
if (! uPenDn(v, hdc, lon, lat)) {
retVal = FALSE;
goto end;
}
lastLon = lon;
}
}
if (nPoints)
Polyline(hdc, dPoints, nPoints);
end:
free(sdBuf);
free(segBuf);
free(dataBuf);
DeleteObject(SelectObject(hdc, hBrush));
DeleteObject(SelectObject(hdc, hPen));
ShowStatus(v->hwndStatus, 0, "Done");
return retVal;
}
void DrawWDBIIMaps(VARS *v, HDC hdc)
{
WDBII_MAP *wdbIIMap;
BOOL clear = TRUE;
for (wdbIIMap = v->wdbIIMaps; wdbIIMap; wdbIIMap = wdbIIMap->next) {
if (! DrawWDBIIMap(v, hdc, wdbIIMap->name, clear))
return;
clear = FALSE;
}
if (v->shwFeatures & SHW_GRID)
DrawGrid(v, hdc);
}
void DoAddWDBIIMap(VARS *v, char *name)
{
WDBII_MAP *wdbIIMap, *p;
wdbIIMap = (WDBII_MAP *)malloc(sizeof(WDBII_MAP));
strcpy(wdbIIMap->name, name);
wdbIIMap->next = NULL;
if (v->wdbIIMaps) {
for (p = v->wdbIIMaps; p->next; p = p->next);
p->next = wdbIIMap;
} else
v->wdbIIMaps = wdbIIMap;
v->wdbIIMode = TRUE;
}
BOOL AddWDBIIMap(VARS *v)
{
WDBII_MAP *wdbIIMap, *p;
char szFileName[256], szTitleName[256];
char curDir[256];
szFileName[0] = '\0';
szTitleName[0] = '\0';
if (*(v->wdbIIDir) != '\0')
FileInitialize(0, v->wdbIIDir);
else
FileInitialize(0, NULL);
if (! FileOpenDlg(v->hwndMain, szFileName, szTitleName))
return FALSE;
DoAddWDBIIMap(v, szFileName);
GetCurrentDirectory(256, (LPTSTR)curDir);
if (strcmp(v->wdbIIDir, curDir))
strcpy(v->wdbIIDir, curDir);
InvalidateRect(v->hwndMain, NULL, FALSE);
UpdateWindow(v->hwndMain);
return TRUE;
}
void DeleteWDBIIMaps(VARS *v)
{
char *p;
while (v->wdbIIMaps) {
p = (char *)(v->wdbIIMaps);
v->wdbIIMaps = v->wdbIIMaps->next;
free(p);
}
v->wdbIIMode = FALSE;
}
BOOL WDBIILoaded(VARS *v, char *name)
{
WDBII_MAP *p;
for (p = v->wdbIIMaps; p; p = p->next) {
if (strstr(p->name, name))
return TRUE;
}
return FALSE;
}