]> git.mxchange.org Git - flightgear.git/blobdiff - src/WeatherCM/FGLocalWeatherDatabase.cpp
Erik Hofman:
[flightgear.git] / src / WeatherCM / FGLocalWeatherDatabase.cpp
index 338b204cb6227a99b3989b74b17e339b278c647f..0ad64b9fa2a0587e266027d622b625fe26d77c0e 100644 (file)
@@ -46,6 +46,8 @@ HISTORY
                                 on 'the bus'
 18.05.2000 Christian Mayer      Minor clean-ups. Changed the code to use 
                                 FGWeatherUtils.h for unit conversion
+18.07.2001 Christian Mayer      Added the posibility to limit the amount of 
+                                stations for a faster init.
 *****************************************************************************/
 
 /****************************************************************************/
@@ -55,6 +57,7 @@ HISTORY
 #include <simgear/constants.h>
 
 #include <Aircraft/aircraft.hxx>
+#include <Main/fg_props.hxx>
 
 #include "FGLocalWeatherDatabase.h"
 
@@ -85,7 +88,7 @@ void FGLocalWeatherDatabase::init( const WeatherPrecision visibility,
     setWeatherVisibility(visibility);
 
     DatabaseStatus = type;
-    database = 0;          //just get sure...
+    database_logic = 0;            //just get sure...
 
     Thunderstorm = false;
     //I don't need to set theThunderstorm as Thunderstorm == false
@@ -102,30 +105,79 @@ void FGLocalWeatherDatabase::init( const WeatherPrecision visibility,
     case use_internet:
        {
            FGWeatherParse *parsed_data = new FGWeatherParse();
-
-           parsed_data->input( "weather/current.gz" );
+           sgVec2       *p;
+            unsigned int *f;
+            string path_to_weather = root + "/weather/current.txt.gz";
+           parsed_data->input( path_to_weather.c_str() );
            unsigned int n = parsed_data->stored_stations();
-
-           sgVec2               *p = new sgVec2              [n];
-           FGPhysicalProperties *f = new FGPhysicalProperties[n];
-
-           // fill the database
-           for (unsigned int i = 0; i < n; i++) 
-           {
-               f[i] = parsed_data->getFGPhysicalProperties(i);
-               parsed_data->getPosition(i, p[i]);
-
-               if ( (i%100) == 0)
-                   cerr << ".";
-           }
+            int m = fgGetInt("/environment/weather/max-stations", -1);
+
+            if ( ( m < 0 ) || ( m > n ) )
+            {
+                m = n;
+
+               p = new sgVec2[n];
+               f = new unsigned int[n];
+
+               // fill the database
+               for (unsigned int i = 0; i < n; i++) 
+               {
+                    f[i] = i;
+                   database_data[i] = parsed_data->getFGPhysicalProperties(i);
+                   parsed_data->getPosition(i, p[i]);
+
+                   if ( (i%100) == 0)
+                       cerr << ".";
+               }
+            }
+            else
+            {   // we have to limit the amount of stations
+
+                //store the "distance" between the station and the current
+                //position. As the distance is calculated from the lat/lon
+                //values it's not worth much - but it's good enough for
+                //comparison
+                map<float, unsigned int> squared_distance;
+                sgVec2 cur_pos;
+
+                cur_pos[0] = cache->last_known_position[0];
+                cur_pos[1] = cache->last_known_position[1];
+                
+                unsigned int i;
+                for( i = 0; i < n; i++ )
+                {
+                  sgVec2 pos;
+                  parsed_data->getPosition(i, pos);
+                  squared_distance[sgDistanceSquaredVec2(cur_pos, pos)] = i;
+                }
+
+                p = new sgVec2      [m];
+                f = new unsigned int[m];
+
+                map<float, unsigned int>::const_iterator ci;
+                ci = squared_distance.begin();
+
+               // fill the database
+               for ( i = 0; i < m; i++ ) 
+                { 
+                    f[i] = i;
+                   database_data.push_back( parsed_data->getFGPhysicalProperties(ci->second) );
+                   parsed_data->getPosition(ci->second, p[i]);
+
+                   if ( (i%100) == 0)
+                       cerr << ".";
+
+                    ci++;
+               }
+            }
 
            // free the memory of the parsed data to ease the required memory
            // for the very memory consuming spherical interpolation
            delete parsed_data;
 
            //and finally init the interpolation
-           cerr << "\nInitialiating Interpolation. (2-3 minutes on a PII-350)\n";
-           database = new SphereInterpolate<FGPhysicalProperties>(n, p, f);
+           cerr << "\nInitialiating Interpolation. (2-3 minutes on a PII-350 for ca. 3500 stations)\n";
+           database_logic = new SphereInterpolate(m, p, f);
 
            //and free my allocations:
            delete[] p;
@@ -145,20 +197,134 @@ void FGLocalWeatherDatabase::init( const WeatherPrecision visibility,
            double x[2] = {0.0,  0.0};  //make an standard weather that's the same at the whole world
            double y[2] = {0.0,  0.0};  //make an standard weather that's the same at the whole world
            double z[2] = {1.0, -1.0};  //make an standard weather that's the same at the whole world
-           FGPhysicalProperties f[2];  //make an standard weather that's the same at the whole world
-           database = new SphereInterpolate<FGPhysicalProperties>(2,x,y,z,f);
+            unsigned int f[2] = {0, 0};
+            database_data.push_back( FGPhysicalProperties() ); // == database_date[0]
+           database_logic = new SphereInterpolate(2,x,y,z,f);
        }
        break;
 
     default:
        cerr << "FGLocalWeatherDatabase error: Unknown database type specified!\n";
     };
+
+    cache->latitude_deg  = fgGetNode("/position/latitude-deg" );
+    cache->longitude_deg = fgGetNode("/position/longitude-deg");
+    cache->altitude_ft   = fgGetNode("/position/altitude-ft"  );
+
+}
+
+void FGLocalWeatherDatabase::bind()
+{
+    fgTie("/environment/weather/wind-north-mps", this, &FGLocalWeatherDatabase::get_wind_north);
+    fgTie("/environment/weather/wind-east-mps", this, &FGLocalWeatherDatabase::get_wind_east);
+    fgTie("/environment/weather/wind-up-mps", this, &FGLocalWeatherDatabase::get_wind_up);
+    fgTie("/environment/weather/temperature-K", this, &FGLocalWeatherDatabase::get_temperature);
+    fgTie("/environment/weather/air-pressure-Pa", this, &FGLocalWeatherDatabase::get_air_pressure);
+    fgTie("/environment/weather/vapor-pressure-Pa", this, &FGLocalWeatherDatabase::get_vapor_pressure);
+    fgTie("/environment/weather/air-density", this, &FGLocalWeatherDatabase::get_air_density);
+    
+
+  SGPropertyNode * station_nodes = fgGetNode("/environment/weather");
+  if (station_nodes == 0) {
+    cerr << "No weatherstations (/environment/weather)!!";
+    return;
+  }
+  
+  int index = 0;
+  for(vector<FGPhysicalProperties>::iterator it = database_data.begin(); it != database_data.end(); it++)
+  {
+      SGPropertyNode * station = station_nodes->getNode("station", index, true);
+
+      station -> tie("air-pressure-Pa", 
+        SGRawValueMethods<FGAirPressureItem,WeatherPrecision>(
+          database_data[0].AirPressure,
+          &FGAirPressureItem::getValue,
+          &FGAirPressureItem::setValue)
+        ,false);
+
+    int i;
+    for( i = 0; i < database_data[index].Wind.size(); i++)
+    {
+      SGPropertyNode * wind = station->getNode("wind", i, true);
+      wind -> tie("north-mps", 
+        SGRawValueMethodsIndexed<FGPhysicalProperties,WeatherPrecision>(
+          database_data[index], i,
+          &FGPhysicalProperties::getWind_x,
+          &FGPhysicalProperties::setWind_x)
+        ,false);
+      wind -> tie("east-mps", 
+        SGRawValueMethodsIndexed<FGPhysicalProperties,WeatherPrecision>(
+          database_data[index], i,
+          &FGPhysicalProperties::getWind_y,
+          &FGPhysicalProperties::setWind_y)
+        ,false);
+      wind -> tie("up-mps", 
+        SGRawValueMethodsIndexed<FGPhysicalProperties,WeatherPrecision>(
+          database_data[index], i,
+          &FGPhysicalProperties::getWind_z,
+          &FGPhysicalProperties::setWind_z)
+        ,false);
+      wind -> tie("altitude-m", 
+        SGRawValueMethodsIndexed<FGPhysicalProperties,WeatherPrecision>(
+          database_data[index], i,
+          &FGPhysicalProperties::getWind_a,
+          &FGPhysicalProperties::setWind_a)
+        ,false);
+    }
+
+    for( i = 0; i < database_data[index].Temperature.size(); i++)
+    {
+      SGPropertyNode * temperature = station->getNode("temperature", i, true);
+      temperature -> tie("value-K", 
+        SGRawValueMethodsIndexed<FGPhysicalProperties,WeatherPrecision>(
+          database_data[index], i,
+          &FGPhysicalProperties::getTemperature_x,
+          &FGPhysicalProperties::setTemperature_x)
+        ,false);
+      temperature -> tie("altitude-m", 
+        SGRawValueMethodsIndexed<FGPhysicalProperties,WeatherPrecision>(
+          database_data[index], i,
+          &FGPhysicalProperties::getTemperature_a,
+          &FGPhysicalProperties::setTemperature_a)
+        ,false);
+    }
+
+    for( i = 0; i < database_data[index].VaporPressure.size(); i++)
+    {
+      SGPropertyNode * vaporpressure = station->getNode("vapor-pressure", i, true);
+      vaporpressure -> tie("value-Pa", 
+        SGRawValueMethodsIndexed<FGPhysicalProperties,WeatherPrecision>(
+          database_data[index], i,
+          &FGPhysicalProperties::getVaporPressure_x,
+          &FGPhysicalProperties::setVaporPressure_x)
+        ,false);
+      vaporpressure -> tie("altitude-m", 
+        SGRawValueMethodsIndexed<FGPhysicalProperties,WeatherPrecision>(
+          database_data[index], i,
+          &FGPhysicalProperties::getVaporPressure_a,
+          &FGPhysicalProperties::setVaporPressure_a)
+        ,false);
+    }
+
+    index++;
+  }
+}
+
+void FGLocalWeatherDatabase::unbind()
+{
+    fgUntie("/environment/weather/wind-north-mps");
+    fgUntie("/environment/weather/wind-east-mps");
+    fgUntie("/environment/weather/wind-up-mps");
+    fgUntie("/environment/weather/temperature-K");
+    fgUntie("/environment/weather/air-pressure-Pa");
+    fgUntie("/environment/weather/vapor-pressure-Pa");
+    fgUntie("/environment/weather/air-density");
 }
 
 FGLocalWeatherDatabase::~FGLocalWeatherDatabase()
 {
     //Tidying up:
-    delete database;
+    delete database_logic;
 }
 
 /****************************************************************************/
@@ -180,14 +346,10 @@ void FGLocalWeatherDatabase::update(const WeatherPrecision dt)
 
 void FGLocalWeatherDatabase::update(const sgVec3& p) //position has changed
 {
-    sgCopyVec3(last_known_position, p);
-
     //uncomment this when you are using the GlobalDatabase
     /*
     cerr << "****\nupdate(p) inside\n";
     cerr << "Parameter: " << p[0] << "/" << p[1] << "/" << p[2] << "\n";
-    sgVec2 p2d;
-    sgSetVec2( p2d, p[0], p[1] );
     cerr << FGPhysicalProperties2D(get(p2d), p2d);
     cerr << "****\n";
     */
@@ -196,7 +358,6 @@ void FGLocalWeatherDatabase::update(const sgVec3& p) //position has changed
 
 void FGLocalWeatherDatabase::update(const sgVec3& p, const WeatherPrecision dt)   //time and/or position has changed
 {
-    sgCopyVec3(last_known_position, p);
 }
 
 /****************************************************************************/
@@ -204,7 +365,12 @@ void FGLocalWeatherDatabase::update(const sgVec3& p, const WeatherPrecision dt)
 /****************************************************************************/
 FGPhysicalProperty FGLocalWeatherDatabase::get(const sgVec3& p) const
 {
-    return FGPhysicalProperty(database->Evaluate(p), p[2]);
+  // check for bogous altitudes. Dunno why, but FGFS want's to know the
+  // weather at an altitude of roughly -3000 meters...
+  if (p[2] < -500.0f)
+    return FGPhysicalProperty(DatabaseEvaluate(p), -500.0f);
+
+  return FGPhysicalProperty(DatabaseEvaluate(p), p[2]);
 }
 
 #ifdef macintosh
@@ -216,13 +382,13 @@ FGPhysicalProperty FGLocalWeatherDatabase::get(const sgVec3& p) const
 #else
 FGPhysicalProperties FGLocalWeatherDatabase::get(const sgVec2& p) const
 {
-    return database->Evaluate(p);
+    return DatabaseEvaluate(p);
 }
 #endif
 
 WeatherPrecision FGLocalWeatherDatabase::getAirDensity(const sgVec3& p) const
 {
-    FGPhysicalProperty dummy(database->Evaluate(p), p[2]);
+    FGPhysicalProperty dummy(DatabaseEvaluate(p), p[2]);
 
     return 
        (dummy.AirPressure*FG_WEATHER_DEFAULT_AIRDENSITY*FG_WEATHER_DEFAULT_TEMPERATURE) / 
@@ -253,8 +419,6 @@ void FGLocalWeatherDatabase::setProperties(const FGPhysicalProperties2D& x)
 void fgUpdateWeatherDatabase(void)
 {
     sgVec3 position;
-    sgVec3 wind;
-    
     
     sgSetVec3(position, 
         current_aircraft.fdm_state->get_Latitude(),