]> git.mxchange.org Git - flightgear.git/blobdiff - src/Environment/environment_ctrl.cxx
Merge branch 'maint' into next
[flightgear.git] / src / Environment / environment_ctrl.cxx
index 4a5bd263339cac721458b46a1c72b94de163169b..72f6f09794ecf07bb8f231056566abb10a2e8c27 100644 (file)
@@ -24,8 +24,6 @@
 #  include "config.h"
 #endif
 
-#include <stdlib.h>
-#include <math.h>
 #include <algorithm>
 
 #include <simgear/debug/logstream.hxx>
 #include <Main/fg_props.hxx>
 #include <Main/util.hxx>
 
+#include "Environment/fgmetar.hxx"
 #include "environment_mgr.hxx"
 #include "environment_ctrl.hxx"
 
 using std::sort;
 
-class metar_filter : public FGAirportSearchFilter {
-    virtual bool pass(FGAirport *a) { return a->getMetar(); }
-} metar_only;
-
+class AirportWithMetar : public FGAirport::AirportFilter
+{
+public:
+  virtual bool passAirport(FGAirport* aApt) const
+  {
+    return aApt->getMetar();
+  }
+};
 \f
 ////////////////////////////////////////////////////////////////////////
 // Implementation of FGEnvironmentCtrl abstract base class.
@@ -328,7 +331,6 @@ FGInterpolateEnvironmentCtrl::bucket::lessThan(bucket *a, bucket *b)
 
 FGMetarEnvironmentCtrl::FGMetarEnvironmentCtrl ()
     : env( new FGInterpolateEnvironmentCtrl ),
-      _icao( "" ),
       metar_loaded( false ),
       search_interval_sec( 60.0 ),        // 1 minute
       same_station_interval_sec( 900.0 ), // 15 minutes
@@ -407,7 +409,7 @@ FGMetarEnvironmentCtrl::update_env_config ()
     double dewpoint;
     
     // If we aren't in the METAR scenario, don't attempt to interpolate.
-    if (fgGetString("/environment/weather-scenario", "METAR") != "METAR") return;
+    if (strcmp(fgGetString("/environment/weather-scenario", "METAR"), "METAR")) return;
 
     if (metar_loaded) {
         // Generate interpolated values between the METAR and the current
@@ -579,7 +581,7 @@ FGMetarEnvironmentCtrl::update_env_config ()
         dewpoint = fgGetDouble("/environment/metar/dewpoint-degc");
 
         // Set the cloud layers by copying over the METAR versions.
-        SGPropertyNode * clouds = fgGetNode("/environment/metar/clouds");
+        SGPropertyNode * clouds = fgGetNode("/environment/metar/clouds", true);
 
         vector<SGPropertyNode_ptr> layers = clouds->getChildren("layer");
         vector<SGPropertyNode_ptr>::const_iterator layer;
@@ -606,6 +608,9 @@ FGMetarEnvironmentCtrl::update_env_config ()
             strncat(s, "/span-m", 128);
             fgSetDouble(s, 40000.0);
         }
+
+        // Force an update of the 3D clouds
+        fgSetDouble("/environment/rebuild-layers", 1.0);
     }
 
     fgSetupWind(dir_from, dir_to, speed, gust);
@@ -642,10 +647,9 @@ double FGMetarEnvironmentCtrl::interpolate_val(double currentval,
 void
 FGMetarEnvironmentCtrl::init ()
 {
-    const SGPropertyNode *longitude
-        = fgGetNode( "/position/longitude-deg", true );
-    const SGPropertyNode *latitude
-        = fgGetNode( "/position/latitude-deg", true );
+    SGGeod pos = SGGeod::fromDeg(
+      fgGetDouble("/position/longitude-deg", true), 
+      fgGetDouble( "/position/latitude-deg", true));
 
     metar_loaded = false;
     bool found_metar = false;
@@ -656,33 +660,31 @@ FGMetarEnvironmentCtrl::init ()
     metar_max_age->setLongValue(0);
 
     while ( !found_metar && (_error_count < 3) ) {
-        const FGAirport* a = globals->get_airports()
-                   ->search( longitude->getDoubleValue(),
-                             latitude->getDoubleValue(),
-                             360.0,
-                             metar_only );
-        if ( a ) {  
-            FGMetarResult result = fetch_data( a->getId() );
-            if ( result.m != NULL ) {
-                SG_LOG( SG_GENERAL, SG_INFO, "closest station w/ metar = "
-                        << a->getId());
-                last_apt = a;
-                _icao = a->getId();
-                search_elapsed = 0.0;
-                fetch_elapsed = 0.0;
-                update_metar_properties( result.m );
-                update_env_config();
-                env->init();
-                found_metar = true;
-            } else {
-                // mark as no metar so it doesn't show up in subsequent
-                // searches.
-                SG_LOG( SG_GENERAL, SG_INFO, "no metar at metar = "
-                        << a->getId() );
-                globals->get_airports()->no_metar( a->getId() );
-            }
+        AirportWithMetar filter;
+        FGAirport* a = FGAirport::findClosest(pos, 10000.0, &filter);
+        if (!a) {
+          break;
         }
-    }
+        
+        FGMetarResult result = fetch_data(a);
+        if ( result.m != NULL ) {
+            SG_LOG( SG_GENERAL, SG_INFO, "closest station w/ metar = "
+                    << a->ident());
+            last_apt = a;
+            search_elapsed = 0.0;
+            fetch_elapsed = 0.0;
+            update_metar_properties( result.m );
+            update_env_config();
+            env->init();
+            found_metar = true;
+        } else {
+            // mark as no metar so it doesn't show up in subsequent
+            // searches.
+            SG_LOG( SG_GENERAL, SG_INFO, "no metar at metar = " << a->ident() );
+            a->setMetar(false);
+        }
+    } // of airprot-with-metar search iteration
+    
     metar_max_age->setLongValue(max_age);
 }
 
@@ -699,7 +701,6 @@ FGMetarEnvironmentCtrl::reinit ()
 void
 FGMetarEnvironmentCtrl::update(double delta_time_sec)
 {
-
     _dt += delta_time_sec;
     if (_error_count >= 3)
        return;
@@ -710,6 +711,9 @@ FGMetarEnvironmentCtrl::update(double delta_time_sec)
         = fgGetNode( "/position/longitude-deg", true );
     static const SGPropertyNode *latitude
         = fgGetNode( "/position/latitude-deg", true );
+    SGGeod pos = SGGeod::fromDeg(longitude->getDoubleValue(), 
+      latitude->getDoubleValue());
+        
     search_elapsed += delta_time_sec;
     fetch_elapsed += delta_time_sec;
     interpolate_elapsed += delta_time_sec;
@@ -717,20 +721,16 @@ FGMetarEnvironmentCtrl::update(double delta_time_sec)
     // if time for a new search request, push it onto the request
     // queue
     if ( search_elapsed > search_interval_sec ) {
-        const FGAirport* a = globals->get_airports()
-                   ->search( longitude->getDoubleValue(),
-                             latitude->getDoubleValue(),
-                             360.0,
-                             metar_only );
-        if ( a ) {
-            if ( !last_apt || last_apt->getId() != a->getId()
+        AirportWithMetar filter;
+        FGAirport* a = FGAirport::findClosest(pos, 10000.0, &filter);
+        if (a) {
+          if ( !last_apt || last_apt->ident() != a->ident()
                  || fetch_elapsed > same_station_interval_sec )
             {
                 SG_LOG( SG_GENERAL, SG_INFO, "closest station w/ metar = "
-                        << a->getId());
-                request_queue.push( a->getId() );
+                        << a->ident());
+                request_queue.push(a);
                 last_apt = a;
-                _icao = a->getId();
                 search_elapsed = 0.0;
                 fetch_elapsed = 0.0;
             } else {
@@ -738,8 +738,9 @@ FGMetarEnvironmentCtrl::update(double delta_time_sec)
                 SG_LOG( SG_GENERAL, SG_INFO, "same station, waiting = "
                         << same_station_interval_sec - fetch_elapsed );
             }
+
         } else {
-            SG_LOG( SG_GENERAL, SG_WARN,
+          SG_LOG( SG_GENERAL, SG_WARN,
                     "Unable to find any airports with metar" );
         }
     } else if ( interpolate_elapsed > EnvironmentUpdatePeriodSec ) {
@@ -751,15 +752,15 @@ FGMetarEnvironmentCtrl::update(double delta_time_sec)
 
 #if !defined(ENABLE_THREADS)
     // No loader thread running so manually fetch the data
-    string id = "";
+    FGAirport* apt = NULL;
     while ( !request_queue.empty() ) {
-        id = request_queue.front();
+        apt = request_queue.front();
         request_queue.pop();
     }
 
-    if ( !id.empty() ) {
-        SG_LOG( SG_GENERAL, SG_INFO, "inline fetching = " << id );
-        result = fetch_data( id );
+    if (apt) {
+        SG_LOG( SG_GENERAL, SG_INFO, "inline fetching = " << apt->ident() );
+        result = fetch_data( apt );
         result_queue.push( result );
     }
 #endif // ENABLE_THREADS
@@ -777,8 +778,8 @@ FGMetarEnvironmentCtrl::update(double delta_time_sec)
             // mark as no metar so it doesn't show up in subsequent
             // searches, and signal an immediate re-search.
             SG_LOG( SG_GENERAL, SG_WARN,
-                    "no metar at station = " << result.icao );
-            globals->get_airports()->no_metar( result.icao );
+                    "no metar at station = " << result.airport->ident() );
+            result.airport->setMetar(false);
             search_elapsed = 9999.0;
         }
     }
@@ -794,10 +795,10 @@ FGMetarEnvironmentCtrl::setEnvironment (FGEnvironment * environment)
 }
 
 FGMetarResult
-FGMetarEnvironmentCtrl::fetch_data( const string &icao )
+FGMetarEnvironmentCtrl::fetch_data(FGAirport* apt)
 {
     FGMetarResult result;
-    result.icao = icao;
+    result.airport = apt;
 
     // if the last error was more than three seconds ago,
     // then pretent nothing happened.
@@ -809,18 +810,14 @@ FGMetarEnvironmentCtrl::fetch_data( const string &icao )
         _error_count = 0;
     }
 
-    // fetch station elevation if exists
-    const FGAirport* a = globals->get_airports()->search( icao );
-    if ( a ) {
-        station_elevation_ft = a->getElevation();
-    }
+    station_elevation_ft = apt->getElevation();
 
     // fetch current metar data
     try {
         string host = proxy_host->getStringValue();
         string auth = proxy_auth->getStringValue();
         string port = proxy_port->getStringValue();
-        result.m = new FGMetar( icao, host, port, auth);
+        result.m = new FGMetar( apt->ident(), host, port, auth);
 
         long max_age = metar_max_age->getLongValue();
         long age = result.m->getAge_min();
@@ -962,7 +959,7 @@ FGMetarEnvironmentCtrl::update_metar_properties( const FGMetar *m )
 void
 FGMetarEnvironmentCtrl::thread_stop()
 {
-    request_queue.push( string() );    // ask thread to terminate
+    request_queue.push(NULL);  // ask thread to terminate
     thread->join();
 }
 
@@ -971,11 +968,11 @@ FGMetarEnvironmentCtrl::MetarThread::run()
 {
     while ( true )
     {
-        string icao = fetcher->request_queue.pop();
-        if (icao.empty())
+        FGAirport* apt = fetcher->request_queue.pop();
+        if (!apt)
             return;
-        SG_LOG( SG_GENERAL, SG_INFO, "Thread: fetch metar data = " << icao );
-        FGMetarResult result = fetcher->fetch_data( icao );
+        SG_LOG( SG_GENERAL, SG_INFO, "Thread: fetch metar data = " << apt->ident() );
+        FGMetarResult result = fetcher->fetch_data( apt );
         fetcher->result_queue.push( result );
     }
 }