//------------------------------------------------------------------------------ // converts screen to lat/lon coordinates //------------------------------------------------------------------------------ bool MapPage::screen2LatLon(const LCreal x, const LCreal y, double* const lat, double* const lon) const { bool ok = false; const double scale = getScale(); const double cosLat = getCosRefLat(); if (lat != nullptr && lon != nullptr && scale != 0 && cosLat != 0) { // buffer the inputs double screenX = x; double screenY = y; // Adjust for the decentered displayment if ( !getCentered() ) screenY -= getDisplacement(); // Scale from screen (inches) to A/C (NM) and // transpose the X and Y from screen to A/C const double acX = screenY/scale; const double acY = screenX/scale; // Rotate A/C to NED double earthX = 0.0; double earthY = 0.0; if (getNorthUp()) { earthX = acX; earthY = acY; } else { earthX = (acX * headingCos) - (acY * headingSin); earthY = (acX * headingSin) + (acY * headingCos); } // Convert nautical miles (NED) from ref point to lat/lon *lat = (earthX/60.0) + getReferenceLatDeg(); *lon = (earthY/(60.0*cosLat)) + getReferenceLonDeg(); ok = true; } return ok; }
//------------------------------------------------------------------------------ // converts lat/lon to screen coordinates //------------------------------------------------------------------------------ bool MapPage::latLon2Screen(const double lat, const double lon, LCreal* const x, LCreal* const y) const { bool ok = false; if (x != nullptr && y != nullptr) { // Convert to nautical miles (NED) centered on ownship const double earthX = ((lat - getReferenceLatDeg()) * 60.0); const double earthY = ((lon - getReferenceLonDeg()) * 60.0 * getCosRefLat()); // Rotate to aircraft coordinates double acX = 0; double acY = 0; if (getNorthUp()) { acX = earthX; acY = earthY; } else { acX = (earthX * headingCos) + (earthY * headingSin); acY = -(earthX * headingSin) + (earthY * headingCos); } // Scale from nautical miles to inches and // transpose the X and Y from A/C to screen double screenY = acX * getScale(); const double screenX = acY * getScale(); // Adjust for the decentered displayment if ( !getCentered() ) screenY += getDisplacement(); *x = static_cast<LCreal>(screenX); *y = static_cast<LCreal>(screenY); ok = true; } return ok; }
//------------------------------------------------------------------------------ // drawFunc() - Draw the map. //------------------------------------------------------------------------------ void MapDrawer::drawFunc() { GLdouble ocolor[4]; // Get our old color glGetDoublev(GL_CURRENT_COLOR, &ocolor[0]); GLdouble dLeft = 0, dRight = 0, dBottom = 0, dTop = 0, dNear = 0, dFar = 0; //double lat = 0, lon = 0; // Determine our rotation, if needed. if (getDisplay() != 0) getDisplay()->getOrtho(dLeft, dRight, dBottom, dTop, dNear, dFar); if (myMap != 0) { double rLat = myMap->getReferenceLatDeg(); double rLon = myMap->getReferenceLonDeg(); int refZone = myMap->findBestZone(rLat, rLon); if (refZone != -1) { // Determine our CENTER tile and pixel position myMap->latLonToTileRowColumn(rLat, rLon, originRow[CENTER_PAGER], originCol[CENTER_PAGER], textureRow[CENTER_PAGER], textureCol[CENTER_PAGER], pixelRow[CENTER_PAGER], \ pixelCol[CENTER_PAGER], pagers[CENTER_PAGER]); // Take the distance in nautical miles, and then convert to degrees LCreal quickRange = getRange(); LCreal disDegN = quickRange / 60.0f; LCreal disDegE = (LCreal)(quickRange / (60.0 * getCosRefLat())); // Get the space (in latitude degrees) between each pixel CadrgTocEntry* te = pagers[CENTER_PAGER]->getToc(); LCreal n = 1, e = 1; if (te != 0) { n = (LCreal)te->getVertInterval(); e = (LCreal)te->getHorizInterval(); } // OK, so we know how far we want to look out (disDeg, and how far it is per pixel, so we can find // the total amount of pixels by dividing disDeg / x. vpHL = disDegN / n; vpWL = disDegE / e; // Scale our viewport by the ratio of our map page to our actual ortho, to make our background map fit into our range circle LCreal rad = getOuterRadius(); LCreal radRatio = (LCreal)(dTop / rad); vpHL *= radRatio; vpWL *= radRatio; // Now stretch and shrink our ortho based on if we are track up double newVPHL = vpHL; double newVPWL = vpWL; // Force our ortho before drawing getDisplay()->forceOrtho(-newVPWL, newVPWL, -newVPHL, newVPHL, -2, 2); // Update our current reference zone updateZone(refZone, zones[CENTER_PAGER], CENTER_PAGER); // Tell our center pager to draw the map drawMap(zones[CENTER_PAGER], CENTER_PAGER); // Check to see if we need to have zones around us (depending on the range) LCreal rngDeg = (quickRange * 2) / 60.0f; int tZone = myMap->findBestZone(rLat + rngDeg, rLon); // Now determine if there are other zones to draw if (tZone != zones[CENTER_PAGER]) { updateZone(tZone, zones[TOP_PAGER], TOP_PAGER); myMap->latLonToTileRowColumn(rLat, rLon, originRow[TOP_PAGER], originCol[TOP_PAGER], textureRow[TOP_PAGER], textureCol[TOP_PAGER], pixelRow[TOP_PAGER], \ pixelCol[TOP_PAGER], pagers[TOP_PAGER]); // Draw the map drawMap(zones[TOP_PAGER], TOP_PAGER); } else pagers[TOP_PAGER]->flushTextures(); // Set our reference zone. myMap->setZone(zones[CENTER_PAGER], pagers[CENTER_PAGER]); } } // Set our ortho and our color back to it's original state after we draw. getDisplay()->forceOrtho(dLeft, dRight, dBottom, dTop, dNear, dFar); glColor4dv(ocolor); }