]> git.mxchange.org Git - flightgear.git/blobdiff - src/GUI/MapWidget.cxx
GUI support for VIA/Discontinuity
[flightgear.git] / src / GUI / MapWidget.cxx
index 8a5a0b715e4fe991bf390ffa7c3c1ee62de4f184..bb44327fb30d49cdd6dd842652e0ecb1af87048a 100644 (file)
@@ -27,6 +27,7 @@
 #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";
@@ -464,7 +465,7 @@ MapWidget::MapWidget(int x, int y, int maxX, int maxY) :
   _width = maxX - x;
   _height = maxY - y;
   _hasPanned = false;
-  _projection = PROJECTION_SAMSON_FLAMSTEED;
+  _projection = PROJECTION_AZIMUTHAL_EQUIDISTANT;
   _magneticHeadings = false;
   
   MapData::setFont(legendFont);
@@ -651,10 +652,9 @@ void MapWidget::update()
     _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();
@@ -742,7 +742,7 @@ void MapWidget::draw(int dx, int dy)
 
   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);
 
@@ -975,7 +975,13 @@ SGVec2d MapWidget::gridPoint(int ix, int iy)
 
 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();
 
@@ -995,7 +1001,6 @@ void MapWidget::drawLatLonGrid()
       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) {
@@ -1005,7 +1010,7 @@ void MapWidget::drawLatLonGrid()
       didDraw |= drawLineClipped(gridPoint(ix, y), gridPoint(ix - 1, y));
     }
 
-    if (ix > 30) {
+    if (ix > (90/_gridSpacing)-1) {
       break;
     }
   } while (didDraw);
@@ -1565,7 +1570,46 @@ SGVec2d MapWidget::project(const SGGeod& geod) const
         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
@@ -1622,6 +1666,43 @@ SGGeod MapWidget::unproject(const SGVec2d& p) const
         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:
     {
@@ -1647,6 +1728,9 @@ SGGeod MapWidget::unproject(const SGVec2d& p) const
         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
 }
 
@@ -1894,7 +1978,7 @@ MapWidget::DrawAIObject::DrawAIObject(SGPropertyNode* m, const SGGeod& g) :
         // 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());