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