#include #include #include #include #include #include #include #include #include #include #include #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; } .