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