#include <Navaids/routePath.hxx>
#include <Aircraft/FlightHistory.hxx>
#include <AIModel/AIAircraft.hxx>
+#include <AIModel/AIManager.hxx>
#include <AIModel/AIFlightPlan.hxx>
const char* RULER_LEGEND_KEY = "ruler-legend";
_width = maxX - x;
_height = maxY - y;
_hasPanned = false;
- _projection = PROJECTION_SAMSON_FLAMSTEED;
+ _projection = PROJECTION_AZIMUTHAL_EQUIDISTANT;
_magneticHeadings = false;
MapData::setFont(legendFont);
_cachedZoom = MAX_ZOOM - zoom();
SGGeod topLeft = unproject(SGVec2d(_width/2, _height/2));
// compute draw range, including a fudge factor for ILSs and other 'long'
- // symbols
+ // symbols.
_drawRangeNm = SGGeodesy::distanceNm(_projectionCenter, topLeft) + 10.0;
-
-
+
FGFlightHistory* history = (FGFlightHistory*) globals->get_subsystem("history");
if (history && _root->getBoolValue("draw-flight-history")) {
_flightHistoryPath = history->pathForHistory();
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
- // cetere drawing about the widget center (which is also the
+ // center drawing about the widget center (which is also the
// projection centre)
glTranslated(dx + sx + (_width/2), dy + sy + (_height/2), 0.0);
void MapWidget::drawLatLonGrid()
{
- _gridSpacing = 1.0;
+ // Larger grid spacing when zoomed out, to prevent clutter
+ if (_cachedZoom < SHOW_DETAIL_ZOOM) {
+ _gridSpacing = 1.0;
+ } else {
+ _gridSpacing = 5.0;
+ }
+
_gridCenter = roundGeod(_gridSpacing, _projectionCenter);
_gridCache.clear();
didDraw |= drawLineClipped(gridPoint(x, iy), gridPoint(x+1, iy));
didDraw |= drawLineClipped(gridPoint(x, -iy), gridPoint(x, -iy + 1));
didDraw |= drawLineClipped(gridPoint(x, iy), gridPoint(x, iy - 1));
-
}
for (int y = -iy; y < iy; ++y) {
didDraw |= drawLineClipped(gridPoint(ix, y), gridPoint(ix - 1, y));
}
- if (ix > 30) {
+ if (ix > (90/_gridSpacing)-1) {
break;
}
} while (didDraw);
p = SGVec2d(cos(geod.getLatitudeRad()) * lonDiff, latDiff) * r * currentScale();
break;
}
-
+
+ case PROJECTION_AZIMUTHAL_EQUIDISTANT:
+ {
+ // Azimuthal Equidistant projection, relative to the projection center
+ // http://www.globmaritime.com/martech/marine-navigation/general-concepts/626-azimuthal-equidistant-projection
+ double ref_lat = _projectionCenter.getLatitudeRad(),
+ ref_lon = _projectionCenter.getLongitudeRad(),
+ lat = geod.getLatitudeRad(),
+ lon = geod.getLongitudeRad(),
+ lonDiff = lon - ref_lon;
+
+ double c = acos( sin(ref_lat) * sin(lat) + cos(ref_lat) * cos(lat) * cos(lonDiff) );
+ if (c == 0.0){
+ // angular distance from center is 0
+ p= SGVec2d(0.0, 0.0);
+ break;
+ }
+
+ double k = c / sin(c);
+ double x, y;
+ if (ref_lat == (90 * SG_DEGREES_TO_RADIANS))
+ {
+ x = (SGD_PI / 2 - lat) * sin(lonDiff);
+ y = -(SGD_PI / 2 - lat) * cos(lonDiff);
+ }
+ else if (ref_lat == -(90 * SG_DEGREES_TO_RADIANS))
+ {
+ x = (SGD_PI / 2 + lat) * sin(lonDiff);
+ y = (SGD_PI / 2 + lat) * cos(lonDiff);
+ }
+ else
+ {
+ x = k * cos(lat) * sin(lonDiff);
+ y = k * ( cos(ref_lat) * sin(lat) - sin(ref_lat) * cos(lat) * cos(lonDiff) );
+ }
+ p = SGVec2d(x, y) * r * currentScale();
+
+ break;
+ }
+
case PROJECTION_ORTHO_AZIMUTH:
{
// http://mathworld.wolfram.com/OrthographicProjection.html
double lon = (unscaled.x() / cos(lat)) + _projectionCenter.getLongitudeRad();
return SGGeod::fromRad(lon, lat);
}
+
+ case PROJECTION_AZIMUTHAL_EQUIDISTANT:
+ {
+ double r = earth_radius_lat(_projectionCenter.getLatitudeRad());
+ SGVec2d unscaled = ur * (1.0 / currentScale());
+ double lat = 0,
+ lon = 0,
+ ref_lat = _projectionCenter.getLatitudeRad(),
+ ref_lon = _projectionCenter.getLongitudeRad(),
+ rho = sqrt(unscaled.x() * unscaled.x() + unscaled.y() * unscaled.y()),
+ c = rho/r;
+
+ if (rho == 0)
+ {
+ lat = ref_lat;
+ lon = ref_lon;
+ }
+ else
+ {
+ lat = asin( cos(c) * sin(ref_lat) + (unscaled.y() * sin(c) * cos(ref_lat)) / rho);
+
+ if (ref_lat == (90 * SG_DEGREES_TO_RADIANS))
+ {
+ lon = ref_lon + atan(-unscaled.x()/unscaled.y());
+ }
+ else if (ref_lat == -(90 * SG_DEGREES_TO_RADIANS))
+ {
+ lon = ref_lon + atan(unscaled.x()/unscaled.y());
+ }
+ else
+ {
+ lon = ref_lon + atan(unscaled.x() * sin(c) / (rho * cos(ref_lat) * cos(c) - unscaled.y() * sin(ref_lat) * sin(c)));
+ }
+ }
+
+ return SGGeod::fromRad(lon, lat);
+ }
case PROJECTION_ORTHO_AZIMUTH:
{
SGVec3d cartPt = orient.rotate(SGVec3d(unscaled.x(), unscaled.y(), 0.0));
return SGGeod::fromCart(cartPt + cartCenter);
}
+
+ default:
+ throw sg_exception("MapWidget::unproject(): requested unknown projection");
} // of projection mode switch
}
// try to access the flight-plan of the aircraft. There are several layers
// of potential NULL-ness here, so we have to be defensive at each stage.
std::string originICAO, destinationICAO;
- FGAIManager* aiManager = static_cast<FGAIManager*>(globals->get_subsystem("ai-model"));
+ FGAIManager* aiManager = globals->get_subsystem<FGAIManager>();
FGAIBasePtr aircraft = aiManager ? aiManager->getObjectFromProperty(model) : NULL;
if (aircraft) {
FGAIAircraft* p = static_cast<FGAIAircraft*>(aircraft.get());